]>
git.proxmox.com Git - ceph.git/blob - ceph/qa/tasks/rbd_fio.py
2 Long running fio tests on rbd mapped devices for format/features provided in config
3 Many fio parameters can be configured so that this task can be used along with thrash/power-cut tests
4 and exercise IO on full disk for all format/features
5 - This test should not be run on VM due to heavy use of resource
13 from teuthology
.parallel
import parallel
14 from teuthology
import misc
as teuthology
15 from tempfile
import NamedTemporaryFile
16 from teuthology
.orchestra
import run
17 from teuthology
.packaging
import install_package
, remove_package
19 log
= logging
.getLogger(__name__
)
21 @contextlib.contextmanager
22 def task(ctx
, config
):
25 fio-io-size: 100g or 80% or 100m
28 features: [[layering],[striping],[layering,exclusive-lock,object-map]]
29 test-clone-io: 1 #remove this option to not run create rbd clone and not run io on clone
30 io-engine: "sync or rbd or any io-engine"
43 features: [[layering],[striping]]
46 Create rbd image + device and exercise IO for format/features provided in config file
47 Config can be per client or one config can be used for all clients, fio jobs are run in parallel for client provided
51 client_config
= config
['all']
52 clients
= ctx
.cluster
.only(teuthology
.is_type('client'))
53 rbd_test_dir
= teuthology
.get_testdir(ctx
) + "/rbd_fio_test"
54 for remote
,role
in clients
.remotes
.items():
55 if 'client_config' in locals():
57 p
.spawn(run_fio
, remote
, client_config
, rbd_test_dir
)
59 for client_config
in config
:
60 if client_config
in role
:
62 p
.spawn(run_fio
, remote
, config
[client_config
], rbd_test_dir
)
67 def get_ioengine_package_name(ioengine
, remote
):
68 system_type
= teuthology
.get_system_type(remote
)
70 return 'librbd1-devel' if system_type
== 'rpm' else 'librbd-dev'
71 elif ioengine
== 'libaio':
72 return 'libaio-devel' if system_type
== 'rpm' else 'libaio-dev'
77 def run_rbd_map(remote
, image
, iodepth
):
78 iodepth
= max(iodepth
, 128) # RBD_QUEUE_DEPTH_DEFAULT
79 dev
= remote
.sh(['sudo', 'rbd', 'device', 'map', '-o',
80 'queue_depth={}'.format(iodepth
), image
]).rstrip('\n')
81 teuthology
.sudo_write_file(
83 '/sys/block/{}/queue/nr_requests'.format(os
.path
.basename(dev
)),
88 def run_fio(remote
, config
, rbd_test_dir
):
90 create fio config file with options based on above config
91 get the fio from github, generate binary, and use it to run on
92 the generated fio config file
94 fio_config
=NamedTemporaryFile(mode
='w', prefix
='fio_rbd_', dir='/tmp/', delete
=False)
95 fio_config
.write('[global]\n')
96 if config
.get('io-engine'):
97 ioengine
=config
['io-engine']
98 fio_config
.write('ioengine={ioe}\n'.format(ioe
=ioengine
))
100 fio_config
.write('ioengine=sync\n')
103 fio_config
.write('bs={bs}\n'.format(bs
=bs
))
105 fio_config
.write('bs=4k\n')
106 iodepth
= config
.get('io-depth', 2)
107 fio_config
.write('iodepth={iod}\n'.format(iod
=iodepth
))
108 if config
.get('fio-io-size'):
109 size
=config
['fio-io-size']
110 fio_config
.write('size={size}\n'.format(size
=size
))
112 fio_config
.write('size=100m\n')
114 fio_config
.write('time_based\n')
115 if config
.get('runtime'):
116 runtime
=config
['runtime']
117 fio_config
.write('runtime={runtime}\n'.format(runtime
=runtime
))
119 fio_config
.write('runtime=1800\n')
120 fio_config
.write('allow_file_create=0\n')
122 if config
.get('image_size'):
123 image_size
=config
['image_size']
126 features
=[['layering'],['striping'],['exclusive-lock','object-map']]
128 if config
.get('formats'):
129 formats
=config
['formats']
130 if config
.get('features'):
131 features
=config
['features']
132 if config
.get('fio-version'):
133 fio_version
=config
['fio-version']
135 # handle package required for ioengine, if any
137 ioengine_pkg
= get_ioengine_package_name(ioengine
, remote
)
139 install_package(ioengine_pkg
, remote
)
141 fio_config
.write('norandommap\n')
142 if ioengine
== 'rbd':
143 fio_config
.write('clientname=admin\n')
144 fio_config
.write('pool=rbd\n')
145 fio_config
.write('invalidate=0\n')
146 elif ioengine
== 'libaio':
147 fio_config
.write('direct=1\n')
149 for feature
in features
:
150 log
.info("Creating rbd images on {sn}".format(sn
=sn
))
151 feature_name
= '-'.join(feature
)
152 rbd_name
= 'i{i}f{f}{sn}'.format(i
=frmt
,f
=feature_name
,sn
=sn
)
153 rbd_snap_name
= 'i{i}f{f}{sn}@i{i}f{f}{sn}Snap'.format(i
=frmt
,f
=feature_name
,sn
=sn
)
154 rbd_clone_name
= 'i{i}f{f}{sn}Clone'.format(i
=frmt
,f
=feature_name
,sn
=sn
)
155 create_args
=['rbd', 'create',
156 '--size', '{size}'.format(size
=image_size
),
158 '--image-format', '{f}'.format(f
=frmt
)]
159 map(lambda x
: create_args
.extend(['--image-feature', x
]), feature
)
160 if config
.get('thick-provision'):
161 create_args
.append('--thick-provision')
162 remote
.run(args
=create_args
)
163 remote
.run(args
=['rbd', 'info', rbd_name
])
164 if ioengine
!= 'rbd':
165 rbd_dev
= run_rbd_map(remote
, rbd_name
, iodepth
)
166 if config
.get('test-clone-io'):
167 log
.info("Testing clones using fio")
168 remote
.run(args
=['rbd', 'snap', 'create', rbd_snap_name
])
169 remote
.run(args
=['rbd', 'snap', 'protect', rbd_snap_name
])
170 remote
.run(args
=['rbd', 'clone', rbd_snap_name
, rbd_clone_name
])
171 rbd_clone_dev
= run_rbd_map(remote
, rbd_clone_name
, iodepth
)
172 fio_config
.write('[{rbd_dev}]\n'.format(rbd_dev
=rbd_dev
))
175 fio_config
.write('rw={rw}\n'.format(rw
=rw
))
177 fio_config
.write('rw=randrw\n')
178 fio_config
.write('filename={rbd_dev}\n'.format(rbd_dev
=rbd_dev
))
179 if config
.get('test-clone-io'):
180 fio_config
.write('[{rbd_clone_dev}]\n'.format(rbd_clone_dev
=rbd_clone_dev
))
181 fio_config
.write('rw={rw}\n'.format(rw
=rw
))
182 fio_config
.write('filename={rbd_clone_dev}\n'.format(rbd_clone_dev
=rbd_clone_dev
))
184 if config
.get('test-clone-io'):
185 log
.info("Testing clones using fio")
186 remote
.run(args
=['rbd', 'snap', 'create', rbd_snap_name
])
187 remote
.run(args
=['rbd', 'snap', 'protect', rbd_snap_name
])
188 remote
.run(args
=['rbd', 'clone', rbd_snap_name
, rbd_clone_name
])
189 fio_config
.write('[{img_name}]\n'.format(img_name
=rbd_name
))
192 fio_config
.write('rw={rw}\n'.format(rw
=rw
))
194 fio_config
.write('rw=randrw\n')
195 fio_config
.write('rbdname={img_name}\n'.format(img_name
=rbd_name
))
196 if config
.get('test-clone-io'):
197 fio_config
.write('[{clone_img_name}]\n'.format(clone_img_name
=rbd_clone_name
))
198 fio_config
.write('rw={rw}\n'.format(rw
=rw
))
199 fio_config
.write('rbdname={clone_img_name}\n'.format(clone_img_name
=rbd_clone_name
))
203 remote
.put_file(fio_config
.name
,fio_config
.name
)
205 log
.info("Running rbd feature - fio test on {sn}".format(sn
=sn
))
206 fio
= "https://github.com/axboe/fio/archive/fio-" + fio_version
+ ".tar.gz"
207 remote
.run(args
=['mkdir', run
.Raw(rbd_test_dir
),])
208 remote
.run(args
=['cd' , run
.Raw(rbd_test_dir
),
209 run
.Raw(';'), 'wget', fio
, run
.Raw(';'), run
.Raw('tar -xvf fio*tar.gz'), run
.Raw(';'),
210 run
.Raw('cd fio-fio*'), run
.Raw(';'), './configure', run
.Raw(';'), 'make'])
211 remote
.run(args
=['ceph', '-s'])
212 remote
.run(args
=[run
.Raw('{tdir}/fio-fio-{v}/fio --showcmd {f}'.format(tdir
=rbd_test_dir
,v
=fio_version
,f
=fio_config
.name
))])
213 remote
.run(args
=['sudo', run
.Raw('{tdir}/fio-fio-{v}/fio {f}'.format(tdir
=rbd_test_dir
,v
=fio_version
,f
=fio_config
.name
))])
214 remote
.run(args
=['ceph', '-s'])
216 out
= remote
.sh('rbd device list --format=json')
217 mapped_images
= json
.loads(out
)
219 log
.info("Unmapping rbd images on {sn}".format(sn
=sn
))
220 for image
in mapped_images
:
221 remote
.run(args
=['sudo', 'rbd', 'device', 'unmap',
222 str(image
['device'])])
223 log
.info("Cleaning up fio install")
224 remote
.run(args
=['rm','-rf', run
.Raw(rbd_test_dir
)])
226 remove_package(ioengine_pkg
, remote
)