1
# Copyright (c) 2010-2011 Red Hat, Inc.
3
# This file is part of HekaFS.
5
# HekaFS is free software: you can redistribute it and/or modify it under the
6
# terms of the GNU General Public License, version 3, as published by the Free
9
# HekaFS is distributed in the hope that it will be useful, but WITHOUT ANY
10
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
11
# A PARTICULAR PURPOSE. See the GNU General Public License for more details.
13
# You should have received a copy of the GNU General Public License * along
14
# with HekaFS. If not, see <http://www.gnu.org/licenses/>.
16
from __future__ import print_function
29
"features/access-control",
33
"performance/io-threads",
39
def copy_stack (old_xl, suffix, recursive=False):
41
new_name = old_xl.name + "-" + suffix
44
new_xl = Translator(new_name)
45
new_xl.type = old_xl.type
46
# The results with normal assignment here are . . . amusing.
47
new_xl.opts = copy.deepcopy(old_xl.opts)
48
for sv in old_xl.subvols:
49
new_xl.subvols.append(copy_stack(sv, suffix, True))
50
# Patch up the path at the bottom.
51
if new_xl.type == "storage/posix":
52
new_xl.opts["directory"] += ("/" + suffix)
55
def cleanup (parent, graph):
56
if parent.type in good_xlators:
57
# Temporary fix so that HekaFS volumes can use the
58
# SSL-enabled multi-threaded socket transport.
59
if parent.type == "protocol/server":
60
parent.type = "protocol/server2"
61
parent.opts["transport-type"] = "ssl"
62
elif parent.type == "protocol/client":
63
parent.type = "protocol/client2"
64
parent.opts["transport-type"] = "ssl"
66
for child in parent.subvols:
67
sv.append(cleanup(child, graph))
70
parent = cleanup(parent.subvols[0], graph)
74
def __init__ (self, name):
81
return "<Translator %s>" % self.name
84
# If it's a string, open it; otherwise, assume it's already a
85
# file-like object (most notably from urllib*).
86
if type(path) in (str,):
100
if text[0] == "volume":
102
raise RuntimeError("nested volume definition")
103
xlator = Translator(text[1])
106
raise RuntimeError("text outside volume definition")
107
if text[0] == "type":
108
xlator.type = text[1]
110
if text[0] == "option":
111
xlator.opts[text[1]] = ''.join(text[2:])
113
if text[0] == "subvolumes":
115
xlator.subvols.append(all_xlators[sv])
117
if text[0] == "end-volume":
118
all_xlators[xlator.name] = xlator
122
raise RuntimeError("unrecognized keyword %s" % text[0])
124
raise RuntimeError("unclosed volume definition")
125
return all_xlators, last_xlator
127
def generate (graph, last, stream=sys.stdout):
128
for sv in last.subvols:
130
generate(graph, sv, stream)
131
print("", file=stream)
133
print("volume %s" % last.name, file=stream)
134
print(" type %s" % last.type, file=stream)
135
for k, v in last.opts.items():
136
print(" option %s %s" % (k, v), file=stream)
138
print(" subvolumes %s" % ''.join(
139
[ sv.name for sv in last.subvols ]), file=stream)
140
print("end-volume", file=stream)
142
def push_filter (graph, old_xl, filt_type, opts={}):
143
suffix = "-" + old_xl.type.split("/")[1]
144
if len(old_xl.name) > len(suffix):
145
if old_xl.name[-len(suffix):] == suffix:
146
old_xl.name = old_xl.name[:-len(suffix)]
147
new_xl = Translator(old_xl.name+suffix)
148
new_xl.type = old_xl.type
149
new_xl.opts = old_xl.opts
150
new_xl.subvols = old_xl.subvols
151
graph[new_xl.name] = new_xl
152
old_xl.name += ("-" + filt_type.split("/")[1])
153
old_xl.type = filt_type
155
old_xl.subvols = [new_xl]
156
graph[old_xl.name] = old_xl
158
def delete (graph, victim):
159
if len(victim.subvols) != 1:
160
raise RuntimeError("attempt to delete non-unary translator")
161
for xl in graph.itervalues():
162
while xl.subvols.count(victim):
163
i = xl.subvols.index(victim)
164
xl.subvols[i] = victim.subvols[0]
166
if __name__ == "__main__":
167
graph, last = load(sys.argv[1])
168
generate(graph, last)