diff options
Diffstat (limited to 'qa/tasks/nvme_loop.py')
-rw-r--r-- | qa/tasks/nvme_loop.py | 106 |
1 files changed, 106 insertions, 0 deletions
diff --git a/qa/tasks/nvme_loop.py b/qa/tasks/nvme_loop.py new file mode 100644 index 000000000..c9d8f0dc7 --- /dev/null +++ b/qa/tasks/nvme_loop.py @@ -0,0 +1,106 @@ +import contextlib +import logging + +from io import StringIO +from teuthology import misc as teuthology +from teuthology import contextutil +from teuthology.orchestra import run + + +log = logging.getLogger(__name__) + + +@contextlib.contextmanager +def task(ctx, config): + log.info('Setting up nvme_loop on scratch devices...') + host = 'hostnqn' + port = '1' + devs_by_remote = {} + old_scratch_by_remote = {} + for remote, roles in ctx.cluster.remotes.items(): + if remote.is_container: + continue + devs = teuthology.get_scratch_devices(remote) + devs_by_remote[remote] = devs + base = '/sys/kernel/config/nvmet' + remote.run( + args=[ + 'grep', '^nvme_loop', '/proc/modules', run.Raw('||'), + 'sudo', 'modprobe', 'nvme_loop', + run.Raw('&&'), + 'sudo', 'mkdir', '-p', f'{base}/hosts/{host}', + run.Raw('&&'), + 'sudo', 'mkdir', '-p', f'{base}/ports/{port}', + run.Raw('&&'), + 'echo', 'loop', run.Raw('|'), + 'sudo', 'tee', f'{base}/ports/{port}/addr_trtype', + ] + ) + for dev in devs: + short = dev.split('/')[-1] + log.info(f'Connecting nvme_loop {remote.shortname}:{dev}...') + remote.run( + args=[ + 'sudo', 'mkdir', '-p', f'{base}/subsystems/{short}', + run.Raw('&&'), + 'echo', '1', run.Raw('|'), + 'sudo', 'tee', f'{base}/subsystems/{short}/attr_allow_any_host', + run.Raw('&&'), + 'sudo', 'mkdir', '-p', f'{base}/subsystems/{short}/namespaces/1', + run.Raw('&&'), + 'echo', '-n', dev, run.Raw('|'), + 'sudo', 'tee', f'{base}/subsystems/{short}/namespaces/1/device_path', + run.Raw('&&'), + 'echo', '1', run.Raw('|'), + 'sudo', 'tee', f'{base}/subsystems/{short}/namespaces/1/enable', + run.Raw('&&'), + 'sudo', 'ln', '-s', f'{base}/subsystems/{short}', + f'{base}/ports/{port}/subsystems/{short}', + run.Raw('&&'), + 'sudo', 'nvme', 'connect', '-t', 'loop', '-n', short, '-q', host, + ] + ) + + # identify nvme_loops devices + old_scratch_by_remote[remote] = remote.read_file('/scratch_devs') + + with contextutil.safe_while(sleep=1, tries=15) as proceed: + while proceed(): + p = remote.run(args=['sudo', 'nvme', 'list'], stdout=StringIO()) + new_devs = [] + for line in p.stdout.getvalue().splitlines(): + dev, _, vendor = line.split()[0:3] + if dev.startswith('/dev/') and vendor == 'Linux': + new_devs.append(dev) + log.info(f'new_devs {new_devs}') + assert len(new_devs) <= len(devs) + if len(new_devs) == len(devs): + break + + remote.write_file( + path='/scratch_devs', + data='\n'.join(new_devs) + '\n', + sudo=True + ) + + try: + yield + + finally: + for remote, devs in devs_by_remote.items(): + if remote.is_container: + continue + for dev in devs: + short = dev.split('/')[-1] + log.info(f'Disconnecting nvme_loop {remote.shortname}:{dev}...') + remote.run( + args=[ + 'sudo', 'nvme', 'disconnect', '-n', short + ], + check_status=False, + ) + remote.write_file( + path='/scratch_devs', + data=old_scratch_by_remote[remote], + sudo=True + ) |