summaryrefslogtreecommitdiffstats
path: root/qa/tasks/nvme_loop.py
diff options
context:
space:
mode:
Diffstat (limited to 'qa/tasks/nvme_loop.py')
-rw-r--r--qa/tasks/nvme_loop.py106
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
+ )