]>
git.proxmox.com Git - mirror_qemu.git/blob - tests/acceptance/virtiofs_submounts.py
7 from avocado
import skipUnless
8 from avocado_qemu
import Test
, BUILD_DIR
9 from avocado_qemu
import wait_for_console_pattern
10 from avocado
.utils
import ssh
12 from qemu
.accel
import kvm_available
14 from boot_linux
import BootLinux
18 subp
= subprocess
.Popen(args
,
19 stdout
=subprocess
.PIPE
,
20 stderr
=subprocess
.PIPE
,
21 universal_newlines
=True)
22 stdout
, stderr
= subp
.communicate()
25 return (stdout
, stderr
, ret
)
27 def has_passwordless_sudo():
29 This function is for use in a @avocado.skipUnless decorator, e.g.:
31 @skipUnless(*has_passwordless_sudo())
32 def test_something_that_needs_sudo(self):
36 _
, stderr
, exitcode
= run_cmd(('sudo', '-n', 'true'))
38 return (False, f
'Failed to use sudo -n: {stderr.strip()}')
43 class VirtiofsSubmountsTest(BootLinux
):
45 :avocado: tags=arch:x86_64
48 def get_portfwd(self
):
51 res
= self
.vm
.command('human-monitor-command',
52 command_line
='info usernet')
53 for line
in res
.split('\r\n'):
55 re
.search(r
'TCP.HOST_FORWARD.*127\.0\.0\.1\s*(\d+)\s+10\.',
61 self
.assertIsNotNone(port
)
62 self
.log
.debug('sshd listening on port: ' + port
)
65 def ssh_connect(self
, username
, keyfile
):
66 self
.ssh_logger
= logging
.getLogger('ssh')
67 port
= self
.get_portfwd()
68 self
.ssh_session
= ssh
.Session('127.0.0.1', port
=int(port
),
69 user
=username
, key
=keyfile
)
72 self
.ssh_session
.connect()
77 self
.fail('sshd timeout')
79 def ssh_command(self
, command
):
80 self
.ssh_logger
.info(command
)
81 result
= self
.ssh_session
.cmd(command
)
82 stdout_lines
= [line
.rstrip() for line
83 in result
.stdout_text
.splitlines()]
84 for line
in stdout_lines
:
85 self
.ssh_logger
.info(line
)
86 stderr_lines
= [line
.rstrip() for line
87 in result
.stderr_text
.splitlines()]
88 for line
in stderr_lines
:
89 self
.ssh_logger
.warning(line
)
91 self
.assertEqual(result
.exit_status
, 0,
92 f
'Guest command failed: {command}')
93 return stdout_lines
, stderr_lines
95 def run(self
, args
, ignore_error
=False):
96 stdout
, stderr
, ret
= run_cmd(args
)
99 cmdline
= ' '.join(args
)
101 self
.fail(f
'{cmdline}: Returned {ret}: {stderr}')
103 self
.log
.warn(f
'{cmdline}: Returned {ret}: {stderr}')
105 return (stdout
, stderr
, ret
)
107 def set_up_shared_dir(self
):
108 atwd
= os
.getenv('AVOCADO_TEST_WORKDIR')
109 self
.shared_dir
= os
.path
.join(atwd
, 'virtiofs-shared')
111 os
.mkdir(self
.shared_dir
)
113 self
.run(('cp', self
.get_data('guest.sh'),
114 os
.path
.join(self
.shared_dir
, 'check.sh')))
116 self
.run(('cp', self
.get_data('guest-cleanup.sh'),
117 os
.path
.join(self
.shared_dir
, 'cleanup.sh')))
119 def set_up_virtiofs(self
):
120 attmp
= os
.getenv('AVOCADO_TESTS_COMMON_TMPDIR')
121 self
.vfsdsock
= os
.path
.join(attmp
, 'vfsdsock')
123 self
.run(('sudo', '-n', 'rm', '-f', self
.vfsdsock
), ignore_error
=True)
126 subprocess
.Popen(('sudo', '-n',
127 'tools/virtiofsd/virtiofsd',
128 f
'--socket-path={self.vfsdsock}',
129 '-o', f
'source={self.shared_dir}',
130 '-o', 'cache=always',
132 '-o', 'announce_submounts',
134 stdout
=subprocess
.DEVNULL
,
135 stderr
=subprocess
.PIPE
,
136 universal_newlines
=True)
138 while not os
.path
.exists(self
.vfsdsock
):
139 if self
.virtiofsd
.poll() is not None:
140 self
.fail('virtiofsd exited prematurely: ' +
141 self
.virtiofsd
.communicate()[1])
144 self
.run(('sudo', '-n', 'chmod', 'go+rw', self
.vfsdsock
))
146 self
.vm
.add_args('-chardev',
147 f
'socket,id=vfsdsock,path={self.vfsdsock}',
149 'vhost-user-fs-pci,queue-size=1024,chardev=vfsdsock' \
152 'memory-backend-file,id=mem,size=1G,' \
153 'mem-path=/dev/shm,share=on',
158 self
.launch_and_wait()
159 self
.ssh_connect('root', self
.ssh_key
)
161 def set_up_nested_mounts(self
):
162 scratch_dir
= os
.path
.join(self
.shared_dir
, 'scratch')
164 os
.mkdir(scratch_dir
)
165 except FileExistsError
:
168 args
= ['bash', self
.get_data('host.sh'), scratch_dir
]
172 out
, _
, _
= self
.run(args
)
173 seed
= re
.search(r
'^Seed: \d+', out
)
174 self
.log
.info(seed
[0])
176 def mount_in_guest(self
):
177 self
.ssh_command('mkdir -p /mnt/host')
178 self
.ssh_command('mount -t virtiofs host /mnt/host')
180 def check_in_guest(self
):
181 self
.ssh_command('bash /mnt/host/check.sh /mnt/host/scratch/share')
183 def live_cleanup(self
):
184 self
.ssh_command('bash /mnt/host/cleanup.sh /mnt/host/scratch')
186 # It would be nice if the above was sufficient to make virtiofsd clear
187 # all references to the mounted directories (so they can be unmounted
188 # on the host), but unfortunately it is not. To do so, we have to
189 # resort to a remount.
190 self
.ssh_command('mount -o remount /mnt/host')
192 scratch_dir
= os
.path
.join(self
.shared_dir
, 'scratch')
193 self
.run(('bash', self
.get_data('cleanup.sh'), scratch_dir
))
195 @skipUnless(*has_passwordless_sudo())
197 vmlinuz
= self
.params
.get('vmlinuz')
199 self
.cancel('vmlinuz parameter not set; you must point it to a '
200 'Linux kernel binary to test (to run this test with ' \
201 'the on-image kernel, set it to an empty string)')
203 self
.seed
= self
.params
.get('seed')
205 atwd
= os
.getenv('AVOCADO_TEST_WORKDIR')
206 self
.ssh_key
= os
.path
.join(atwd
, 'id_ed25519')
208 self
.run(('ssh-keygen', '-t', 'ed25519', '-f', self
.ssh_key
))
210 pubkey
= open(self
.ssh_key
+ '.pub').read()
212 super(VirtiofsSubmountsTest
, self
).setUp(pubkey
)
215 self
.vm
.add_args('-kernel', vmlinuz
,
216 '-append', 'console=ttyS0 root=/dev/sda1')
218 # Allow us to connect to SSH
219 self
.vm
.add_args('-netdev', 'user,id=vnet,hostfwd=:127.0.0.1:0-:22',
220 '-device', 'e1000,netdev=vnet')
222 if not kvm_available(self
.arch
, self
.qemu_bin
):
223 self
.cancel(KVM_NOT_AVAILABLE
)
224 self
.vm
.add_args('-accel', 'kvm')
232 scratch_dir
= os
.path
.join(self
.shared_dir
, 'scratch')
233 self
.run(('bash', self
.get_data('cleanup.sh'), scratch_dir
),
236 def test_pre_virtiofsd_set_up(self
):
237 self
.set_up_shared_dir()
239 self
.set_up_nested_mounts()
241 self
.set_up_virtiofs()
243 self
.mount_in_guest()
244 self
.check_in_guest()
246 def test_pre_launch_set_up(self
):
247 self
.set_up_shared_dir()
248 self
.set_up_virtiofs()
250 self
.set_up_nested_mounts()
253 self
.mount_in_guest()
254 self
.check_in_guest()
256 def test_post_launch_set_up(self
):
257 self
.set_up_shared_dir()
258 self
.set_up_virtiofs()
261 self
.set_up_nested_mounts()
263 self
.mount_in_guest()
264 self
.check_in_guest()
266 def test_post_mount_set_up(self
):
267 self
.set_up_shared_dir()
268 self
.set_up_virtiofs()
270 self
.mount_in_guest()
272 self
.set_up_nested_mounts()
274 self
.check_in_guest()
276 def test_two_runs(self
):
277 self
.set_up_shared_dir()
279 self
.set_up_nested_mounts()
281 self
.set_up_virtiofs()
283 self
.mount_in_guest()
284 self
.check_in_guest()
287 self
.set_up_nested_mounts()
289 self
.check_in_guest()