root / autotools / build-rpc @ cd40dc53
History | View | Annotate | Download (4.9 kB)
1 | d5a2a550 | Michael Hanselmann | #!/usr/bin/python |
---|---|---|---|
2 | d5a2a550 | Michael Hanselmann | # |
3 | d5a2a550 | Michael Hanselmann | |
4 | d5a2a550 | Michael Hanselmann | # Copyright (C) 2011 Google Inc. |
5 | d5a2a550 | Michael Hanselmann | # |
6 | d5a2a550 | Michael Hanselmann | # This program is free software; you can redistribute it and/or modify |
7 | d5a2a550 | Michael Hanselmann | # it under the terms of the GNU General Public License as published by |
8 | d5a2a550 | Michael Hanselmann | # the Free Software Foundation; either version 2 of the License, or |
9 | d5a2a550 | Michael Hanselmann | # (at your option) any later version. |
10 | d5a2a550 | Michael Hanselmann | # |
11 | d5a2a550 | Michael Hanselmann | # This program is distributed in the hope that it will be useful, but |
12 | d5a2a550 | Michael Hanselmann | # WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | d5a2a550 | Michael Hanselmann | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
14 | d5a2a550 | Michael Hanselmann | # General Public License for more details. |
15 | d5a2a550 | Michael Hanselmann | # |
16 | d5a2a550 | Michael Hanselmann | # You should have received a copy of the GNU General Public License |
17 | d5a2a550 | Michael Hanselmann | # along with this program; if not, write to the Free Software |
18 | d5a2a550 | Michael Hanselmann | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA |
19 | d5a2a550 | Michael Hanselmann | # 02110-1301, USA. |
20 | d5a2a550 | Michael Hanselmann | |
21 | d5a2a550 | Michael Hanselmann | |
22 | d5a2a550 | Michael Hanselmann | """Script to generate RPC code. |
23 | d5a2a550 | Michael Hanselmann | |
24 | d5a2a550 | Michael Hanselmann | """ |
25 | d5a2a550 | Michael Hanselmann | |
26 | d5a2a550 | Michael Hanselmann | # pylint: disable=C0103 |
27 | d5a2a550 | Michael Hanselmann | # [C0103] Invalid name |
28 | d5a2a550 | Michael Hanselmann | |
29 | d5a2a550 | Michael Hanselmann | import sys |
30 | d5a2a550 | Michael Hanselmann | import re |
31 | d5a2a550 | Michael Hanselmann | import itertools |
32 | d5a2a550 | Michael Hanselmann | import textwrap |
33 | d5a2a550 | Michael Hanselmann | from cStringIO import StringIO |
34 | d5a2a550 | Michael Hanselmann | |
35 | d5a2a550 | Michael Hanselmann | from ganeti import utils |
36 | d5a2a550 | Michael Hanselmann | from ganeti import compat |
37 | d5a2a550 | Michael Hanselmann | from ganeti import build |
38 | d5a2a550 | Michael Hanselmann | |
39 | d5a2a550 | Michael Hanselmann | |
40 | d5a2a550 | Michael Hanselmann | _SINGLE = "single-node" |
41 | d5a2a550 | Michael Hanselmann | _MULTI = "multi-node" |
42 | d5a2a550 | Michael Hanselmann | |
43 | d5a2a550 | Michael Hanselmann | |
44 | d5a2a550 | Michael Hanselmann | def _WritePreamble(sw): |
45 | d5a2a550 | Michael Hanselmann | """Writes a preamble for the RPC wrapper output. |
46 | d5a2a550 | Michael Hanselmann | |
47 | d5a2a550 | Michael Hanselmann | """ |
48 | d5a2a550 | Michael Hanselmann | sw.Write("# This code is automatically generated at build time.") |
49 | d5a2a550 | Michael Hanselmann | sw.Write("# Do not modify manually.") |
50 | d5a2a550 | Michael Hanselmann | sw.Write("") |
51 | d5a2a550 | Michael Hanselmann | sw.Write("\"\"\"Automatically generated RPC client wrappers.") |
52 | d5a2a550 | Michael Hanselmann | sw.Write("") |
53 | d5a2a550 | Michael Hanselmann | sw.Write("\"\"\"") |
54 | d5a2a550 | Michael Hanselmann | sw.Write("") |
55 | d5a2a550 | Michael Hanselmann | |
56 | d5a2a550 | Michael Hanselmann | |
57 | d5a2a550 | Michael Hanselmann | def _WrapCode(line): |
58 | d5a2a550 | Michael Hanselmann | """Wraps Python code. |
59 | d5a2a550 | Michael Hanselmann | |
60 | d5a2a550 | Michael Hanselmann | """ |
61 | d5a2a550 | Michael Hanselmann | return textwrap.wrap(line, width=70, expand_tabs=False, |
62 | d5a2a550 | Michael Hanselmann | fix_sentence_endings=False, break_long_words=False, |
63 | d5a2a550 | Michael Hanselmann | replace_whitespace=True, |
64 | d5a2a550 | Michael Hanselmann | subsequent_indent=utils.ShellWriter.INDENT_STR) |
65 | d5a2a550 | Michael Hanselmann | |
66 | d5a2a550 | Michael Hanselmann | |
67 | d5a2a550 | Michael Hanselmann | def _WriteDocstring(sw, name, timeout, kind, args, desc): |
68 | d5a2a550 | Michael Hanselmann | """Writes a docstring for an RPC wrapper. |
69 | d5a2a550 | Michael Hanselmann | |
70 | d5a2a550 | Michael Hanselmann | """ |
71 | d5a2a550 | Michael Hanselmann | sw.Write("\"\"\"Wrapper for RPC call '%s'", name) |
72 | d5a2a550 | Michael Hanselmann | sw.Write("") |
73 | d5a2a550 | Michael Hanselmann | if desc: |
74 | d5a2a550 | Michael Hanselmann | sw.Write(desc) |
75 | d5a2a550 | Michael Hanselmann | sw.Write("") |
76 | d5a2a550 | Michael Hanselmann | |
77 | d5a2a550 | Michael Hanselmann | note = ["This is a %s call" % kind] |
78 | d5a2a550 | Michael Hanselmann | if timeout: |
79 | d5a2a550 | Michael Hanselmann | note.append(" with a timeout of %s" % utils.FormatSeconds(timeout)) |
80 | d5a2a550 | Michael Hanselmann | sw.Write("@note: %s", "".join(note)) |
81 | d5a2a550 | Michael Hanselmann | |
82 | d5a2a550 | Michael Hanselmann | if kind == _SINGLE: |
83 | d5a2a550 | Michael Hanselmann | sw.Write("@type node: string") |
84 | d5a2a550 | Michael Hanselmann | sw.Write("@param node: Node name") |
85 | d5a2a550 | Michael Hanselmann | else: |
86 | d5a2a550 | Michael Hanselmann | sw.Write("@type node_list: list of string") |
87 | d5a2a550 | Michael Hanselmann | sw.Write("@param node_list: List of node names") |
88 | d5a2a550 | Michael Hanselmann | |
89 | d5a2a550 | Michael Hanselmann | if args: |
90 | d5a2a550 | Michael Hanselmann | for (argname, _, argtext) in args: |
91 | d5a2a550 | Michael Hanselmann | if argtext: |
92 | d5a2a550 | Michael Hanselmann | docline = "@param %s: %s" % (argname, argtext) |
93 | d5a2a550 | Michael Hanselmann | for line in _WrapCode(docline): |
94 | d5a2a550 | Michael Hanselmann | sw.Write(line) |
95 | d5a2a550 | Michael Hanselmann | sw.Write("") |
96 | d5a2a550 | Michael Hanselmann | sw.Write("\"\"\"") |
97 | d5a2a550 | Michael Hanselmann | |
98 | d5a2a550 | Michael Hanselmann | |
99 | d5a2a550 | Michael Hanselmann | def _WriteBaseClass(sw, clsname, calls): |
100 | d5a2a550 | Michael Hanselmann | """Write RPC wrapper class. |
101 | d5a2a550 | Michael Hanselmann | |
102 | d5a2a550 | Michael Hanselmann | """ |
103 | d5a2a550 | Michael Hanselmann | sw.Write("") |
104 | d5a2a550 | Michael Hanselmann | sw.Write("class %s(object):", clsname) |
105 | d5a2a550 | Michael Hanselmann | sw.IncIndent() |
106 | d5a2a550 | Michael Hanselmann | try: |
107 | d5a2a550 | Michael Hanselmann | sw.Write("# E1101: Non-existent members") |
108 | d5a2a550 | Michael Hanselmann | sw.Write("# R0904: Too many public methods") |
109 | d5a2a550 | Michael Hanselmann | sw.Write("# pylint: disable=E1101,R0904") |
110 | d5a2a550 | Michael Hanselmann | |
111 | d5a2a550 | Michael Hanselmann | if not calls: |
112 | d5a2a550 | Michael Hanselmann | sw.Write("pass") |
113 | d5a2a550 | Michael Hanselmann | return |
114 | d5a2a550 | Michael Hanselmann | |
115 | d5a2a550 | Michael Hanselmann | for (name, kind, timeout, args, postproc, desc) in calls: |
116 | d5a2a550 | Michael Hanselmann | funcargs = ["self"] |
117 | d5a2a550 | Michael Hanselmann | |
118 | d5a2a550 | Michael Hanselmann | if kind == _SINGLE: |
119 | d5a2a550 | Michael Hanselmann | funcargs.append("node") |
120 | d5a2a550 | Michael Hanselmann | elif kind == _MULTI: |
121 | d5a2a550 | Michael Hanselmann | funcargs.append("node_list") |
122 | d5a2a550 | Michael Hanselmann | else: |
123 | d5a2a550 | Michael Hanselmann | raise Exception("Unknown kind '%s'" % kind) |
124 | d5a2a550 | Michael Hanselmann | |
125 | d5a2a550 | Michael Hanselmann | funcargs.extend(map(compat.fst, args)) |
126 | d5a2a550 | Michael Hanselmann | |
127 | d5a2a550 | Michael Hanselmann | assert "read_timeout" not in funcargs |
128 | d5a2a550 | Michael Hanselmann | funcargs.append("read_timeout=%s" % timeout) |
129 | d5a2a550 | Michael Hanselmann | |
130 | d5a2a550 | Michael Hanselmann | funcdef = "def call_%s(%s):" % (name, utils.CommaJoin(funcargs)) |
131 | d5a2a550 | Michael Hanselmann | for line in _WrapCode(funcdef): |
132 | d5a2a550 | Michael Hanselmann | sw.Write(line) |
133 | d5a2a550 | Michael Hanselmann | |
134 | d5a2a550 | Michael Hanselmann | sw.IncIndent() |
135 | d5a2a550 | Michael Hanselmann | try: |
136 | d5a2a550 | Michael Hanselmann | _WriteDocstring(sw, name, timeout, kind, args, desc) |
137 | d5a2a550 | Michael Hanselmann | |
138 | d5a2a550 | Michael Hanselmann | buf = StringIO() |
139 | d5a2a550 | Michael Hanselmann | buf.write("return ") |
140 | d5a2a550 | Michael Hanselmann | |
141 | d5a2a550 | Michael Hanselmann | # In case line gets too long and is wrapped in a bad spot |
142 | d5a2a550 | Michael Hanselmann | buf.write("( ") |
143 | d5a2a550 | Michael Hanselmann | |
144 | d5a2a550 | Michael Hanselmann | if postproc: |
145 | d5a2a550 | Michael Hanselmann | buf.write("%s(" % postproc) |
146 | d5a2a550 | Michael Hanselmann | buf.write("self._Call(") |
147 | d5a2a550 | Michael Hanselmann | if kind == _SINGLE: |
148 | d5a2a550 | Michael Hanselmann | buf.write("[node]") |
149 | d5a2a550 | Michael Hanselmann | else: |
150 | d5a2a550 | Michael Hanselmann | buf.write("node_list") |
151 | cd40dc53 | Michael Hanselmann | |
152 | cd40dc53 | Michael Hanselmann | buf.write(", \"%s\", read_timeout, [%s], [%s])" % |
153 | cd40dc53 | Michael Hanselmann | (name, |
154 | cd40dc53 | Michael Hanselmann | # Argument definitions |
155 | cd40dc53 | Michael Hanselmann | utils.CommaJoin(map(compat.snd, args)), |
156 | cd40dc53 | Michael Hanselmann | # Function arguments |
157 | cd40dc53 | Michael Hanselmann | utils.CommaJoin(map(compat.fst, args)))) |
158 | cd40dc53 | Michael Hanselmann | |
159 | d5a2a550 | Michael Hanselmann | if kind == _SINGLE: |
160 | d5a2a550 | Michael Hanselmann | buf.write("[node]") |
161 | d5a2a550 | Michael Hanselmann | if postproc: |
162 | d5a2a550 | Michael Hanselmann | buf.write(")") |
163 | d5a2a550 | Michael Hanselmann | buf.write(")") |
164 | d5a2a550 | Michael Hanselmann | |
165 | d5a2a550 | Michael Hanselmann | for line in _WrapCode(buf.getvalue()): |
166 | d5a2a550 | Michael Hanselmann | sw.Write(line) |
167 | d5a2a550 | Michael Hanselmann | finally: |
168 | d5a2a550 | Michael Hanselmann | sw.DecIndent() |
169 | d5a2a550 | Michael Hanselmann | sw.Write("") |
170 | d5a2a550 | Michael Hanselmann | finally: |
171 | d5a2a550 | Michael Hanselmann | sw.DecIndent() |
172 | d5a2a550 | Michael Hanselmann | |
173 | d5a2a550 | Michael Hanselmann | |
174 | d5a2a550 | Michael Hanselmann | def main(): |
175 | d5a2a550 | Michael Hanselmann | """Main function. |
176 | d5a2a550 | Michael Hanselmann | |
177 | d5a2a550 | Michael Hanselmann | """ |
178 | d5a2a550 | Michael Hanselmann | buf = StringIO() |
179 | d5a2a550 | Michael Hanselmann | sw = utils.ShellWriter(buf) |
180 | d5a2a550 | Michael Hanselmann | |
181 | d5a2a550 | Michael Hanselmann | _WritePreamble(sw) |
182 | d5a2a550 | Michael Hanselmann | |
183 | d5a2a550 | Michael Hanselmann | for filename in sys.argv[1:]: |
184 | d5a2a550 | Michael Hanselmann | sw.Write("# Definitions from '%s'", filename) |
185 | d5a2a550 | Michael Hanselmann | |
186 | d5a2a550 | Michael Hanselmann | module = build.LoadModule(filename) |
187 | d5a2a550 | Michael Hanselmann | |
188 | d5a2a550 | Michael Hanselmann | # Call types are re-defined in definitions file to avoid imports. Verify |
189 | d5a2a550 | Michael Hanselmann | # here to ensure they're equal to local constants. |
190 | d5a2a550 | Michael Hanselmann | assert module.SINGLE == _SINGLE |
191 | d5a2a550 | Michael Hanselmann | assert module.MULTI == _MULTI |
192 | d5a2a550 | Michael Hanselmann | |
193 | d5a2a550 | Michael Hanselmann | for (clsname, calls) in module.CALLS.items(): |
194 | d5a2a550 | Michael Hanselmann | _WriteBaseClass(sw, clsname, calls) |
195 | d5a2a550 | Michael Hanselmann | |
196 | d5a2a550 | Michael Hanselmann | print buf.getvalue() |
197 | d5a2a550 | Michael Hanselmann | |
198 | d5a2a550 | Michael Hanselmann | |
199 | d5a2a550 | Michael Hanselmann | if __name__ == "__main__": |
200 | d5a2a550 | Michael Hanselmann | main() |