4 # Copyright (C) 2011 Google Inc.
6 # This program is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 2 of the License, or
9 # (at your option) any later version.
11 # This program is distributed in the hope that it will be useful, but
12 # WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 # General Public License for more details.
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22 """Script to generate RPC code.
26 # pylint: disable=C0103
27 # [C0103] Invalid name
33 from cStringIO import StringIO
35 from ganeti import utils
36 from ganeti import compat
37 from ganeti import build
40 _SINGLE = "single-node"
44 def _WritePreamble(sw):
45 """Writes a preamble for the RPC wrapper output.
48 sw.Write("# This code is automatically generated at build time.")
49 sw.Write("# Do not modify manually.")
51 sw.Write("\"\"\"Automatically generated RPC client wrappers.")
61 return textwrap.wrap(line, width=70, expand_tabs=False,
62 fix_sentence_endings=False, break_long_words=False,
63 replace_whitespace=True,
64 subsequent_indent=utils.ShellWriter.INDENT_STR)
67 def _WriteDocstring(sw, name, timeout, kind, args, desc):
68 """Writes a docstring for an RPC wrapper.
71 sw.Write("\"\"\"Wrapper for RPC call '%s'", name)
77 note = ["This is a %s call" % kind]
79 note.append(" with a timeout of %s" % utils.FormatSeconds(timeout))
80 sw.Write("@note: %s", "".join(note))
83 sw.Write("@type node: string")
84 sw.Write("@param node: Node name")
86 sw.Write("@type node_list: list of string")
87 sw.Write("@param node_list: List of node names")
90 for (argname, _, argtext) in args:
92 docline = "@param %s: %s" % (argname, argtext)
93 for line in _WrapCode(docline):
99 def _MakeArgument((argname, wrapper, _)):
100 """Format argument for function call.
104 return wrapper % argname
109 def _WriteBaseClass(sw, clsname, calls):
110 """Write RPC wrapper class.
114 sw.Write("class %s(object):", clsname)
117 sw.Write("# E1101: Non-existent members")
118 sw.Write("# R0904: Too many public methods")
119 sw.Write("# pylint: disable=E1101,R0904")
125 for (name, kind, timeout, args, postproc, desc) in calls:
129 funcargs.append("node")
131 funcargs.append("node_list")
133 raise Exception("Unknown kind '%s'" % kind)
135 funcargs.extend(map(compat.fst, args))
137 assert "read_timeout" not in funcargs
138 funcargs.append("read_timeout=%s" % timeout)
140 funcdef = "def call_%s(%s):" % (name, utils.CommaJoin(funcargs))
141 for line in _WrapCode(funcdef):
146 _WriteDocstring(sw, name, timeout, kind, args, desc)
151 # In case line gets too long and is wrapped in a bad spot
155 buf.write("%s(" % postproc)
156 buf.write("self._Call(")
160 buf.write("node_list")
161 buf.write(", \"%s\", read_timeout, [%s])" %
162 (name, utils.CommaJoin(map(_MakeArgument, args))))
169 for line in _WrapCode(buf.getvalue()):
183 sw = utils.ShellWriter(buf)
187 for filename in sys.argv[1:]:
188 sw.Write("# Definitions from '%s'", filename)
190 module = build.LoadModule(filename)
192 # Call types are re-defined in definitions file to avoid imports. Verify
193 # here to ensure they're equal to local constants.
194 assert module.SINGLE == _SINGLE
195 assert module.MULTI == _MULTI
197 for (clsname, calls) in module.CALLS.items():
198 _WriteBaseClass(sw, clsname, calls)
203 if __name__ == "__main__":