Statistics
| Branch: | Tag: | Revision:

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()