28 timestr = time.strftime(
"%Y%m%d-%H%M%S")
29 log_filename =
"hole_creation_" + timestr +
".log" 31 logger = logging.getLogger()
32 logger.setLevel(logging.DEBUG)
34 fh = logging.FileHandler(log_filename)
35 fh.setLevel(logging.DEBUG)
37 ch = logging.StreamHandler()
38 ch.setLevel(logging.DEBUG)
39 fformatter = logging.Formatter(
'%(asctime)s - %(levelname)s - %(message)s')
40 cformatter = logging.Formatter(
'%(levelname)s : %(message)s')
41 fh.setFormatter(fformatter)
42 ch.setFormatter(cformatter)
46 logger.info(
"***** Script Started *****")
48 parser = argparse.ArgumentParser(description=
"Basic Arguments to run the script")
49 parser.add_argument(
'-rn', action=
'store_true', default=
False, dest=
'random',
50 help=
'For inducing error at Random place')
51 parser.add_argument(
'-e', action=
'store', default=0, type=int, dest=
'noOfErr',
52 help=
'How Many number of error do you want to induce in Metadata')
53 parser.add_argument(
'-rt', action=
'store', dest=
'Record_Type',
54 help=
'Record Type For inducing error at particular record like:' 55 ' BE_BTREE, BE_EMAP, CAS_CTG etc')
56 parser.add_argument(
'-m', action=
'store', dest=
'mfile', help=
'Metadata Path')
57 parser.add_argument(
'-v', action=
'store_true', default=
False, dest=
'verify',
58 help=
'Read full Metadata and Print all the Records entries counts')
59 parser.add_argument(
'-a', action=
'store_true', default=
False, dest=
'allErr',
60 help=
'Induce Error in All Record at Random place')
61 parser.add_argument(
'-gmd', action=
'store_true', default=
False, dest=
'allGMD',
62 help=
'Induce Error in All GMD type of Record at Random place')
63 parser.add_argument(
'-dmd', action=
'store_true', default=
False, dest=
'allDMD',
64 help=
'Induce Error in All DMD type of Record at Random place')
65 parser.add_argument(
'-512k', action=
'store_true', default=
False, dest=
'err512k',
66 help=
'Induce 512K bytes error in Metadata')
67 parser.add_argument(
'-huge', action=
'store_true', default=
False, dest=
'hugeCorruption',
68 help=
'Induce Huge amount of corruption in Metadata')
69 parser.add_argument(
'-seed', action=
'store', default=0, type=float, dest=
'seed',
70 help=
'Seed is used to initialize the "random" library:' 71 ' to initialize the random generation')
72 parser.add_argument(
'-corrupt_emap', action=
'store', dest=
'corrupt_emap',
73 help=
'Induce Error in Emap specified by Cob Id')
74 parser.add_argument(
'-list_emap', action=
'store_true', default=
False, dest=
'list_emap',
75 help=
'Display all Emap keys with device id')
76 parser.add_argument(
'-parse_size', action=
'store', dest=
'parse_size', type=int,
77 help=
'Limit for metadata parsing size in bytes for list_emap and verify option')
78 parser.add_argument(
'-offset', action=
'store', default=0, type=int, dest=
'seek_offset',
79 help=
'Starting offset of metadata file in multiple of 8 bytes')
81 args = parser.parse_args()
83 results = parser.parse_args()
84 logger.info(
'Induce Random Error = {!r}'.
format(args.random))
85 logger.info(
'Number of Error induce = {!r}'.
format(args.noOfErr))
86 logger.info(
'Record Type = {!r}'.
format(args.Record_Type))
87 logger.info(
'Metadata file path = {!r}'.
format(args.mfile))
88 logger.info(
'Verify Record entries = {!r}'.
format(args.verify))
89 logger.info(
'Induce Error in All Record = {!r}'.
format(args.allErr))
90 logger.info(
'Induce Error in GMD Record = {!r}'.
format(args.allGMD))
91 logger.info(
'Induce Error in DMD Record = {!r}'.
format(args.allDMD))
92 logger.info(
'Induce 512k errors = {!r}'.
format(args.err512k))
93 logger.info(
'Induce huge errors = {!r}'.
format(args.hugeCorruption))
94 logger.info(
'Seed for random number = {!r}'.
format(args.seed))
95 logger.info(
'Induce Error in emap by Cob Id = {!r}'.
format(args.corrupt_emap))
96 logger.info(
'List all Emap Keys and Records = {!r}'.
format(args.list_emap))
97 logger.info(
'Limit for parsing size in bytes = {!r}'.
format(args.parse_size))
98 logger.info(
'Metadata seek offset in bytes multiple of 8 bytes = {!r}'.
format(args.seek_offset))
100 filename = args.mfile
101 recordType = args.Record_Type
102 noOfErr = args.noOfErr
106 logger.info(
"Seed used: {}".
format(seed))
109 logger.info(
"Seed used: {}".
format(seed))
112 random_system=random.SystemRandom()
114 if not os.walk(filename):
115 logger.error(
'Failed: The path specified does not exist or Missing file path')
119 header = b
'33011ca5e511de77' 121 footer = b
'33f007e7f007e777' 123 typeDict = {b
'01':
'RPC_PACKET', b
'02':
'RPC_ITEM', b
'03':
'BE_BTREE',
124 b
'04':
'BE_BNODE', b
'05':
'BE_EMAP_KEY', b
'06':
'BE_EMAP_REC',
125 b
'07':
'BE_EMAP', b
'08':
'BE_LIST', b
'09':
'BE_SEG_HDR',
126 b
'0a':
'BALLOC', b
'0b':
'ADDB2_FRAME_HEADER', b
'0c':
'STOB_AD_0TYPE_REC',
127 b
'0d':
'STOB_AD_DOMAIN', b
'0e':
'COB_DOMAIN', b
'0f':
'COB_NSREC',
128 b
'10':
'BALLOC_GROUP_DESC', b
'11':
'EXT', b
'12':
'CAS_INDEX',
129 b
'13':
'POOLNODE', b
'14':
'POOLDEV', b
'15':
'POOL_SPARE_USAGE',
130 b
'16':
'CAS_STATE', b
'17':
'CAS_CTG', b
'22':
'WRONG_ENTRY', b
'44':
'WRONG_ENTRY'}
132 recordDict = {
'BE_BTREE': [],
'BE_BNODE': [],
'BE_EMAP_KEY': [],
'BE_EMAP_REC': [],
133 'BE_EMAP': [],
'BE_LIST': [],
'BE_SEG_HDR': [],
'BALLOC': [],
134 'STOB_AD_0TYPE_REC': [],
'STOB_AD_DOMAIN': [],
'COB_DOMAIN': [],
135 'COB_NSREC': [],
'BALLOC_GROUP_DESC': [],
'EXT': [],
'POOLNODE': [],
136 'POOLDEV': [],
'POOL_SPARE_USAGE': [],
'CAS_STATE': [],
'CAS_CTG': [],
'EXTRA': []}
138 AllRecordList = [
'BE_BTREE',
'BE_BNODE',
'BE_EMAP_KEY',
'BE_EMAP_REC',
'BE_EMAP',
'BE_LIST',
139 'BE_SEG_HDR',
'BALLOC',
'STOB_AD_0TYPE_REC',
'STOB_AD_DOMAIN',
'COB_DOMAIN',
140 'COB_NSREC',
'BALLOC_GROUP_DESC',
'EXT',
'POOLNODE',
141 'POOLDEV',
'POOL_SPARE_USAGE',
'CAS_STATE',
'CAS_CTG',
'EXTRA']
142 DMDList = [
'BE_BNODE',
'BE_EMAP_KEY',
'BE_EMAP_REC',
'COB_NSREC',
'BALLOC_GROUP_DESC']
143 GMDList = [
'BE_BTREE',
'BE_EMAP',
'BE_LIST',
'BE_SEG_HDR',
'BALLOC',
'STOB_AD_0TYPE_REC',
144 'STOB_AD_DOMAIN',
'COB_DOMAIN',
'CAS_STATE',
'CAS_CTG']
146 btreeType = {b
'01':
'M0_BBT_INVALID', b
'02':
'M0_BBT_BALLOC_GROUP_EXTENTS',
147 b
'03':
'M0_BBT_BALLOC_GROUP_DESC', b
'04':
'M0_BBT_EMAP_EM_MAPPING',
148 b
'05':
'M0_BBT_CAS_CTG', b
'06':
'M0_BBT_COB_NAMESPACE',
149 b
'07':
'M0_BBT_COB_OBJECT_INDEX', b
'08':
'M0_BBT_COB_FILEATTR_BASIC',
150 b
'09':
'M0_BBT_COB_FILEATTR_EA', b
'0a':
'M0_BBT_COB_FILEATTR_OMG',
151 b
'0b':
'M0_BBT_CONFDB', b
'0c':
'M0_BBT_UT_KV_OPS', b
'0d':
'M0_BBT_NR'}
156 if record
in recordDict.keys():
157 recordDict[record].append(i)
158 if record ==
"BE_BNODE":
160 btNumActiveKey = i + 56
161 BeBnodeTypeKeys[i] = [bliType, btNumActiveKey]
163 recordDict[
'EXTRA'].append(i)
174 """Edit metadata with the fixed pattern of 0x1111222244443333.""" 175 with open(filename,
'r+b')
as wbfr:
176 logger.info(
"** Corrupting 8byte of Metadata at offset {}" 177 " with b'1111222244443333' **".
format(offset))
179 wbfr.write(b
'\x33\x33\x44\x44\x22\x22\x11\x11')
185 """Verifies that meta-data contains the valid footer at the given offset.""" 186 with open(filename,
"rb")
as mdata:
188 data = binascii.hexlify((mdata.read(8))[::-1])
195 """Function read complete record starting after header and until footer for record.""" 201 curr_record.append(data.decode(
'utf-8'))
205 curr_record = [
hex(
int(i, 16))
for i
in curr_record]
206 return curr_record, offset
210 """Reads BeNode data.""" 211 llist = BeBnodeTypeKeys[offset]
212 with open(filename,
"rb")
as mdata:
214 data = binascii.hexlify((mdata.read(8))[::-1])
216 logger.info(
"bli_type of BE_BNODE is: {0}: {1}".
format( data, btreeType[data]))
219 data = binascii.hexlify((mdata.read(8))[::-1])
221 logger.info(
"Active key count of BE_BNODE is: {}".
format(
int(data,16)))
225 """Induces Corruption in a record with number of error.""" 228 logger.info(recordType)
229 logger.info(
"Number of Error want to induce: {}".
format(noOfErr))
230 lookupList = recordDict[recordType]
231 if (len(lookupList)
and noOfErr) == 0:
232 logger.error(
"Record List is empty. Please choose another Record")
235 elif len(lookupList) < noOfErr:
237 " Record List contains Less number of entries than input." 238 " Please reduce the number of Error Injection")
242 logger.info(lookupList)
243 logger.info(
"**** Inducing {} Error in Record: {} ****".
format(noOfErr, recordType))
244 for i
in range(noOfErr):
245 offset = lookupList[i]
248 if recordType ==
"BE_BNODE":
255 """Induces corruption in meta data at random offset.""" 259 recType = random_system.choice(
list(recordDict))
260 logger.info(
"+++ Picked a Random Record from Dictionary Record type:{}+++".
format(recType))
261 logger.info(
"Number of Error want to induce: {}".
format(noOfErr))
262 lookupList = recordDict[recType]
263 logger.info(lookupList)
264 if (len(lookupList) == 0)
or (len(lookupList) < noOfErr):
265 logger.info(
"Record List is empty OR contains Less number of entries than input." 266 " Going to next Record")
268 lookupList = random_system.sample(lookupList, noOfErr)
269 logger.info(lookupList)
270 for i
in range(noOfErr):
271 offset = lookupList[i]
272 logger.info(
"**** Inducing RANDOM Error in Record at offsets: {}****" 283 """Function which induces error in a particular type of record.""" 286 logger.info(
"++++ Induce Random number of errors in All Records ++++")
287 for recType
in recList:
288 logger.info(
"Record Name: {}".
format(recType))
289 lookupList = recordDict[recType]
290 length = len(lookupList)
292 logger.info(
"Record List is empty. Moving to Next Record")
294 lookupList = random_system.sample(lookupList,
295 random_system.randint(1, length))
296 logger.info(
"Inducing {} Error at these offsets".
format(len(lookupList)))
297 logger.info(lookupList)
298 for offset
in lookupList:
299 logger.info(
"**** Inducing Error in Record at offsets {}****" 309 """Corrupt Metadata file from random location till end of metadata file.""" 311 with open(filename,
'r+b')
as wbfr:
312 logger.info(
"** Corrupting 8byte of Metadata with b'1111222244443333' all place")
313 wbfr.seek(-1, os.SEEK_END)
314 endOffset = wbfr.tell()
315 offset = random_system.randint(1, endOffset)
316 logger.info(
"Start offset is {}".
format(offset))
330 """Corrupt 512k Metadata in Metadata file from random location.""" 333 with open(filename,
'r+b')
as wbfr:
334 wbfr.seek(-524400, os.SEEK_END)
335 endOffset = wbfr.tell()
336 offset = random_system.randint(1, endOffset)
337 logger.info(
"Start offset is {}".
format(offset))
355 """Method to extract cob related data.""" 356 M0_FID_DEVICE_ID_OFFSET = 32
357 M0_FID_DEVICE_ID_MASK = 72057589742960640
358 M0_FID_TYPE_MASK = 72057594037927935
362 cob_f_container = ((tid << (64 - 8 )) | (
int(stob_f_container, 16) & M0_FID_TYPE_MASK))
363 cob_f_key =
int(stob_f_key, 16)
364 device_id = (
int(cob_f_container) & M0_FID_DEVICE_ID_MASK) >> M0_FID_DEVICE_ID_OFFSET
366 return cob_f_container, cob_f_key, device_id
370 """Method take cob_f_cotainer, cob_f_key and returns stob_f_container, stob_f_key.""" 371 M0_FID_TYPE_MASK = 72057594037927935
375 stob_f_container = ((tid << (64 - 8 )) | (
int(cob_f_container, 16) & M0_FID_TYPE_MASK))
376 stob_f_key =
int(cob_f_key, 16)
378 return stob_f_container, stob_f_key
382 """Method corrupts EMAP record specified by Cob ID.""" 385 lookupList = recordDict[recordType]
387 logger.info(
"*****Corrupting BE_EMAP_KEY for Cob ID {}*****".
format(args.corrupt_emap))
389 for offset
in lookupList:
391 if (
hex(stob_f_container)
in emap_key_data)
and\
392 (
hex(stob_f_key)
in emap_key_data)
and \
393 (
"0xffffffffffffffff" not in emap_key_data):
396 rec_offset = offset + 32
400 if emap_rec_data[3] !=
"0x0":
401 logger.info(
"** Metadata at offset {}," 402 " BE_EMAP_KEY ek_prefix = {}:{}," 403 " ek_offset = {}".
format(offset-24,
404 emap_key_data[0], emap_key_data[1], emap_key_data[2]))
405 logger.info(
"** Metadata at offset {}," 406 " BE_EMAP_REC er_start = {}," 407 " er_value = {}, er_unit_size = {}," 408 " er_cs_nob = {}, checksum = {}".
format(
409 offset+32, emap_rec_data[0], emap_rec_data[1],
410 emap_rec_data[2], emap_rec_data[3], emap_rec_data[4:]))
418 logger.info(
"*****Listing all emap keys and emap records with device id*****")
419 recordType =
"BE_EMAP_KEY" 421 lookupList = recordDict[recordType]
424 for offset
in lookupList:
427 stob_f_container_hex = emap_key_data[0]
428 stob_f_key_hex = emap_key_data[1]
432 emap_rec_offset = offset + 32
435 logger.info(
"** Metadata at offset {}," 436 " BE_EMAP_KEY ek_prefix = {}:{}," 437 " ek_offset = {}, Device ID = {}".
format(offset,
438 emap_key_data[0], emap_key_data[1], emap_key_data[2], device_id))
439 logger.info(
"** Metadata at offset {}," 440 " BE_EMAP_REC er_start = {}," 441 " er_value = {}, er_unit_size = {}," 442 " er_cs_nob = {}, checksum = {}" 443 .
format(emap_rec_offset, emap_rec_data[0],
444 emap_rec_data[1], emap_rec_data[2],
445 emap_rec_data[3], emap_rec_data[4:]))
451 logger.info(
"***********Record list will be print here************")
452 for record, items
in recordDict.items():
453 logger.info(
" {} : {}".
format(record, len(items)))
459 with open(filename,
"rb")
as metadata:
461 metadata.seek(args.seek_offset)
463 byte = metadata.read(8)
467 byte = binascii.hexlify(byte[::-1])
469 byte = binascii.hexlify((metadata.read(8))[::-1])
471 if rtype
not in typeDict.keys():
473 record = typeDict[rtype]
475 if size > b
'00000000':
477 i =
int(size, 16) + i - 16
481 if (args.verify ==
True)
or (args.list_emap ==
True):
483 if i > args.parse_size:
497 elif args.hugeCorruption:
518 elif args.corrupt_emap:
519 _f_container, _f_key = args.corrupt_emap.split(
":")
520 cob_f_container =
hex(
int(_f_container, 16))
523 noOfErrs =
CorruptEmap(
"BE_EMAP_KEY", stob_f_container, stob_f_key)
529 logger.info(
"Number of errors induced by script: {}".
format(noOfErrs))
532 logger.info(
"**** Successfully injected holes in metadata ****")
534 logger.error(
"**** Failed to inject holes in metadata ****")
static struct m0_list list
def RecordOffset(record, i, size)
def ListAllEmapPerDevice()
static M0_UNUSED void print(struct m0_be_list *list)
def VerifyLengthOfRecord(recordDict)
def InduceCorruption(recordType, noOfErr)
def InduceErrInRecords(recList)
def ReadCompleteRecord(offset)
def ConvertAdstob2Cob(stob_f_container, stob_f_key)
def ConvertCobAdstob(cob_f_container, cob_f_key)
def CorruptEmap(recordType, stob_f_container, stob_f_key)
def InduceRandomCorruption(noOfErr)
static void hex(struct m0_addb2__context *ctx, const uint64_t *v, char *buf)