-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathobject2file-map.py
83 lines (68 loc) · 3.1 KB
/
object2file-map.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
#!/usr/bin/env python3
#Brett Kelly <[email protected]> 2023
import sys
import argparse
import concurrent.futures
import subprocess
import json
import os
import re
def process_inode(inode, pool_name):
if validate_inode(inode):
obj = inode + ".00000000"
command = f"rados -p {pool_name} getxattr {obj} parent | ceph-dencoder type inode_backtrace_t import - decode dump_json"
result = subprocess.run(command, shell=True, stdout=subprocess.PIPE,stderr=subprocess.PIPE)
if result.returncode == 0:
inode_backtrace_json = json.loads(result.stdout)
file_path_json = inode_backtrace_json['ancestors']
num_elements = len(file_path_json)
path_elements = []
itr = num_elements - 1
while itr >= 0:
path_elements.append(file_path_json[itr]['dname'])
itr -= 1
file_path = os.path.join('/', *path_elements)
print(file_path)
else:
print("Object " + "'"+ obj + "'" + " has no backtrace info present", file=sys.stderr)
else:
print("Inode " + "'"+ inode + "'" + " is not in valid format (11 digit hex), ignoring...", file=sys.stderr)
def distribute_inodes(file_path, num_threads, pool_name):
with open(file_path, 'r') as file:
inodes = file.readlines()
inodes = [inode.strip() for inode in inodes]
with concurrent.futures.ThreadPoolExecutor(max_workers=num_threads) as executor:
futures = [executor.submit(process_inode, inode, pool_name) for inode in inodes]
concurrent.futures.wait(futures)
def validate_inode(inode):
pattern = r"^[0-9A-Fa-f]{11}$"
return re.match(pattern, inode)
if __name__ == '__main__':
if os.geteuid() != 0:
print("This script requires root privileges", file=sys.stderr)
sys.exit(1)
parser = argparse.ArgumentParser(description='Distribute inodes across threads.')
parser.add_argument('-i', '--input_file', help='File path, Required if not using -o')
parser.add_argument('-o', '--object_name', help='Object Name, Required if not using -i')
parser.add_argument('-n', '--num_threads', type=int, help='Number of threads, Optional defaults to 16')
parser.add_argument('-p', '--pool_name', help='Name of RADOS pool, Required')
args = parser.parse_args()
if not args.input_file and not args.object_name or not args.pool_name:
parser.print_help()
sys.exit(1)
if not args.num_threads:
num_threads = 16
else:
num_threads = args.num_threads
pool_name = args.pool_name
if not os.path.isfile("/etc/ceph/ceph.client.admin.keyring"):
print("This script requires ceph admin.keyring be present", file=sys.stderr)
sys.exit(1)
if args.input_file:
file_path = args.input_file
distribute_inodes(file_path, num_threads, pool_name)
if args.object_name:
# If given a single object name, split into inode and chunk and process_inode directly bypass threading
object_name = args.object_name
inode = object_name.split('.')
process_inode(inode[0], pool_name)