def _convert_and_check(self, chunk_volume, chunk_path, chunk_id_info, expected_raw_meta=None, expected_errors=0): conf = self.conf conf['volume'] = self.rawx_volumes[chunk_volume] converter = BlobConverter(conf, logger=self.logger) converter.safe_convert_chunk(chunk_path) self.assertEqual(1, converter.total_chunks_processed) self.assertEqual(1, converter.passes) self.assertEqual(expected_errors, converter.errors) checker = Checker(self.ns) for chunk_id, info in chunk_id_info.items(): account, container, path, version, content_id = info fullpath = encode_fullpath(account, container, path, version, content_id) cid = cid_from_name(account, container) meta, raw_meta = read_chunk_metadata(chunk_path, chunk_id) self.assertEqual(meta.get('chunk_id'), chunk_id) self.assertEqual(meta.get('container_id'), cid) self.assertEqual(meta.get('content_path'), path) self.assertEqual(meta.get('content_version'), version) self.assertEqual(meta.get('content_id'), content_id) self.assertEqual(meta.get('full_path'), fullpath) checker.check( Target(account, container=container, obj=path, chunk='http://' + converter.volume_id + '/' + chunk_id)) for _ in checker.run(): pass self.assertTrue(checker.report()) if expected_raw_meta: self.assertDictEqual(expected_raw_meta, raw_meta) continue self.assertNotIn(CHUNK_XATTR_KEYS['chunk_id'], raw_meta) self.assertNotIn(CHUNK_XATTR_KEYS['container_id'], raw_meta) self.assertNotIn(CHUNK_XATTR_KEYS['content_path'], raw_meta) self.assertNotIn(CHUNK_XATTR_KEYS['content_version'], raw_meta) self.assertNotIn(CHUNK_XATTR_KEYS['content_id'], raw_meta) self.assertIn(CHUNK_XATTR_CONTENT_FULLPATH_PREFIX + chunk_id, raw_meta) for k in raw_meta.keys(): if k.startswith('oio:'): self.fail('old fullpath always existing') self.assertEqual(raw_meta[CHUNK_XATTR_KEYS['oio_version']], OIO_VERSION)
class TestIntegrityCrawler(BaseTestCase): def setUp(self): super(TestIntegrityCrawler, self).setUp() self.container = 'ct-' + random_str(8) self.obj = 'obj-' + random_str(8) self.account = 'test-integrity-' + random_str(8) self.storage.object_create(self.account, self.container, obj_name=self.obj, data="chunk") _, self.rebuild_file = tempfile.mkstemp() self.checker = Checker(self.ns, rebuild_file=self.rebuild_file) self.meta, chunks = self.storage.object_locate(self.account, self.container, self.obj) self.chunk = chunks[0] self.irreparable = len(chunks) == 1 self.storage.blob_client.chunk_delete(self.chunk['real_url']) def tearDown(self): super(TestIntegrityCrawler, self).tearDown() os.remove(self.rebuild_file) self.storage.container_flush(self.account, self.container) self.storage.container_delete(self.account, self.container) self.wait_for_event('oio-preserved', type_=EventTypes.CONTAINER_DELETED, fields={'user': self.container}) self.storage.account_delete(self.account) def _verify_rebuilder_input(self): try: line = fileinput.input(self.rebuild_file).next().strip() cid = cid_from_name(self.account, self.container) expected = '|'.join([cid, self.meta['id'], self.chunk['url']]) if self.irreparable: expected = IRREPARABLE_PREFIX + '|' + expected self.assertEqual(expected, line) finally: fileinput.close() def test_account_rebuilder_output(self): self.checker.check(Target(self.account), recurse=DEFAULT_DEPTH) for _ in self.checker.run(): pass self.checker.fd.flush() self._verify_rebuilder_input() def test_container_rebuilder_output(self): self.checker.check(Target(self.account, container=self.container), recurse=DEFAULT_DEPTH) for _ in self.checker.run(): pass self.checker.fd.flush() self._verify_rebuilder_input() def test_object_rebuilder_output(self): self.checker.check(Target(self.account, container=self.container, obj=self.obj), recurse=DEFAULT_DEPTH) for _ in self.checker.run(): pass self.checker.fd.flush() self._verify_rebuilder_input() def test_object_rebuilder_output_with_confirmations(self): """ Check that chunk targets showing errors are reported only after the right number of confirmations. """ self.checker.required_confirmations = 2 tgt = Target(self.account, container=self.container, obj=self.obj, content_id=self.meta['id'], version=self.meta['version']) self.checker.check(tgt, recurse=DEFAULT_DEPTH) for _ in self.checker.run(): pass self.checker.fd.flush() # File is empty self.assertRaises(StopIteration, self._verify_rebuilder_input) self.assertIn(repr(tgt), self.checker.delayed_targets) # 1st confirmation for dtgt in self.checker.delayed_targets.values(): self.checker.check(dtgt, recurse=DEFAULT_DEPTH) for _ in self.checker.run(): pass self.checker.fd.flush() # File is empty self.assertRaises(StopIteration, self._verify_rebuilder_input) self.assertIn(repr(tgt), self.checker.delayed_targets) # 2nd confirmation for dtgt in self.checker.delayed_targets.values(): self.checker.check(dtgt, recurse=DEFAULT_DEPTH) for _ in self.checker.run(): pass self.checker.fd.flush() # File is NOT empty self._verify_rebuilder_input() self.assertNotIn(repr(tgt), self.checker.delayed_targets)
class TestIntegrityCrawler(BaseTestCase): def setUp(self): super(TestIntegrityCrawler, self).setUp() self.container = 'ct-' + random_str(8) self.obj = 'obj-' + random_str(8) self.account = 'test-integrity-' + random_str(8) self.storage.object_create(self.account, self.container, obj_name=self.obj, data="chunk") _, self.rebuild_file = tempfile.mkstemp() self.checker = Checker(self.ns, rebuild_file=self.rebuild_file) self.meta, chunks = self.storage.object_locate(self.account, self.container, self.obj) self.chunk = chunks[0] self.irreparable = len(chunks) == 1 self.storage.blob_client.chunk_delete(self.chunk['real_url']) def tearDown(self): super(TestIntegrityCrawler, self).tearDown() os.remove(self.rebuild_file) self.storage.container_flush(self.account, self.container) self.storage.container_delete(self.account, self.container) self.wait_for_event('oio-preserved', type_=EventTypes.CONTAINER_DELETED, fields={'user': self.container}) self.storage.account_delete(self.account) def _verify_rebuilder_input(self): try: line = fileinput.input(self.rebuild_file).next().strip() cid = cid_from_name(self.account, self.container) expected = '|'.join([cid, self.meta['id'], self.chunk['url']]) if self.irreparable: expected = IRREPARABLE_PREFIX + '|' + expected self.assertEqual(expected, line) finally: fileinput.close() def test_account_rebuilder_output(self): self.checker.check(Target(self.account), recurse=DEFAULT_DEPTH) for _ in self.checker.run(): pass self.checker.fd.flush() self._verify_rebuilder_input() def test_container_rebuilder_output(self): self.checker.check(Target(self.account, container=self.container), recurse=DEFAULT_DEPTH) for _ in self.checker.run(): pass self.checker.fd.flush() self._verify_rebuilder_input() def test_object_rebuilder_output(self): self.checker.check(Target(self.account, container=self.container, obj=self.obj), recurse=DEFAULT_DEPTH) for _ in self.checker.run(): pass self.checker.fd.flush() self._verify_rebuilder_input()