glusterfs

Форк
0
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

11
import sys
12
import os
13
import xattr
14
import uuid
15
import re
16
import errno
17

18
CHANGELOG_SEARCH_MAX_TRY = 31
19
DEC_CTIME_START = 5
20
ROOT_GFID = "00000000-0000-0000-0000-000000000001"
21
MAX_NUM_CHANGELOGS_TRY = 2
22

23

24
def output_not_found(gfid):
25
    # Write GFID to stderr
26
    sys.stderr.write("%s\n" % gfid)
27

28

29
def output_success(path):
30
    # Write converted Path to Stdout
31
    sys.stdout.write("%s\n" % path)
32

33

34
def full_dir_path(gfid):
35
    out_path = ""
36
    while True:
37
        path = os.path.join(".glusterfs", gfid[0:2], gfid[2:4], gfid)
38
        path_readlink = os.readlink(path)
39
        pgfid = os.path.dirname(path_readlink)
40
        out_path = os.path.join(os.path.basename(path_readlink), out_path)
41
        if pgfid == "../../00/00/%s" % ROOT_GFID:
42
            out_path = os.path.join("./", out_path)
43
            break
44
        gfid = os.path.basename(pgfid)
45
    return out_path
46

47

48
def find_path_from_changelog(fd, gfid):
49
    """
50
    In given Changelog File, finds using following pattern
51
    <T><GFID>\x00<TYPE>\x00<MODE>\x00<UID>\x00<GID>\x00<PARGFID>/<BASENAME>
52
    Pattern search finds PARGFID and BASENAME, Convert PARGFID to Path
53
    Using readlink and add basename to form Full path.
54
    """
55
    content = fd.read()
56

57
    pattern = "E%s" % gfid
58
    pattern += "\x00(3|23)\x00\d+\x00\d+\x00\d+\x00([^\x00]+)/([^\x00]+)"
59
    pat = re.compile(pattern)
60
    match = pat.search(content)
61

62
    if match:
63
        pgfid = match.group(2)
64
        basename = match.group(3)
65
        if pgfid == ROOT_GFID:
66
            return os.path.join("./", basename)
67
        else:
68
            full_path_parent = full_dir_path(pgfid)
69
            if full_path_parent:
70
                return os.path.join(full_path_parent, basename)
71

72
    return None
73

74

75
def gfid_to_path(gfid):
76
    """
77
    Try readlink, if it is directory it succeeds.
78
    Get ctime of the GFID file, Decrement by 5 sec
79
    Search for Changelog filename, Since Changelog file generated
80
    every 15 sec, Search and get immediate next Changelog after the file
81
    Creation. Get the Path by searching in Changelog file.
82
    Get the resultant file's GFID and Compare with the input, If these
83
    GFIDs are different then Some thing is changed(May be Rename)
84
    """
85
    gfid = gfid.strip()
86
    gpath = os.path.join(".glusterfs", gfid[0:2], gfid[2:4], gfid)
87
    try:
88
        output_success(full_dir_path(gfid))
89
        return
90
    except OSError:
91
        # Not an SymLink
92
        pass
93

94
    try:
95
        ctime = int(os.stat(gpath).st_ctime)
96
        ctime -= DEC_CTIME_START
97
    except (OSError, IOError):
98
        output_not_found(gfid)
99
        return
100

101
    path = None
102
    found_changelog = False
103
    changelog_parse_try = 0
104
    for i in range(CHANGELOG_SEARCH_MAX_TRY):
105
        cl = os.path.join(".glusterfs/changelogs", "CHANGELOG.%s" % ctime)
106

107
        try:
108
            with open(cl, "rb") as f:
109
                changelog_parse_try += 1
110
                found_changelog = True
111
                path = find_path_from_changelog(f, gfid)
112
                if not path and changelog_parse_try < MAX_NUM_CHANGELOGS_TRY:
113
                    ctime += 1
114
                    continue
115
            break
116
        except (IOError, OSError) as e:
117
            if e.errno == errno.ENOENT:
118
                ctime += 1
119
            else:
120
                break
121

122
    if not found_changelog:
123
        output_not_found(gfid)
124
        return
125

126
    if not path:
127
        output_not_found(gfid)
128
        return
129
    gfid1 = str(uuid.UUID(bytes=xattr.get(path, "trusted.gfid")))
130
    if gfid != gfid1:
131
        output_not_found(gfid)
132
        return
133

134
    output_success(path)
135

136

137
def main():
138
    num_arguments = 3
139
    if not sys.stdin.isatty():
140
        num_arguments = 2
141

142
    if len(sys.argv) != num_arguments:
143
        sys.stderr.write("Invalid arguments\nUsage: "
144
                         "%s <BRICK_PATH> <GFID_FILE>\n" % sys.argv[0])
145
        sys.exit(1)
146

147
    path = sys.argv[1]
148

149
    if sys.stdin.isatty():
150
        gfid_list = os.path.abspath(sys.argv[2])
151
        os.chdir(path)
152
        with open(gfid_list) as f:
153
            for gfid in f:
154
                gfid_to_path(gfid)
155
    else:
156
        os.chdir(path)
157
        for gfid in sys.stdin:
158
            gfid_to_path(gfid)
159

160

161
if __name__ == "__main__":
162
    main()
163

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.