]> git.proxmox.com Git - ceph.git/blame - ceph/qa/tasks/ceph_objectstore_tool.py
import 15.2.0 Octopus source
[ceph.git] / ceph / qa / tasks / ceph_objectstore_tool.py
CommitLineData
7c673cae
FG
1"""
2ceph_objectstore_tool - Simple test of ceph-objectstore-tool utility
3"""
9f95a23c
TL
4from io import BytesIO
5
7c673cae
FG
6import contextlib
7import logging
8import ceph_manager
9from teuthology import misc as teuthology
10import time
11import os
9f95a23c 12import six
7c673cae
FG
13import string
14from teuthology.orchestra import run
15import sys
16import tempfile
17import json
9f95a23c
TL
18
19from teuthology.exceptions import CommandFailedError
20
7c673cae
FG
21from util.rados import (rados, create_replicated_pool, create_ec_pool)
22# from util.rados import (rados, create_ec_pool,
23# create_replicated_pool,
24# create_cache_pool)
25
26log = logging.getLogger(__name__)
27
28# Should get cluster name "ceph" from somewhere
29# and normal path from osd_data and osd_journal in conf
30FSPATH = "/var/lib/ceph/osd/ceph-{id}"
31JPATH = "/var/lib/ceph/osd/ceph-{id}/journal"
32
33
34def cod_setup_local_data(log, ctx, NUM_OBJECTS, DATADIR,
35 BASE_NAME, DATALINECOUNT):
36 objects = range(1, NUM_OBJECTS + 1)
37 for i in objects:
38 NAME = BASE_NAME + "{num}".format(num=i)
39 LOCALNAME = os.path.join(DATADIR, NAME)
40
41 dataline = range(DATALINECOUNT)
42 fd = open(LOCALNAME, "w")
43 data = "This is the data for " + NAME + "\n"
44 for _ in dataline:
45 fd.write(data)
46 fd.close()
47
48
49def cod_setup_remote_data(log, ctx, remote, NUM_OBJECTS, DATADIR,
50 BASE_NAME, DATALINECOUNT):
51
52 objects = range(1, NUM_OBJECTS + 1)
53 for i in objects:
54 NAME = BASE_NAME + "{num}".format(num=i)
55 DDNAME = os.path.join(DATADIR, NAME)
56
57 remote.run(args=['rm', '-f', DDNAME])
58
59 dataline = range(DATALINECOUNT)
60 data = "This is the data for " + NAME + "\n"
61 DATA = ""
62 for _ in dataline:
63 DATA += data
64 teuthology.write_file(remote, DDNAME, DATA)
65
66
67def cod_setup(log, ctx, remote, NUM_OBJECTS, DATADIR,
68 BASE_NAME, DATALINECOUNT, POOL, db, ec):
69 ERRORS = 0
70 log.info("Creating {objs} objects in pool".format(objs=NUM_OBJECTS))
71
72 objects = range(1, NUM_OBJECTS + 1)
73 for i in objects:
74 NAME = BASE_NAME + "{num}".format(num=i)
75 DDNAME = os.path.join(DATADIR, NAME)
76
77 proc = rados(ctx, remote, ['-p', POOL, 'put', NAME, DDNAME],
78 wait=False)
79 # proc = remote.run(args=['rados', '-p', POOL, 'put', NAME, DDNAME])
80 ret = proc.wait()
81 if ret != 0:
82 log.critical("Rados put failed with status {ret}".
83 format(ret=proc.exitstatus))
84 sys.exit(1)
85
86 db[NAME] = {}
87
88 keys = range(i)
89 db[NAME]["xattr"] = {}
90 for k in keys:
91 if k == 0:
92 continue
93 mykey = "key{i}-{k}".format(i=i, k=k)
94 myval = "val{i}-{k}".format(i=i, k=k)
95 proc = remote.run(args=['rados', '-p', POOL, 'setxattr',
96 NAME, mykey, myval])
97 ret = proc.wait()
98 if ret != 0:
99 log.error("setxattr failed with {ret}".format(ret=ret))
100 ERRORS += 1
101 db[NAME]["xattr"][mykey] = myval
102
103 # Erasure coded pools don't support omap
104 if ec:
105 continue
106
107 # Create omap header in all objects but REPobject1
108 if i != 1:
109 myhdr = "hdr{i}".format(i=i)
110 proc = remote.run(args=['rados', '-p', POOL, 'setomapheader',
111 NAME, myhdr])
112 ret = proc.wait()
113 if ret != 0:
114 log.critical("setomapheader failed with {ret}".format(ret=ret))
115 ERRORS += 1
116 db[NAME]["omapheader"] = myhdr
117
118 db[NAME]["omap"] = {}
119 for k in keys:
120 if k == 0:
121 continue
122 mykey = "okey{i}-{k}".format(i=i, k=k)
123 myval = "oval{i}-{k}".format(i=i, k=k)
124 proc = remote.run(args=['rados', '-p', POOL, 'setomapval',
125 NAME, mykey, myval])
126 ret = proc.wait()
127 if ret != 0:
128 log.critical("setomapval failed with {ret}".format(ret=ret))
129 db[NAME]["omap"][mykey] = myval
130
131 return ERRORS
132
133
134def get_lines(filename):
135 tmpfd = open(filename, "r")
136 line = True
137 lines = []
138 while line:
139 line = tmpfd.readline().rstrip('\n')
140 if line:
141 lines += [line]
142 tmpfd.close()
143 os.unlink(filename)
144 return lines
145
146
147@contextlib.contextmanager
148def task(ctx, config):
149 """
150 Run ceph_objectstore_tool test
151
152 The config should be as follows::
153
154 ceph_objectstore_tool:
155 objects: 20 # <number of objects>
156 pgnum: 12
157 """
158
159 if config is None:
160 config = {}
161 assert isinstance(config, dict), \
162 'ceph_objectstore_tool task only accepts a dict for configuration'
163
164 log.info('Beginning ceph_objectstore_tool...')
165
166 log.debug(config)
167 log.debug(ctx)
168 clients = ctx.cluster.only(teuthology.is_type('client'))
169 assert len(clients.remotes) > 0, 'Must specify at least 1 client'
170 (cli_remote, _) = clients.remotes.popitem()
171 log.debug(cli_remote)
172
173 # clients = dict(teuthology.get_clients(ctx=ctx, roles=config.keys()))
174 # client = clients.popitem()
175 # log.info(client)
176 osds = ctx.cluster.only(teuthology.is_type('osd'))
177 log.info("OSDS")
178 log.info(osds)
179 log.info(osds.remotes)
180
181 manager = ctx.managers['ceph']
182 while (len(manager.get_osd_status()['up']) !=
183 len(manager.get_osd_status()['raw'])):
184 time.sleep(10)
185 while (len(manager.get_osd_status()['in']) !=
186 len(manager.get_osd_status()['up'])):
187 time.sleep(10)
188 manager.raw_cluster_cmd('osd', 'set', 'noout')
189 manager.raw_cluster_cmd('osd', 'set', 'nodown')
190
191 PGNUM = config.get('pgnum', 12)
192 log.info("pgnum: {num}".format(num=PGNUM))
193
194 ERRORS = 0
195
196 REP_POOL = "rep_pool"
197 REP_NAME = "REPobject"
198 create_replicated_pool(cli_remote, REP_POOL, PGNUM)
199 ERRORS += test_objectstore(ctx, config, cli_remote, REP_POOL, REP_NAME)
200
201 EC_POOL = "ec_pool"
202 EC_NAME = "ECobject"
203 create_ec_pool(cli_remote, EC_POOL, 'default', PGNUM)
204 ERRORS += test_objectstore(ctx, config, cli_remote,
205 EC_POOL, EC_NAME, ec=True)
206
207 if ERRORS == 0:
208 log.info("TEST PASSED")
209 else:
210 log.error("TEST FAILED WITH {errcount} ERRORS".format(errcount=ERRORS))
211
212 assert ERRORS == 0
213
214 try:
215 yield
216 finally:
217 log.info('Ending ceph_objectstore_tool')
218
219
220def test_objectstore(ctx, config, cli_remote, REP_POOL, REP_NAME, ec=False):
221 manager = ctx.managers['ceph']
222
223 osds = ctx.cluster.only(teuthology.is_type('osd'))
224
225 TEUTHDIR = teuthology.get_testdir(ctx)
226 DATADIR = os.path.join(TEUTHDIR, "ceph.data")
227 DATALINECOUNT = 10000
228 ERRORS = 0
229 NUM_OBJECTS = config.get('objects', 10)
230 log.info("objects: {num}".format(num=NUM_OBJECTS))
231
232 pool_dump = manager.get_pool_dump(REP_POOL)
233 REPID = pool_dump['pool']
234
235 log.debug("repid={num}".format(num=REPID))
236
237 db = {}
238
239 LOCALDIR = tempfile.mkdtemp("cod")
240
241 cod_setup_local_data(log, ctx, NUM_OBJECTS, LOCALDIR,
242 REP_NAME, DATALINECOUNT)
243 allremote = []
244 allremote.append(cli_remote)
245 allremote += osds.remotes.keys()
246 allremote = list(set(allremote))
247 for remote in allremote:
248 cod_setup_remote_data(log, ctx, remote, NUM_OBJECTS, DATADIR,
249 REP_NAME, DATALINECOUNT)
250
251 ERRORS += cod_setup(log, ctx, cli_remote, NUM_OBJECTS, DATADIR,
252 REP_NAME, DATALINECOUNT, REP_POOL, db, ec)
253
254 pgs = {}
255 for stats in manager.get_pg_stats():
256 if stats["pgid"].find(str(REPID) + ".") != 0:
257 continue
9f95a23c 258 if pool_dump["type"] == ceph_manager.PoolType.REPLICATED:
7c673cae
FG
259 for osd in stats["acting"]:
260 pgs.setdefault(osd, []).append(stats["pgid"])
9f95a23c 261 elif pool_dump["type"] == ceph_manager.PoolType.ERASURE_CODED:
7c673cae
FG
262 shard = 0
263 for osd in stats["acting"]:
264 pgs.setdefault(osd, []).append("{pgid}s{shard}".
265 format(pgid=stats["pgid"],
266 shard=shard))
267 shard += 1
268 else:
269 raise Exception("{pool} has an unexpected type {type}".
270 format(pool=REP_POOL, type=pool_dump["type"]))
271
272 log.info(pgs)
273 log.info(db)
274
275 for osd in manager.get_osd_status()['up']:
276 manager.kill_osd(osd)
277 time.sleep(5)
278
279 pgswithobjects = set()
280 objsinpg = {}
281
282 # Test --op list and generate json for all objects
283 log.info("Test --op list by generating json for all objects")
284 prefix = ("sudo ceph-objectstore-tool "
285 "--data-path {fpath} "
286 "--journal-path {jpath} ").format(fpath=FSPATH, jpath=JPATH)
9f95a23c 287 for remote in osds.remotes.keys():
7c673cae
FG
288 log.debug(remote)
289 log.debug(osds.remotes[remote])
290 for role in osds.remotes[remote]:
291 if string.find(role, "osd.") != 0:
292 continue
293 osdid = int(role.split('.')[1])
294 log.info("process osd.{id} on {remote}".
295 format(id=osdid, remote=remote))
296 cmd = (prefix + "--op list").format(id=osdid)
9f95a23c
TL
297 try:
298 lines = remote.sh(cmd, check_status=False).splitlines()
299 for pgline in lines:
7c673cae
FG
300 if not pgline:
301 continue
302 (pg, obj) = json.loads(pgline)
303 name = obj['oid']
304 if name in db:
305 pgswithobjects.add(pg)
306 objsinpg.setdefault(pg, []).append(name)
307 db[name].setdefault("pg2json",
308 {})[pg] = json.dumps(obj)
9f95a23c
TL
309 except CommandFailedError as e:
310 log.error("Bad exit status {ret} from --op list request".
311 format(ret=e.exitstatus))
312 ERRORS += 1
7c673cae
FG
313
314 log.info(db)
315 log.info(pgswithobjects)
316 log.info(objsinpg)
317
9f95a23c 318 if pool_dump["type"] == ceph_manager.PoolType.REPLICATED:
7c673cae
FG
319 # Test get-bytes
320 log.info("Test get-bytes and set-bytes")
321 for basename in db.keys():
322 file = os.path.join(DATADIR, basename)
323 GETNAME = os.path.join(DATADIR, "get")
324 SETNAME = os.path.join(DATADIR, "set")
325
9f95a23c 326 for remote in osds.remotes.keys():
7c673cae
FG
327 for role in osds.remotes[remote]:
328 if string.find(role, "osd.") != 0:
329 continue
330 osdid = int(role.split('.')[1])
331 if osdid not in pgs:
332 continue
333
9f95a23c 334 for pg, JSON in db[basename]["pg2json"].items():
7c673cae
FG
335 if pg in pgs[osdid]:
336 cmd = ((prefix + "--pgid {pg}").
337 format(id=osdid, pg=pg).split())
338 cmd.append(run.Raw("'{json}'".format(json=JSON)))
339 cmd += ("get-bytes {fname}".
340 format(fname=GETNAME).split())
341 proc = remote.run(args=cmd, check_status=False)
342 if proc.exitstatus != 0:
343 remote.run(args="rm -f {getfile}".
344 format(getfile=GETNAME).split())
345 log.error("Bad exit status {ret}".
346 format(ret=proc.exitstatus))
347 ERRORS += 1
348 continue
349 cmd = ("diff -q {file} {getfile}".
350 format(file=file, getfile=GETNAME))
351 proc = remote.run(args=cmd.split())
352 if proc.exitstatus != 0:
353 log.error("Data from get-bytes differ")
354 # log.debug("Got:")
355 # cat_file(logging.DEBUG, GETNAME)
356 # log.debug("Expected:")
357 # cat_file(logging.DEBUG, file)
358 ERRORS += 1
359 remote.run(args="rm -f {getfile}".
360 format(getfile=GETNAME).split())
361
362 data = ("put-bytes going into {file}\n".
363 format(file=file))
364 teuthology.write_file(remote, SETNAME, data)
365 cmd = ((prefix + "--pgid {pg}").
366 format(id=osdid, pg=pg).split())
367 cmd.append(run.Raw("'{json}'".format(json=JSON)))
368 cmd += ("set-bytes {fname}".
369 format(fname=SETNAME).split())
370 proc = remote.run(args=cmd, check_status=False)
371 proc.wait()
372 if proc.exitstatus != 0:
373 log.info("set-bytes failed for object {obj} "
374 "in pg {pg} osd.{id} ret={ret}".
375 format(obj=basename, pg=pg,
376 id=osdid, ret=proc.exitstatus))
377 ERRORS += 1
378
379 cmd = ((prefix + "--pgid {pg}").
380 format(id=osdid, pg=pg).split())
381 cmd.append(run.Raw("'{json}'".format(json=JSON)))
382 cmd += "get-bytes -".split()
9f95a23c
TL
383 try:
384 output = remote.sh(cmd, wait=True)
385 if data != output:
7c673cae
FG
386 log.error("Data inconsistent after "
387 "set-bytes, got:")
9f95a23c 388 log.error(output)
7c673cae 389 ERRORS += 1
9f95a23c
TL
390 except CommandFailedError as e:
391 log.error("get-bytes after "
392 "set-bytes ret={ret}".
393 format(ret=e.exitstatus))
394 ERRORS += 1
7c673cae
FG
395
396 cmd = ((prefix + "--pgid {pg}").
397 format(id=osdid, pg=pg).split())
398 cmd.append(run.Raw("'{json}'".format(json=JSON)))
399 cmd += ("set-bytes {fname}".
400 format(fname=file).split())
401 proc = remote.run(args=cmd, check_status=False)
402 proc.wait()
403 if proc.exitstatus != 0:
404 log.info("set-bytes failed for object {obj} "
405 "in pg {pg} osd.{id} ret={ret}".
406 format(obj=basename, pg=pg,
407 id=osdid, ret=proc.exitstatus))
408 ERRORS += 1
409
410 log.info("Test list-attrs get-attr")
411 for basename in db.keys():
412 file = os.path.join(DATADIR, basename)
413 GETNAME = os.path.join(DATADIR, "get")
414 SETNAME = os.path.join(DATADIR, "set")
415
9f95a23c 416 for remote in osds.remotes.keys():
7c673cae
FG
417 for role in osds.remotes[remote]:
418 if string.find(role, "osd.") != 0:
419 continue
420 osdid = int(role.split('.')[1])
421 if osdid not in pgs:
422 continue
423
9f95a23c 424 for pg, JSON in db[basename]["pg2json"].items():
7c673cae
FG
425 if pg in pgs[osdid]:
426 cmd = ((prefix + "--pgid {pg}").
427 format(id=osdid, pg=pg).split())
428 cmd.append(run.Raw("'{json}'".format(json=JSON)))
429 cmd += ["list-attrs"]
9f95a23c
TL
430 try:
431 keys = remote.sh(cmd, wait=True, stderr=BytesIO()).split()
432 except CommandFailedError as e:
7c673cae 433 log.error("Bad exit status {ret}".
9f95a23c 434 format(ret=e.exitstatus))
7c673cae
FG
435 ERRORS += 1
436 continue
7c673cae
FG
437 values = dict(db[basename]["xattr"])
438
439 for key in keys:
440 if (key == "_" or
441 key == "snapset" or
442 key == "hinfo_key"):
443 continue
444 key = key.strip("_")
445 if key not in values:
446 log.error("The key {key} should be present".
447 format(key=key))
448 ERRORS += 1
449 continue
450 exp = values.pop(key)
451 cmd = ((prefix + "--pgid {pg}").
452 format(id=osdid, pg=pg).split())
453 cmd.append(run.Raw("'{json}'".format(json=JSON)))
454 cmd += ("get-attr {key}".
455 format(key="_" + key).split())
9f95a23c
TL
456 try:
457 val = remote.sh(cmd, wait=True)
458 except CommandFailedError as e:
7c673cae 459 log.error("get-attr failed with {ret}".
9f95a23c 460 format(ret=e.exitstatus))
7c673cae
FG
461 ERRORS += 1
462 continue
7c673cae
FG
463 if exp != val:
464 log.error("For key {key} got value {got} "
465 "instead of {expected}".
466 format(key=key, got=val,
467 expected=exp))
468 ERRORS += 1
469 if "hinfo_key" in keys:
470 cmd_prefix = prefix.format(id=osdid)
471 cmd = """
472 expected=$({prefix} --pgid {pg} '{json}' get-attr {key} | base64)
473 echo placeholder | {prefix} --pgid {pg} '{json}' set-attr {key} -
474 test $({prefix} --pgid {pg} '{json}' get-attr {key}) = placeholder
475 echo $expected | base64 --decode | \
476 {prefix} --pgid {pg} '{json}' set-attr {key} -
477 test $({prefix} --pgid {pg} '{json}' get-attr {key} | base64) = $expected
478 """.format(prefix=cmd_prefix, pg=pg, json=JSON,
479 key="hinfo_key")
480 log.debug(cmd)
481 proc = remote.run(args=['bash', '-e', '-x',
482 '-c', cmd],
483 check_status=False,
9f95a23c
TL
484 stdout=BytesIO(),
485 stderr=BytesIO())
7c673cae
FG
486 proc.wait()
487 if proc.exitstatus != 0:
488 log.error("failed with " +
489 str(proc.exitstatus))
9f95a23c
TL
490 log.error(" ".join([
491 six.ensure_str(proc.stdout.getvalue()),
492 six.ensure_str(proc.stderr.getvalue()),
493 ]))
7c673cae
FG
494 ERRORS += 1
495
496 if len(values) != 0:
497 log.error("Not all keys found, remaining keys:")
498 log.error(values)
499
500 log.info("Test pg info")
9f95a23c 501 for remote in osds.remotes.keys():
7c673cae
FG
502 for role in osds.remotes[remote]:
503 if string.find(role, "osd.") != 0:
504 continue
505 osdid = int(role.split('.')[1])
506 if osdid not in pgs:
507 continue
508
509 for pg in pgs[osdid]:
510 cmd = ((prefix + "--op info --pgid {pg}").
511 format(id=osdid, pg=pg).split())
9f95a23c
TL
512 try:
513 info = remote.sh(cmd, wait=True)
514 except CommandFailedError as e:
7c673cae 515 log.error("Failure of --op info command with {ret}".
9f95a23c 516 format(e.exitstatus))
7c673cae
FG
517 ERRORS += 1
518 continue
7c673cae
FG
519 if not str(pg) in info:
520 log.error("Bad data from info: {info}".format(info=info))
521 ERRORS += 1
522
523 log.info("Test pg logging")
9f95a23c 524 for remote in osds.remotes.keys():
7c673cae
FG
525 for role in osds.remotes[remote]:
526 if string.find(role, "osd.") != 0:
527 continue
528 osdid = int(role.split('.')[1])
529 if osdid not in pgs:
530 continue
531
532 for pg in pgs[osdid]:
533 cmd = ((prefix + "--op log --pgid {pg}").
534 format(id=osdid, pg=pg).split())
9f95a23c
TL
535 try:
536 output = remote.sh(cmd, wait=True)
537 except CommandFailedError as e:
7c673cae
FG
538 log.error("Getting log failed for pg {pg} "
539 "from osd.{id} with {ret}".
9f95a23c 540 format(pg=pg, id=osdid, ret=e.exitstatus))
7c673cae
FG
541 ERRORS += 1
542 continue
543 HASOBJ = pg in pgswithobjects
9f95a23c 544 MODOBJ = "modify" in output
7c673cae
FG
545 if HASOBJ != MODOBJ:
546 log.error("Bad log for pg {pg} from osd.{id}".
547 format(pg=pg, id=osdid))
548 MSG = (HASOBJ and [""] or ["NOT "])[0]
549 log.error("Log should {msg}have a modify entry".
550 format(msg=MSG))
551 ERRORS += 1
552
553 log.info("Test pg export")
554 EXP_ERRORS = 0
9f95a23c 555 for remote in osds.remotes.keys():
7c673cae
FG
556 for role in osds.remotes[remote]:
557 if string.find(role, "osd.") != 0:
558 continue
559 osdid = int(role.split('.')[1])
560 if osdid not in pgs:
561 continue
562
563 for pg in pgs[osdid]:
564 fpath = os.path.join(DATADIR, "osd{id}.{pg}".
565 format(id=osdid, pg=pg))
566
567 cmd = ((prefix + "--op export --pgid {pg} --file {file}").
568 format(id=osdid, pg=pg, file=fpath))
9f95a23c
TL
569 try:
570 remote.sh(cmd, wait=True)
571 except CommandFailedError as e:
7c673cae
FG
572 log.error("Exporting failed for pg {pg} "
573 "on osd.{id} with {ret}".
9f95a23c 574 format(pg=pg, id=osdid, ret=e.exitstatus))
7c673cae
FG
575 EXP_ERRORS += 1
576
577 ERRORS += EXP_ERRORS
578
579 log.info("Test pg removal")
580 RM_ERRORS = 0
9f95a23c 581 for remote in osds.remotes.keys():
7c673cae
FG
582 for role in osds.remotes[remote]:
583 if string.find(role, "osd.") != 0:
584 continue
585 osdid = int(role.split('.')[1])
586 if osdid not in pgs:
587 continue
588
589 for pg in pgs[osdid]:
3efd9988 590 cmd = ((prefix + "--force --op remove --pgid {pg}").
7c673cae 591 format(pg=pg, id=osdid))
9f95a23c
TL
592 try:
593 remote.sh(cmd, wait=True)
594 except CommandFailedError as e:
7c673cae
FG
595 log.error("Removing failed for pg {pg} "
596 "on osd.{id} with {ret}".
9f95a23c 597 format(pg=pg, id=osdid, ret=e.exitstatus))
7c673cae
FG
598 RM_ERRORS += 1
599
600 ERRORS += RM_ERRORS
601
602 IMP_ERRORS = 0
603 if EXP_ERRORS == 0 and RM_ERRORS == 0:
604 log.info("Test pg import")
605
9f95a23c 606 for remote in osds.remotes.keys():
7c673cae
FG
607 for role in osds.remotes[remote]:
608 if string.find(role, "osd.") != 0:
609 continue
610 osdid = int(role.split('.')[1])
611 if osdid not in pgs:
612 continue
613
614 for pg in pgs[osdid]:
615 fpath = os.path.join(DATADIR, "osd{id}.{pg}".
616 format(id=osdid, pg=pg))
617
618 cmd = ((prefix + "--op import --file {file}").
619 format(id=osdid, file=fpath))
9f95a23c
TL
620 try:
621 remote.sh(cmd, wait=True)
622 except CommandFailedError as e:
7c673cae 623 log.error("Import failed from {file} with {ret}".
9f95a23c 624 format(file=fpath, ret=e.exitstatus))
7c673cae
FG
625 IMP_ERRORS += 1
626 else:
627 log.warning("SKIPPING IMPORT TESTS DUE TO PREVIOUS FAILURES")
628
629 ERRORS += IMP_ERRORS
630
631 if EXP_ERRORS == 0 and RM_ERRORS == 0 and IMP_ERRORS == 0:
632 log.info("Restarting OSDs....")
633 # They are still look to be up because of setting nodown
634 for osd in manager.get_osd_status()['up']:
635 manager.revive_osd(osd)
636 # Wait for health?
637 time.sleep(5)
638 # Let scrub after test runs verify consistency of all copies
639 log.info("Verify replicated import data")
640 objects = range(1, NUM_OBJECTS + 1)
641 for i in objects:
642 NAME = REP_NAME + "{num}".format(num=i)
643 TESTNAME = os.path.join(DATADIR, "gettest")
644 REFNAME = os.path.join(DATADIR, NAME)
645
646 proc = rados(ctx, cli_remote,
647 ['-p', REP_POOL, 'get', NAME, TESTNAME], wait=False)
648
649 ret = proc.wait()
650 if ret != 0:
651 log.error("After import, rados get failed with {ret}".
652 format(ret=proc.exitstatus))
653 ERRORS += 1
654 continue
655
656 cmd = "diff -q {gettest} {ref}".format(gettest=TESTNAME,
657 ref=REFNAME)
658 proc = cli_remote.run(args=cmd, check_status=False)
659 proc.wait()
660 if proc.exitstatus != 0:
661 log.error("Data comparison failed for {obj}".format(obj=NAME))
662 ERRORS += 1
663
664 return ERRORS