glusterfs
162 строки · 4.5 Кб
1#!/usr/bin/python3
2
3# Copyright (c) 2015 Red Hat, Inc. <http://www.redhat.com/>
4# This file is part of GlusterFS.
5#
6# This file is licensed to you under your choice of the GNU Lesser
7# General Public License, version 3 or any later version (LGPLv3 or
8# later), or the GNU General Public License, version 2 (GPLv2), in all
9# cases as published by the Free Software Foundation.
10
11import sys12import os13import xattr14import uuid15import re16import errno17
18CHANGELOG_SEARCH_MAX_TRY = 3119DEC_CTIME_START = 520ROOT_GFID = "00000000-0000-0000-0000-000000000001"21MAX_NUM_CHANGELOGS_TRY = 222
23
24def output_not_found(gfid):25# Write GFID to stderr26sys.stderr.write("%s\n" % gfid)27
28
29def output_success(path):30# Write converted Path to Stdout31sys.stdout.write("%s\n" % path)32
33
34def full_dir_path(gfid):35out_path = ""36while True:37path = os.path.join(".glusterfs", gfid[0:2], gfid[2:4], gfid)38path_readlink = os.readlink(path)39pgfid = os.path.dirname(path_readlink)40out_path = os.path.join(os.path.basename(path_readlink), out_path)41if pgfid == "../../00/00/%s" % ROOT_GFID:42out_path = os.path.join("./", out_path)43break44gfid = os.path.basename(pgfid)45return out_path46
47
48def find_path_from_changelog(fd, gfid):49"""50In given Changelog File, finds using following pattern
51<T><GFID>\x00<TYPE>\x00<MODE>\x00<UID>\x00<GID>\x00<PARGFID>/<BASENAME>
52Pattern search finds PARGFID and BASENAME, Convert PARGFID to Path
53Using readlink and add basename to form Full path.
54"""
55content = fd.read()56
57pattern = "E%s" % gfid58pattern += "\x00(3|23)\x00\d+\x00\d+\x00\d+\x00([^\x00]+)/([^\x00]+)"59pat = re.compile(pattern)60match = pat.search(content)61
62if match:63pgfid = match.group(2)64basename = match.group(3)65if pgfid == ROOT_GFID:66return os.path.join("./", basename)67else:68full_path_parent = full_dir_path(pgfid)69if full_path_parent:70return os.path.join(full_path_parent, basename)71
72return None73
74
75def gfid_to_path(gfid):76"""77Try readlink, if it is directory it succeeds.
78Get ctime of the GFID file, Decrement by 5 sec
79Search for Changelog filename, Since Changelog file generated
80every 15 sec, Search and get immediate next Changelog after the file
81Creation. Get the Path by searching in Changelog file.
82Get the resultant file's GFID and Compare with the input, If these
83GFIDs are different then Some thing is changed(May be Rename)
84"""
85gfid = gfid.strip()86gpath = os.path.join(".glusterfs", gfid[0:2], gfid[2:4], gfid)87try:88output_success(full_dir_path(gfid))89return90except OSError:91# Not an SymLink92pass93
94try:95ctime = int(os.stat(gpath).st_ctime)96ctime -= DEC_CTIME_START97except (OSError, IOError):98output_not_found(gfid)99return100
101path = None102found_changelog = False103changelog_parse_try = 0104for i in range(CHANGELOG_SEARCH_MAX_TRY):105cl = os.path.join(".glusterfs/changelogs", "CHANGELOG.%s" % ctime)106
107try:108with open(cl, "rb") as f:109changelog_parse_try += 1110found_changelog = True111path = find_path_from_changelog(f, gfid)112if not path and changelog_parse_try < MAX_NUM_CHANGELOGS_TRY:113ctime += 1114continue115break116except (IOError, OSError) as e:117if e.errno == errno.ENOENT:118ctime += 1119else:120break121
122if not found_changelog:123output_not_found(gfid)124return125
126if not path:127output_not_found(gfid)128return129gfid1 = str(uuid.UUID(bytes=xattr.get(path, "trusted.gfid")))130if gfid != gfid1:131output_not_found(gfid)132return133
134output_success(path)135
136
137def main():138num_arguments = 3139if not sys.stdin.isatty():140num_arguments = 2141
142if len(sys.argv) != num_arguments:143sys.stderr.write("Invalid arguments\nUsage: "144"%s <BRICK_PATH> <GFID_FILE>\n" % sys.argv[0])145sys.exit(1)146
147path = sys.argv[1]148
149if sys.stdin.isatty():150gfid_list = os.path.abspath(sys.argv[2])151os.chdir(path)152with open(gfid_list) as f:153for gfid in f:154gfid_to_path(gfid)155else:156os.chdir(path)157for gfid in sys.stdin:158gfid_to_path(gfid)159
160
161if __name__ == "__main__":162main()163