Statistics
| Branch: | Tag: | Revision:

root / lib / rpc.py @ c70d2d9b

History | View | Annotate | Download (33.5 kB)

1 2f31098c Iustin Pop
#
2 a8083063 Iustin Pop
#
3 a8083063 Iustin Pop
4 a8083063 Iustin Pop
# Copyright (C) 2006, 2007 Google Inc.
5 a8083063 Iustin Pop
#
6 a8083063 Iustin Pop
# This program is free software; you can redistribute it and/or modify
7 a8083063 Iustin Pop
# it under the terms of the GNU General Public License as published by
8 a8083063 Iustin Pop
# the Free Software Foundation; either version 2 of the License, or
9 a8083063 Iustin Pop
# (at your option) any later version.
10 a8083063 Iustin Pop
#
11 a8083063 Iustin Pop
# This program is distributed in the hope that it will be useful, but
12 a8083063 Iustin Pop
# WITHOUT ANY WARRANTY; without even the implied warranty of
13 a8083063 Iustin Pop
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 a8083063 Iustin Pop
# General Public License for more details.
15 a8083063 Iustin Pop
#
16 a8083063 Iustin Pop
# You should have received a copy of the GNU General Public License
17 a8083063 Iustin Pop
# along with this program; if not, write to the Free Software
18 a8083063 Iustin Pop
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 a8083063 Iustin Pop
# 02110-1301, USA.
20 a8083063 Iustin Pop
21 a8083063 Iustin Pop
22 3ef3c771 Iustin Pop
"""Inter-node RPC library.
23 a8083063 Iustin Pop

24 a8083063 Iustin Pop
"""
25 a8083063 Iustin Pop
26 72737a7f Iustin Pop
# pylint: disable-msg=C0103,R0201,R0904
27 72737a7f Iustin Pop
# C0103: Invalid name, since call_ are not valid
28 72737a7f Iustin Pop
# R0201: Method could be a function, we keep all rpcs instance methods
29 72737a7f Iustin Pop
# as not to change them back and forth between static/instance methods
30 72737a7f Iustin Pop
# if they need to start using instance attributes
31 72737a7f Iustin Pop
# R0904: Too many public methods
32 a8083063 Iustin Pop
33 a8083063 Iustin Pop
import os
34 58b311ca Iustin Pop
import logging
35 12bce260 Michael Hanselmann
import zlib
36 12bce260 Michael Hanselmann
import base64
37 a8083063 Iustin Pop
38 a8083063 Iustin Pop
from ganeti import utils
39 a8083063 Iustin Pop
from ganeti import objects
40 ecfe9491 Michael Hanselmann
from ganeti import http
41 7c28c575 Michael Hanselmann
from ganeti import serializer
42 eafd8762 Michael Hanselmann
from ganeti import constants
43 781de953 Iustin Pop
from ganeti import errors
44 a8083063 Iustin Pop
45 fe267188 Iustin Pop
# pylint has a bug here, doesn't see this import
46 fe267188 Iustin Pop
import ganeti.http.client  # pylint: disable-msg=W0611
47 ae88ef45 Michael Hanselmann
48 a8083063 Iustin Pop
49 4331f6cd Michael Hanselmann
# Module level variable
50 4331f6cd Michael Hanselmann
_http_manager = None
51 4331f6cd Michael Hanselmann
52 4331f6cd Michael Hanselmann
53 4331f6cd Michael Hanselmann
def Init():
54 4331f6cd Michael Hanselmann
  """Initializes the module-global HTTP client manager.
55 4331f6cd Michael Hanselmann

56 4331f6cd Michael Hanselmann
  Must be called before using any RPC function.
57 4331f6cd Michael Hanselmann

58 4331f6cd Michael Hanselmann
  """
59 fe267188 Iustin Pop
  global _http_manager # pylint: disable-msg=W0603
60 4331f6cd Michael Hanselmann
61 4331f6cd Michael Hanselmann
  assert not _http_manager, "RPC module initialized more than once"
62 4331f6cd Michael Hanselmann
63 ae88ef45 Michael Hanselmann
  _http_manager = http.client.HttpClientManager()
64 4331f6cd Michael Hanselmann
65 4331f6cd Michael Hanselmann
66 4331f6cd Michael Hanselmann
def Shutdown():
67 4331f6cd Michael Hanselmann
  """Stops the module-global HTTP client manager.
68 4331f6cd Michael Hanselmann

69 4331f6cd Michael Hanselmann
  Must be called before quitting the program.
70 4331f6cd Michael Hanselmann

71 4331f6cd Michael Hanselmann
  """
72 fe267188 Iustin Pop
  global _http_manager # pylint: disable-msg=W0603
73 4331f6cd Michael Hanselmann
74 4331f6cd Michael Hanselmann
  if _http_manager:
75 4331f6cd Michael Hanselmann
    _http_manager.Shutdown()
76 4331f6cd Michael Hanselmann
    _http_manager = None
77 4331f6cd Michael Hanselmann
78 4331f6cd Michael Hanselmann
79 781de953 Iustin Pop
class RpcResult(object):
80 781de953 Iustin Pop
  """RPC Result class.
81 781de953 Iustin Pop

82 781de953 Iustin Pop
  This class holds an RPC result. It is needed since in multi-node
83 781de953 Iustin Pop
  calls we can't raise an exception just because one one out of many
84 781de953 Iustin Pop
  failed, and therefore we use this class to encapsulate the result.
85 781de953 Iustin Pop

86 5bbd3f7f Michael Hanselmann
  @ivar data: the data payload, for successful results, or None
87 ed83f5cc Iustin Pop
  @type failed: boolean
88 ed83f5cc Iustin Pop
  @ivar failed: whether the operation failed at RPC level (not
89 ed83f5cc Iustin Pop
      application level on the remote node)
90 ed83f5cc Iustin Pop
  @ivar call: the name of the RPC call
91 ed83f5cc Iustin Pop
  @ivar node: the name of the node to which we made the call
92 ed83f5cc Iustin Pop
  @ivar offline: whether the operation failed because the node was
93 ed83f5cc Iustin Pop
      offline, as opposed to actual failure; offline=True will always
94 ed83f5cc Iustin Pop
      imply failed=True, in order to allow simpler checking if
95 ed83f5cc Iustin Pop
      the user doesn't care about the exact failure mode
96 ed83f5cc Iustin Pop

97 781de953 Iustin Pop
  """
98 ed83f5cc Iustin Pop
  def __init__(self, data=None, failed=False, offline=False,
99 ed83f5cc Iustin Pop
               call=None, node=None):
100 781de953 Iustin Pop
    self.failed = failed
101 ed83f5cc Iustin Pop
    self.offline = offline
102 ed83f5cc Iustin Pop
    self.call = call
103 ed83f5cc Iustin Pop
    self.node = node
104 ed83f5cc Iustin Pop
    if offline:
105 ed83f5cc Iustin Pop
      self.failed = True
106 ed83f5cc Iustin Pop
      self.error = "Node is marked offline"
107 f2def43a Iustin Pop
      self.data = self.payload = None
108 ed83f5cc Iustin Pop
    elif failed:
109 781de953 Iustin Pop
      self.error = data
110 f2def43a Iustin Pop
      self.data = self.payload = None
111 781de953 Iustin Pop
    else:
112 781de953 Iustin Pop
      self.data = data
113 781de953 Iustin Pop
      self.error = None
114 f2def43a Iustin Pop
      if isinstance(data, (tuple, list)) and len(data) == 2:
115 f2def43a Iustin Pop
        self.payload = data[1]
116 f2def43a Iustin Pop
      else:
117 f2def43a Iustin Pop
        self.payload = None
118 781de953 Iustin Pop
119 781de953 Iustin Pop
  def Raise(self):
120 781de953 Iustin Pop
    """If the result has failed, raise an OpExecError.
121 781de953 Iustin Pop

122 781de953 Iustin Pop
    This is used so that LU code doesn't have to check for each
123 781de953 Iustin Pop
    result, but instead can call this function.
124 781de953 Iustin Pop

125 781de953 Iustin Pop
    """
126 781de953 Iustin Pop
    if self.failed:
127 781de953 Iustin Pop
      raise errors.OpExecError("Call '%s' to node '%s' has failed: %s" %
128 781de953 Iustin Pop
                               (self.call, self.node, self.error))
129 781de953 Iustin Pop
130 3247bbac Iustin Pop
  def RemoteFailMsg(self):
131 3247bbac Iustin Pop
    """Check if the remote procedure failed.
132 3247bbac Iustin Pop

133 3247bbac Iustin Pop
    This is valid only for RPC calls which return result of the form
134 3247bbac Iustin Pop
    (status, data | error_msg).
135 3247bbac Iustin Pop

136 3247bbac Iustin Pop
    @return: empty string for succcess, otherwise an error message
137 3247bbac Iustin Pop

138 3247bbac Iustin Pop
    """
139 3247bbac Iustin Pop
    def _EnsureErr(val):
140 3247bbac Iustin Pop
      """Helper to ensure we return a 'True' value for error."""
141 3247bbac Iustin Pop
      if val:
142 3247bbac Iustin Pop
        return val
143 3247bbac Iustin Pop
      else:
144 3247bbac Iustin Pop
        return "No error information"
145 3247bbac Iustin Pop
146 3247bbac Iustin Pop
    if self.failed:
147 3247bbac Iustin Pop
      return _EnsureErr(self.error)
148 3247bbac Iustin Pop
    if not isinstance(self.data, (tuple, list)):
149 3247bbac Iustin Pop
      return "Invalid result type (%s)" % type(self.data)
150 3247bbac Iustin Pop
    if len(self.data) != 2:
151 3247bbac Iustin Pop
      return "Invalid result length (%d), expected 2" % len(self.data)
152 3247bbac Iustin Pop
    if not self.data[0]:
153 3247bbac Iustin Pop
      return _EnsureErr(self.data[1])
154 3247bbac Iustin Pop
    return ""
155 3247bbac Iustin Pop
156 781de953 Iustin Pop
157 a8083063 Iustin Pop
class Client:
158 a8083063 Iustin Pop
  """RPC Client class.
159 a8083063 Iustin Pop

160 2f8598a5 Alexander Schreiber
  This class, given a (remote) method name, a list of parameters and a
161 a8083063 Iustin Pop
  list of nodes, will contact (in parallel) all nodes, and return a
162 a8083063 Iustin Pop
  dict of results (key: node name, value: result).
163 a8083063 Iustin Pop

164 5bbd3f7f Michael Hanselmann
  One current bug is that generic failure is still signaled by
165 a8083063 Iustin Pop
  'False' result, which is not good. This overloading of values can
166 a8083063 Iustin Pop
  cause bugs.
167 a8083063 Iustin Pop

168 a8083063 Iustin Pop
  """
169 160e2921 Iustin Pop
  def __init__(self, procedure, body, port):
170 a8083063 Iustin Pop
    self.procedure = procedure
171 160e2921 Iustin Pop
    self.body = body
172 160e2921 Iustin Pop
    self.port = port
173 ecfe9491 Michael Hanselmann
    self.nc = {}
174 a8083063 Iustin Pop
175 d57ae7f7 Michael Hanselmann
    self._ssl_params = \
176 d57ae7f7 Michael Hanselmann
      http.HttpSslParams(ssl_key_path=constants.SSL_CERT_FILE,
177 d57ae7f7 Michael Hanselmann
                         ssl_cert_path=constants.SSL_CERT_FILE)
178 d57ae7f7 Michael Hanselmann
179 bdf7d8c0 Iustin Pop
  def ConnectList(self, node_list, address_list=None):
180 a8083063 Iustin Pop
    """Add a list of nodes to the target nodes.
181 a8083063 Iustin Pop

182 3ef3c771 Iustin Pop
    @type node_list: list
183 3ef3c771 Iustin Pop
    @param node_list: the list of node names to connect
184 bdf7d8c0 Iustin Pop
    @type address_list: list or None
185 bdf7d8c0 Iustin Pop
    @keyword address_list: either None or a list with node addresses,
186 bdf7d8c0 Iustin Pop
        which must have the same length as the node list
187 3ef3c771 Iustin Pop

188 a8083063 Iustin Pop
    """
189 bdf7d8c0 Iustin Pop
    if address_list is None:
190 bdf7d8c0 Iustin Pop
      address_list = [None for _ in node_list]
191 bdf7d8c0 Iustin Pop
    else:
192 bdf7d8c0 Iustin Pop
      assert len(node_list) == len(address_list), \
193 bdf7d8c0 Iustin Pop
             "Name and address lists should have the same length"
194 bdf7d8c0 Iustin Pop
    for node, address in zip(node_list, address_list):
195 bdf7d8c0 Iustin Pop
      self.ConnectNode(node, address)
196 bdf7d8c0 Iustin Pop
197 bdf7d8c0 Iustin Pop
  def ConnectNode(self, name, address=None):
198 a8083063 Iustin Pop
    """Add a node to the target list.
199 a8083063 Iustin Pop

200 bdf7d8c0 Iustin Pop
    @type name: str
201 bdf7d8c0 Iustin Pop
    @param name: the node name
202 bdf7d8c0 Iustin Pop
    @type address: str
203 bdf7d8c0 Iustin Pop
    @keyword address: the node address, if known
204 bdf7d8c0 Iustin Pop

205 a8083063 Iustin Pop
    """
206 ecfe9491 Michael Hanselmann
    if address is None:
207 ecfe9491 Michael Hanselmann
      address = name
208 ecfe9491 Michael Hanselmann
209 ae88ef45 Michael Hanselmann
    self.nc[name] = \
210 ae88ef45 Michael Hanselmann
      http.client.HttpClientRequest(address, self.port, http.HTTP_PUT,
211 ae88ef45 Michael Hanselmann
                                    "/%s" % self.procedure,
212 ae88ef45 Michael Hanselmann
                                    post_data=self.body,
213 ae88ef45 Michael Hanselmann
                                    ssl_params=self._ssl_params,
214 ae88ef45 Michael Hanselmann
                                    ssl_verify_peer=True)
215 a8083063 Iustin Pop
216 3ef3c771 Iustin Pop
  def GetResults(self):
217 ecfe9491 Michael Hanselmann
    """Call nodes and return results.
218 ecfe9491 Michael Hanselmann

219 ecfe9491 Michael Hanselmann
    @rtype: list
220 5fcc718f Iustin Pop
    @return: List of RPC results
221 a8083063 Iustin Pop

222 a8083063 Iustin Pop
    """
223 5bbd3f7f Michael Hanselmann
    assert _http_manager, "RPC module not initialized"
224 4331f6cd Michael Hanselmann
225 4331f6cd Michael Hanselmann
    _http_manager.ExecRequests(self.nc.values())
226 a8083063 Iustin Pop
227 ecfe9491 Michael Hanselmann
    results = {}
228 a8083063 Iustin Pop
229 ecfe9491 Michael Hanselmann
    for name, req in self.nc.iteritems():
230 ae88ef45 Michael Hanselmann
      if req.success and req.resp_status_code == http.HTTP_OK:
231 781de953 Iustin Pop
        results[name] = RpcResult(data=serializer.LoadJson(req.resp_body),
232 781de953 Iustin Pop
                                  node=name, call=self.procedure)
233 ecfe9491 Michael Hanselmann
        continue
234 a8083063 Iustin Pop
235 d57ae7f7 Michael Hanselmann
      # TODO: Better error reporting
236 ecfe9491 Michael Hanselmann
      if req.error:
237 ecfe9491 Michael Hanselmann
        msg = req.error
238 ecfe9491 Michael Hanselmann
      else:
239 ecfe9491 Michael Hanselmann
        msg = req.resp_body
240 ecfe9491 Michael Hanselmann
241 1b8acf70 Iustin Pop
      logging.error("RPC error in %s from node %s: %s",
242 1b8acf70 Iustin Pop
                    self.procedure, name, msg)
243 781de953 Iustin Pop
      results[name] = RpcResult(data=msg, failed=True, node=name,
244 781de953 Iustin Pop
                                call=self.procedure)
245 ecfe9491 Michael Hanselmann
246 ecfe9491 Michael Hanselmann
    return results
247 a8083063 Iustin Pop
248 a8083063 Iustin Pop
249 72737a7f Iustin Pop
class RpcRunner(object):
250 72737a7f Iustin Pop
  """RPC runner class"""
251 a8083063 Iustin Pop
252 72737a7f Iustin Pop
  def __init__(self, cfg):
253 72737a7f Iustin Pop
    """Initialized the rpc runner.
254 a8083063 Iustin Pop

255 72737a7f Iustin Pop
    @type cfg:  C{config.ConfigWriter}
256 72737a7f Iustin Pop
    @param cfg: the configuration object that will be used to get data
257 72737a7f Iustin Pop
                about the cluster
258 a8083063 Iustin Pop

259 72737a7f Iustin Pop
    """
260 72737a7f Iustin Pop
    self._cfg = cfg
261 160e2921 Iustin Pop
    self.port = utils.GetNodeDaemonPort()
262 a8083063 Iustin Pop
263 0eca8e0c Iustin Pop
  def _InstDict(self, instance, hvp=None, bep=None):
264 26ba2bd8 Iustin Pop
    """Convert the given instance to a dict.
265 26ba2bd8 Iustin Pop

266 26ba2bd8 Iustin Pop
    This is done via the instance's ToDict() method and additionally
267 26ba2bd8 Iustin Pop
    we fill the hvparams with the cluster defaults.
268 26ba2bd8 Iustin Pop

269 26ba2bd8 Iustin Pop
    @type instance: L{objects.Instance}
270 26ba2bd8 Iustin Pop
    @param instance: an Instance object
271 0eca8e0c Iustin Pop
    @type hvp: dict or None
272 5bbd3f7f Michael Hanselmann
    @param hvp: a dictionary with overridden hypervisor parameters
273 0eca8e0c Iustin Pop
    @type bep: dict or None
274 5bbd3f7f Michael Hanselmann
    @param bep: a dictionary with overridden backend parameters
275 26ba2bd8 Iustin Pop
    @rtype: dict
276 26ba2bd8 Iustin Pop
    @return: the instance dict, with the hvparams filled with the
277 26ba2bd8 Iustin Pop
        cluster defaults
278 26ba2bd8 Iustin Pop

279 26ba2bd8 Iustin Pop
    """
280 26ba2bd8 Iustin Pop
    idict = instance.ToDict()
281 5b442704 Iustin Pop
    cluster = self._cfg.GetClusterInfo()
282 5b442704 Iustin Pop
    idict["hvparams"] = cluster.FillHV(instance)
283 0eca8e0c Iustin Pop
    if hvp is not None:
284 0eca8e0c Iustin Pop
      idict["hvparams"].update(hvp)
285 5b442704 Iustin Pop
    idict["beparams"] = cluster.FillBE(instance)
286 0eca8e0c Iustin Pop
    if bep is not None:
287 0eca8e0c Iustin Pop
      idict["beparams"].update(bep)
288 26ba2bd8 Iustin Pop
    return idict
289 26ba2bd8 Iustin Pop
290 84b45587 Iustin Pop
  def _ConnectList(self, client, node_list, call):
291 25348212 Iustin Pop
    """Helper for computing node addresses.
292 25348212 Iustin Pop

293 6af6270a Iustin Pop
    @type client: L{ganeti.rpc.Client}
294 25348212 Iustin Pop
    @param client: a C{Client} instance
295 25348212 Iustin Pop
    @type node_list: list
296 25348212 Iustin Pop
    @param node_list: the node list we should connect
297 84b45587 Iustin Pop
    @type call: string
298 84b45587 Iustin Pop
    @param call: the name of the remote procedure call, for filling in
299 84b45587 Iustin Pop
        correctly any eventual offline nodes' results
300 25348212 Iustin Pop

301 25348212 Iustin Pop
    """
302 25348212 Iustin Pop
    all_nodes = self._cfg.GetAllNodesInfo()
303 ed83f5cc Iustin Pop
    name_list = []
304 25348212 Iustin Pop
    addr_list = []
305 ed83f5cc Iustin Pop
    skip_dict = {}
306 25348212 Iustin Pop
    for node in node_list:
307 25348212 Iustin Pop
      if node in all_nodes:
308 ed83f5cc Iustin Pop
        if all_nodes[node].offline:
309 84b45587 Iustin Pop
          skip_dict[node] = RpcResult(node=node, offline=True, call=call)
310 ed83f5cc Iustin Pop
          continue
311 25348212 Iustin Pop
        val = all_nodes[node].primary_ip
312 25348212 Iustin Pop
      else:
313 25348212 Iustin Pop
        val = None
314 25348212 Iustin Pop
      addr_list.append(val)
315 ed83f5cc Iustin Pop
      name_list.append(node)
316 ed83f5cc Iustin Pop
    if name_list:
317 ed83f5cc Iustin Pop
      client.ConnectList(name_list, address_list=addr_list)
318 ed83f5cc Iustin Pop
    return skip_dict
319 25348212 Iustin Pop
320 84b45587 Iustin Pop
  def _ConnectNode(self, client, node, call):
321 25348212 Iustin Pop
    """Helper for computing one node's address.
322 25348212 Iustin Pop

323 6af6270a Iustin Pop
    @type client: L{ganeti.rpc.Client}
324 25348212 Iustin Pop
    @param client: a C{Client} instance
325 25348212 Iustin Pop
    @type node: str
326 25348212 Iustin Pop
    @param node: the node we should connect
327 84b45587 Iustin Pop
    @type call: string
328 84b45587 Iustin Pop
    @param call: the name of the remote procedure call, for filling in
329 84b45587 Iustin Pop
        correctly any eventual offline nodes' results
330 25348212 Iustin Pop

331 25348212 Iustin Pop
    """
332 25348212 Iustin Pop
    node_info = self._cfg.GetNodeInfo(node)
333 25348212 Iustin Pop
    if node_info is not None:
334 ed83f5cc Iustin Pop
      if node_info.offline:
335 84b45587 Iustin Pop
        return RpcResult(node=node, offline=True, call=call)
336 25348212 Iustin Pop
      addr = node_info.primary_ip
337 25348212 Iustin Pop
    else:
338 25348212 Iustin Pop
      addr = None
339 25348212 Iustin Pop
    client.ConnectNode(node, address=addr)
340 25348212 Iustin Pop
341 ed83f5cc Iustin Pop
  def _MultiNodeCall(self, node_list, procedure, args):
342 160e2921 Iustin Pop
    """Helper for making a multi-node call
343 160e2921 Iustin Pop

344 160e2921 Iustin Pop
    """
345 160e2921 Iustin Pop
    body = serializer.DumpJson(args, indent=False)
346 160e2921 Iustin Pop
    c = Client(procedure, body, self.port)
347 84b45587 Iustin Pop
    skip_dict = self._ConnectList(c, node_list, procedure)
348 ed83f5cc Iustin Pop
    skip_dict.update(c.GetResults())
349 ed83f5cc Iustin Pop
    return skip_dict
350 9a525d83 Michael Hanselmann
351 9a525d83 Michael Hanselmann
  @classmethod
352 9a525d83 Michael Hanselmann
  def _StaticMultiNodeCall(cls, node_list, procedure, args,
353 9a525d83 Michael Hanselmann
                           address_list=None):
354 160e2921 Iustin Pop
    """Helper for making a multi-node static call
355 160e2921 Iustin Pop

356 160e2921 Iustin Pop
    """
357 160e2921 Iustin Pop
    body = serializer.DumpJson(args, indent=False)
358 160e2921 Iustin Pop
    c = Client(procedure, body, utils.GetNodeDaemonPort())
359 9a525d83 Michael Hanselmann
    c.ConnectList(node_list, address_list=address_list)
360 9a525d83 Michael Hanselmann
    return c.GetResults()
361 9a525d83 Michael Hanselmann
362 9a525d83 Michael Hanselmann
  def _SingleNodeCall(self, node, procedure, args):
363 160e2921 Iustin Pop
    """Helper for making a single-node call
364 9a525d83 Michael Hanselmann

365 9a525d83 Michael Hanselmann
    """
366 160e2921 Iustin Pop
    body = serializer.DumpJson(args, indent=False)
367 160e2921 Iustin Pop
    c = Client(procedure, body, self.port)
368 84b45587 Iustin Pop
    result = self._ConnectNode(c, node, procedure)
369 ed83f5cc Iustin Pop
    if result is None:
370 ed83f5cc Iustin Pop
      # we did connect, node is not offline
371 ed83f5cc Iustin Pop
      result = c.GetResults()[node]
372 ed83f5cc Iustin Pop
    return result
373 9a525d83 Michael Hanselmann
374 9a525d83 Michael Hanselmann
  @classmethod
375 9a525d83 Michael Hanselmann
  def _StaticSingleNodeCall(cls, node, procedure, args):
376 160e2921 Iustin Pop
    """Helper for making a single-node static call
377 9a525d83 Michael Hanselmann

378 9a525d83 Michael Hanselmann
    """
379 160e2921 Iustin Pop
    body = serializer.DumpJson(args, indent=False)
380 160e2921 Iustin Pop
    c = Client(procedure, body, utils.GetNodeDaemonPort())
381 3097c858 Michael Hanselmann
    c.ConnectNode(node)
382 ed83f5cc Iustin Pop
    return c.GetResults()[node]
383 9a525d83 Michael Hanselmann
384 12bce260 Michael Hanselmann
  @staticmethod
385 12bce260 Michael Hanselmann
  def _Compress(data):
386 12bce260 Michael Hanselmann
    """Compresses a string for transport over RPC.
387 12bce260 Michael Hanselmann

388 12bce260 Michael Hanselmann
    Small amounts of data are not compressed.
389 12bce260 Michael Hanselmann

390 12bce260 Michael Hanselmann
    @type data: str
391 12bce260 Michael Hanselmann
    @param data: Data
392 12bce260 Michael Hanselmann
    @rtype: tuple
393 12bce260 Michael Hanselmann
    @return: Encoded data to send
394 12bce260 Michael Hanselmann

395 12bce260 Michael Hanselmann
    """
396 12bce260 Michael Hanselmann
    # Small amounts of data are not compressed
397 12bce260 Michael Hanselmann
    if len(data) < 512:
398 12bce260 Michael Hanselmann
      return (constants.RPC_ENCODING_NONE, data)
399 12bce260 Michael Hanselmann
400 12bce260 Michael Hanselmann
    # Compress with zlib and encode in base64
401 12bce260 Michael Hanselmann
    return (constants.RPC_ENCODING_ZLIB_BASE64,
402 12bce260 Michael Hanselmann
            base64.b64encode(zlib.compress(data, 3)))
403 12bce260 Michael Hanselmann
404 781de953 Iustin Pop
  #
405 781de953 Iustin Pop
  # Begin RPC calls
406 781de953 Iustin Pop
  #
407 781de953 Iustin Pop
408 72737a7f Iustin Pop
  def call_volume_list(self, node_list, vg_name):
409 72737a7f Iustin Pop
    """Gets the logical volumes present in a given volume group.
410 a8083063 Iustin Pop

411 72737a7f Iustin Pop
    This is a multi-node call.
412 a8083063 Iustin Pop

413 72737a7f Iustin Pop
    """
414 9a525d83 Michael Hanselmann
    return self._MultiNodeCall(node_list, "volume_list", [vg_name])
415 a8083063 Iustin Pop
416 72737a7f Iustin Pop
  def call_vg_list(self, node_list):
417 72737a7f Iustin Pop
    """Gets the volume group list.
418 a8083063 Iustin Pop

419 72737a7f Iustin Pop
    This is a multi-node call.
420 a8083063 Iustin Pop

421 72737a7f Iustin Pop
    """
422 9a525d83 Michael Hanselmann
    return self._MultiNodeCall(node_list, "vg_list", [])
423 a8083063 Iustin Pop
424 72737a7f Iustin Pop
  def call_bridges_exist(self, node, bridges_list):
425 72737a7f Iustin Pop
    """Checks if a node has all the bridges given.
426 a8083063 Iustin Pop

427 72737a7f Iustin Pop
    This method checks if all bridges given in the bridges_list are
428 72737a7f Iustin Pop
    present on the remote node, so that an instance that uses interfaces
429 72737a7f Iustin Pop
    on those bridges can be started.
430 a8083063 Iustin Pop

431 72737a7f Iustin Pop
    This is a single-node call.
432 a8083063 Iustin Pop

433 72737a7f Iustin Pop
    """
434 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "bridges_exist", [bridges_list])
435 a8083063 Iustin Pop
436 0eca8e0c Iustin Pop
  def call_instance_start(self, node, instance, hvp, bep):
437 72737a7f Iustin Pop
    """Starts an instance.
438 a8083063 Iustin Pop

439 72737a7f Iustin Pop
    This is a single-node call.
440 a8083063 Iustin Pop

441 72737a7f Iustin Pop
    """
442 0eca8e0c Iustin Pop
    idict = self._InstDict(instance, hvp=hvp, bep=bep)
443 0eca8e0c Iustin Pop
    return self._SingleNodeCall(node, "instance_start", [idict])
444 a8083063 Iustin Pop
445 72737a7f Iustin Pop
  def call_instance_shutdown(self, node, instance):
446 72737a7f Iustin Pop
    """Stops an instance.
447 a8083063 Iustin Pop

448 72737a7f Iustin Pop
    This is a single-node call.
449 2a10865c Iustin Pop

450 72737a7f Iustin Pop
    """
451 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "instance_shutdown",
452 9a525d83 Michael Hanselmann
                                [self._InstDict(instance)])
453 2a10865c Iustin Pop
454 6906a9d8 Guido Trotter
  def call_migration_info(self, node, instance):
455 6906a9d8 Guido Trotter
    """Gather the information necessary to prepare an instance migration.
456 6906a9d8 Guido Trotter

457 6906a9d8 Guido Trotter
    This is a single-node call.
458 6906a9d8 Guido Trotter

459 6906a9d8 Guido Trotter
    @type node: string
460 6906a9d8 Guido Trotter
    @param node: the node on which the instance is currently running
461 6906a9d8 Guido Trotter
    @type instance: C{objects.Instance}
462 6906a9d8 Guido Trotter
    @param instance: the instance definition
463 6906a9d8 Guido Trotter

464 6906a9d8 Guido Trotter
    """
465 6906a9d8 Guido Trotter
    return self._SingleNodeCall(node, "migration_info",
466 6906a9d8 Guido Trotter
                                [self._InstDict(instance)])
467 6906a9d8 Guido Trotter
468 6906a9d8 Guido Trotter
  def call_accept_instance(self, node, instance, info, target):
469 6906a9d8 Guido Trotter
    """Prepare a node to accept an instance.
470 6906a9d8 Guido Trotter

471 6906a9d8 Guido Trotter
    This is a single-node call.
472 6906a9d8 Guido Trotter

473 6906a9d8 Guido Trotter
    @type node: string
474 6906a9d8 Guido Trotter
    @param node: the target node for the migration
475 6906a9d8 Guido Trotter
    @type instance: C{objects.Instance}
476 6906a9d8 Guido Trotter
    @param instance: the instance definition
477 6906a9d8 Guido Trotter
    @type info: opaque/hypervisor specific (string/data)
478 6906a9d8 Guido Trotter
    @param info: result for the call_migration_info call
479 6906a9d8 Guido Trotter
    @type target: string
480 6906a9d8 Guido Trotter
    @param target: target hostname (usually ip address) (on the node itself)
481 6906a9d8 Guido Trotter

482 6906a9d8 Guido Trotter
    """
483 6906a9d8 Guido Trotter
    return self._SingleNodeCall(node, "accept_instance",
484 6906a9d8 Guido Trotter
                                [self._InstDict(instance), info, target])
485 6906a9d8 Guido Trotter
486 6906a9d8 Guido Trotter
  def call_finalize_migration(self, node, instance, info, success):
487 6906a9d8 Guido Trotter
    """Finalize any target-node migration specific operation.
488 6906a9d8 Guido Trotter

489 6906a9d8 Guido Trotter
    This is called both in case of a successful migration and in case of error
490 6906a9d8 Guido Trotter
    (in which case it should abort the migration).
491 6906a9d8 Guido Trotter

492 6906a9d8 Guido Trotter
    This is a single-node call.
493 6906a9d8 Guido Trotter

494 6906a9d8 Guido Trotter
    @type node: string
495 6906a9d8 Guido Trotter
    @param node: the target node for the migration
496 6906a9d8 Guido Trotter
    @type instance: C{objects.Instance}
497 6906a9d8 Guido Trotter
    @param instance: the instance definition
498 6906a9d8 Guido Trotter
    @type info: opaque/hypervisor specific (string/data)
499 6906a9d8 Guido Trotter
    @param info: result for the call_migration_info call
500 6906a9d8 Guido Trotter
    @type success: boolean
501 6906a9d8 Guido Trotter
    @param success: whether the migration was a success or a failure
502 6906a9d8 Guido Trotter

503 6906a9d8 Guido Trotter
    """
504 6906a9d8 Guido Trotter
    return self._SingleNodeCall(node, "finalize_migration",
505 6906a9d8 Guido Trotter
                                [self._InstDict(instance), info, success])
506 6906a9d8 Guido Trotter
507 72737a7f Iustin Pop
  def call_instance_migrate(self, node, instance, target, live):
508 72737a7f Iustin Pop
    """Migrate an instance.
509 2a10865c Iustin Pop

510 72737a7f Iustin Pop
    This is a single-node call.
511 2a10865c Iustin Pop

512 72737a7f Iustin Pop
    @type node: string
513 72737a7f Iustin Pop
    @param node: the node on which the instance is currently running
514 72737a7f Iustin Pop
    @type instance: C{objects.Instance}
515 72737a7f Iustin Pop
    @param instance: the instance definition
516 72737a7f Iustin Pop
    @type target: string
517 72737a7f Iustin Pop
    @param target: the target node name
518 72737a7f Iustin Pop
    @type live: boolean
519 72737a7f Iustin Pop
    @param live: whether the migration should be done live or not (the
520 72737a7f Iustin Pop
        interpretation of this parameter is left to the hypervisor)
521 007a2f3e Alexander Schreiber

522 72737a7f Iustin Pop
    """
523 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "instance_migrate",
524 9a525d83 Michael Hanselmann
                                [self._InstDict(instance), target, live])
525 007a2f3e Alexander Schreiber
526 07813a9e Iustin Pop
  def call_instance_reboot(self, node, instance, reboot_type):
527 72737a7f Iustin Pop
    """Reboots an instance.
528 007a2f3e Alexander Schreiber

529 72737a7f Iustin Pop
    This is a single-node call.
530 a8083063 Iustin Pop

531 72737a7f Iustin Pop
    """
532 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "instance_reboot",
533 07813a9e Iustin Pop
                                [self._InstDict(instance), reboot_type])
534 a8083063 Iustin Pop
535 d15a9ad3 Guido Trotter
  def call_instance_os_add(self, node, inst):
536 72737a7f Iustin Pop
    """Installs an OS on the given instance.
537 a8083063 Iustin Pop

538 72737a7f Iustin Pop
    This is a single-node call.
539 decd5f45 Iustin Pop

540 72737a7f Iustin Pop
    """
541 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "instance_os_add",
542 9a525d83 Michael Hanselmann
                                [self._InstDict(inst)])
543 decd5f45 Iustin Pop
544 d15a9ad3 Guido Trotter
  def call_instance_run_rename(self, node, inst, old_name):
545 72737a7f Iustin Pop
    """Run the OS rename script for an instance.
546 decd5f45 Iustin Pop

547 72737a7f Iustin Pop
    This is a single-node call.
548 a8083063 Iustin Pop

549 72737a7f Iustin Pop
    """
550 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "instance_run_rename",
551 9a525d83 Michael Hanselmann
                                [self._InstDict(inst), old_name])
552 a8083063 Iustin Pop
553 72737a7f Iustin Pop
  def call_instance_info(self, node, instance, hname):
554 72737a7f Iustin Pop
    """Returns information about a single instance.
555 a8083063 Iustin Pop

556 72737a7f Iustin Pop
    This is a single-node call.
557 a8083063 Iustin Pop

558 9a525d83 Michael Hanselmann
    @type node: list
559 9a525d83 Michael Hanselmann
    @param node: the list of nodes to query
560 72737a7f Iustin Pop
    @type instance: string
561 72737a7f Iustin Pop
    @param instance: the instance name
562 72737a7f Iustin Pop
    @type hname: string
563 72737a7f Iustin Pop
    @param hname: the hypervisor type of the instance
564 a8083063 Iustin Pop

565 72737a7f Iustin Pop
    """
566 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "instance_info", [instance, hname])
567 e69d05fd Iustin Pop
568 56e7640c Iustin Pop
  def call_instance_migratable(self, node, instance):
569 56e7640c Iustin Pop
    """Checks whether the given instance can be migrated.
570 56e7640c Iustin Pop

571 56e7640c Iustin Pop
    This is a single-node call.
572 56e7640c Iustin Pop

573 56e7640c Iustin Pop
    @param node: the node to query
574 56e7640c Iustin Pop
    @type instance: L{objects.Instance}
575 56e7640c Iustin Pop
    @param instance: the instance to check
576 56e7640c Iustin Pop

577 56e7640c Iustin Pop

578 56e7640c Iustin Pop
    """
579 56e7640c Iustin Pop
    return self._SingleNodeCall(node, "instance_migratable",
580 56e7640c Iustin Pop
                                [self._InstDict(instance)])
581 56e7640c Iustin Pop
582 72737a7f Iustin Pop
  def call_all_instances_info(self, node_list, hypervisor_list):
583 72737a7f Iustin Pop
    """Returns information about all instances on the given nodes.
584 a8083063 Iustin Pop

585 72737a7f Iustin Pop
    This is a multi-node call.
586 a8083063 Iustin Pop

587 72737a7f Iustin Pop
    @type node_list: list
588 72737a7f Iustin Pop
    @param node_list: the list of nodes to query
589 72737a7f Iustin Pop
    @type hypervisor_list: list
590 72737a7f Iustin Pop
    @param hypervisor_list: the hypervisors to query for instances
591 a8083063 Iustin Pop

592 72737a7f Iustin Pop
    """
593 9a525d83 Michael Hanselmann
    return self._MultiNodeCall(node_list, "all_instances_info",
594 9a525d83 Michael Hanselmann
                               [hypervisor_list])
595 e69d05fd Iustin Pop
596 72737a7f Iustin Pop
  def call_instance_list(self, node_list, hypervisor_list):
597 72737a7f Iustin Pop
    """Returns the list of running instances on a given node.
598 a8083063 Iustin Pop

599 72737a7f Iustin Pop
    This is a multi-node call.
600 a8083063 Iustin Pop

601 72737a7f Iustin Pop
    @type node_list: list
602 72737a7f Iustin Pop
    @param node_list: the list of nodes to query
603 72737a7f Iustin Pop
    @type hypervisor_list: list
604 72737a7f Iustin Pop
    @param hypervisor_list: the hypervisors to query for instances
605 16abfbc2 Alexander Schreiber

606 72737a7f Iustin Pop
    """
607 9a525d83 Michael Hanselmann
    return self._MultiNodeCall(node_list, "instance_list", [hypervisor_list])
608 16abfbc2 Alexander Schreiber
609 72737a7f Iustin Pop
  def call_node_tcp_ping(self, node, source, target, port, timeout,
610 72737a7f Iustin Pop
                         live_port_needed):
611 72737a7f Iustin Pop
    """Do a TcpPing on the remote node
612 a8083063 Iustin Pop

613 72737a7f Iustin Pop
    This is a single-node call.
614 caad16e2 Iustin Pop

615 72737a7f Iustin Pop
    """
616 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "node_tcp_ping",
617 9a525d83 Michael Hanselmann
                                [source, target, port, timeout,
618 72737a7f Iustin Pop
                                 live_port_needed])
619 a8083063 Iustin Pop
620 caad16e2 Iustin Pop
  def call_node_has_ip_address(self, node, address):
621 caad16e2 Iustin Pop
    """Checks if a node has the given IP address.
622 caad16e2 Iustin Pop

623 caad16e2 Iustin Pop
    This is a single-node call.
624 caad16e2 Iustin Pop

625 caad16e2 Iustin Pop
    """
626 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "node_has_ip_address", [address])
627 a8083063 Iustin Pop
628 72737a7f Iustin Pop
  def call_node_info(self, node_list, vg_name, hypervisor_type):
629 72737a7f Iustin Pop
    """Return node information.
630 e69d05fd Iustin Pop

631 72737a7f Iustin Pop
    This will return memory information and volume group size and free
632 72737a7f Iustin Pop
    space.
633 a8083063 Iustin Pop

634 72737a7f Iustin Pop
    This is a multi-node call.
635 a8083063 Iustin Pop

636 72737a7f Iustin Pop
    @type node_list: list
637 72737a7f Iustin Pop
    @param node_list: the list of nodes to query
638 c41eea6e Iustin Pop
    @type vg_name: C{string}
639 c41eea6e Iustin Pop
    @param vg_name: the name of the volume group to ask for disk space
640 72737a7f Iustin Pop
        information
641 72737a7f Iustin Pop
    @type hypervisor_type: C{str}
642 72737a7f Iustin Pop
    @param hypervisor_type: the name of the hypervisor to ask for
643 72737a7f Iustin Pop
        memory information
644 a8083063 Iustin Pop

645 72737a7f Iustin Pop
    """
646 9a525d83 Michael Hanselmann
    retux = self._MultiNodeCall(node_list, "node_info",
647 9a525d83 Michael Hanselmann
                                [vg_name, hypervisor_type])
648 a8083063 Iustin Pop
649 781de953 Iustin Pop
    for result in retux.itervalues():
650 781de953 Iustin Pop
      if result.failed or not isinstance(result.data, dict):
651 781de953 Iustin Pop
        result.data = {}
652 186ec53c Iustin Pop
      if result.offline:
653 186ec53c Iustin Pop
        log_name = None
654 186ec53c Iustin Pop
      else:
655 186ec53c Iustin Pop
        log_name = "call_node_info"
656 781de953 Iustin Pop
657 781de953 Iustin Pop
      utils.CheckDict(result.data, {
658 781de953 Iustin Pop
        'memory_total' : '-',
659 781de953 Iustin Pop
        'memory_dom0' : '-',
660 781de953 Iustin Pop
        'memory_free' : '-',
661 781de953 Iustin Pop
        'vg_size' : 'node_unreachable',
662 781de953 Iustin Pop
        'vg_free' : '-',
663 186ec53c Iustin Pop
        }, log_name)
664 72737a7f Iustin Pop
    return retux
665 a8083063 Iustin Pop
666 72737a7f Iustin Pop
  def call_node_add(self, node, dsa, dsapub, rsa, rsapub, ssh, sshpub):
667 72737a7f Iustin Pop
    """Add a node to the cluster.
668 a8083063 Iustin Pop

669 72737a7f Iustin Pop
    This is a single-node call.
670 a8083063 Iustin Pop

671 72737a7f Iustin Pop
    """
672 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "node_add",
673 9a525d83 Michael Hanselmann
                                [dsa, dsapub, rsa, rsapub, ssh, sshpub])
674 a8083063 Iustin Pop
675 72737a7f Iustin Pop
  def call_node_verify(self, node_list, checkdict, cluster_name):
676 72737a7f Iustin Pop
    """Request verification of given parameters.
677 a8083063 Iustin Pop

678 72737a7f Iustin Pop
    This is a multi-node call.
679 a8083063 Iustin Pop

680 72737a7f Iustin Pop
    """
681 9a525d83 Michael Hanselmann
    return self._MultiNodeCall(node_list, "node_verify",
682 9a525d83 Michael Hanselmann
                               [checkdict, cluster_name])
683 a8083063 Iustin Pop
684 9a525d83 Michael Hanselmann
  @classmethod
685 2503680f Guido Trotter
  def call_node_start_master(cls, node, start_daemons, no_voting):
686 72737a7f Iustin Pop
    """Tells a node to activate itself as a master.
687 a8083063 Iustin Pop

688 72737a7f Iustin Pop
    This is a single-node call.
689 a8083063 Iustin Pop

690 72737a7f Iustin Pop
    """
691 9a525d83 Michael Hanselmann
    return cls._StaticSingleNodeCall(node, "node_start_master",
692 2503680f Guido Trotter
                                     [start_daemons, no_voting])
693 a8083063 Iustin Pop
694 9a525d83 Michael Hanselmann
  @classmethod
695 9a525d83 Michael Hanselmann
  def call_node_stop_master(cls, node, stop_daemons):
696 72737a7f Iustin Pop
    """Tells a node to demote itself from master status.
697 a8083063 Iustin Pop

698 72737a7f Iustin Pop
    This is a single-node call.
699 4e071d3b Iustin Pop

700 72737a7f Iustin Pop
    """
701 9a525d83 Michael Hanselmann
    return cls._StaticSingleNodeCall(node, "node_stop_master", [stop_daemons])
702 4e071d3b Iustin Pop
703 9a525d83 Michael Hanselmann
  @classmethod
704 9a525d83 Michael Hanselmann
  def call_master_info(cls, node_list):
705 72737a7f Iustin Pop
    """Query master info.
706 4e071d3b Iustin Pop

707 72737a7f Iustin Pop
    This is a multi-node call.
708 a8083063 Iustin Pop

709 72737a7f Iustin Pop
    """
710 72737a7f Iustin Pop
    # TODO: should this method query down nodes?
711 9a525d83 Michael Hanselmann
    return cls._StaticMultiNodeCall(node_list, "master_info", [])
712 a8083063 Iustin Pop
713 72737a7f Iustin Pop
  def call_version(self, node_list):
714 72737a7f Iustin Pop
    """Query node version.
715 a8083063 Iustin Pop

716 72737a7f Iustin Pop
    This is a multi-node call.
717 a8083063 Iustin Pop

718 72737a7f Iustin Pop
    """
719 9a525d83 Michael Hanselmann
    return self._MultiNodeCall(node_list, "version", [])
720 a8083063 Iustin Pop
721 72737a7f Iustin Pop
  def call_blockdev_create(self, node, bdev, size, owner, on_primary, info):
722 72737a7f Iustin Pop
    """Request creation of a given block device.
723 a8083063 Iustin Pop

724 72737a7f Iustin Pop
    This is a single-node call.
725 a8083063 Iustin Pop

726 72737a7f Iustin Pop
    """
727 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "blockdev_create",
728 9a525d83 Michael Hanselmann
                                [bdev.ToDict(), size, owner, on_primary, info])
729 a8083063 Iustin Pop
730 72737a7f Iustin Pop
  def call_blockdev_remove(self, node, bdev):
731 72737a7f Iustin Pop
    """Request removal of a given block device.
732 a8083063 Iustin Pop

733 72737a7f Iustin Pop
    This is a single-node call.
734 f3e513ad Iustin Pop

735 72737a7f Iustin Pop
    """
736 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "blockdev_remove", [bdev.ToDict()])
737 f3e513ad Iustin Pop
738 72737a7f Iustin Pop
  def call_blockdev_rename(self, node, devlist):
739 72737a7f Iustin Pop
    """Request rename of the given block devices.
740 f3e513ad Iustin Pop

741 72737a7f Iustin Pop
    This is a single-node call.
742 a8083063 Iustin Pop

743 72737a7f Iustin Pop
    """
744 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "blockdev_rename",
745 9a525d83 Michael Hanselmann
                                [(d.ToDict(), uid) for d, uid in devlist])
746 a8083063 Iustin Pop
747 72737a7f Iustin Pop
  def call_blockdev_assemble(self, node, disk, owner, on_primary):
748 72737a7f Iustin Pop
    """Request assembling of a given block device.
749 a8083063 Iustin Pop

750 72737a7f Iustin Pop
    This is a single-node call.
751 a8083063 Iustin Pop

752 72737a7f Iustin Pop
    """
753 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "blockdev_assemble",
754 9a525d83 Michael Hanselmann
                                [disk.ToDict(), owner, on_primary])
755 a8083063 Iustin Pop
756 72737a7f Iustin Pop
  def call_blockdev_shutdown(self, node, disk):
757 72737a7f Iustin Pop
    """Request shutdown of a given block device.
758 a8083063 Iustin Pop

759 72737a7f Iustin Pop
    This is a single-node call.
760 a8083063 Iustin Pop

761 72737a7f Iustin Pop
    """
762 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "blockdev_shutdown", [disk.ToDict()])
763 a8083063 Iustin Pop
764 72737a7f Iustin Pop
  def call_blockdev_addchildren(self, node, bdev, ndevs):
765 72737a7f Iustin Pop
    """Request adding a list of children to a (mirroring) device.
766 a8083063 Iustin Pop

767 72737a7f Iustin Pop
    This is a single-node call.
768 a8083063 Iustin Pop

769 72737a7f Iustin Pop
    """
770 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "blockdev_addchildren",
771 9a525d83 Michael Hanselmann
                                [bdev.ToDict(),
772 9a525d83 Michael Hanselmann
                                 [disk.ToDict() for disk in ndevs]])
773 a8083063 Iustin Pop
774 72737a7f Iustin Pop
  def call_blockdev_removechildren(self, node, bdev, ndevs):
775 72737a7f Iustin Pop
    """Request removing a list of children from a (mirroring) device.
776 a8083063 Iustin Pop

777 72737a7f Iustin Pop
    This is a single-node call.
778 a8083063 Iustin Pop

779 72737a7f Iustin Pop
    """
780 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "blockdev_removechildren",
781 9a525d83 Michael Hanselmann
                                [bdev.ToDict(),
782 9a525d83 Michael Hanselmann
                                 [disk.ToDict() for disk in ndevs]])
783 a8083063 Iustin Pop
784 72737a7f Iustin Pop
  def call_blockdev_getmirrorstatus(self, node, disks):
785 72737a7f Iustin Pop
    """Request status of a (mirroring) device.
786 a8083063 Iustin Pop

787 72737a7f Iustin Pop
    This is a single-node call.
788 a8083063 Iustin Pop

789 72737a7f Iustin Pop
    """
790 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "blockdev_getmirrorstatus",
791 9a525d83 Michael Hanselmann
                                [dsk.ToDict() for dsk in disks])
792 a8083063 Iustin Pop
793 72737a7f Iustin Pop
  def call_blockdev_find(self, node, disk):
794 72737a7f Iustin Pop
    """Request identification of a given block device.
795 72737a7f Iustin Pop

796 72737a7f Iustin Pop
    This is a single-node call.
797 a8083063 Iustin Pop

798 72737a7f Iustin Pop
    """
799 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "blockdev_find", [disk.ToDict()])
800 d61cbe76 Iustin Pop
801 b2e7666a Iustin Pop
  def call_blockdev_close(self, node, instance_name, disks):
802 72737a7f Iustin Pop
    """Closes the given block devices.
803 d61cbe76 Iustin Pop

804 72737a7f Iustin Pop
    This is a single-node call.
805 d61cbe76 Iustin Pop

806 72737a7f Iustin Pop
    """
807 b2e7666a Iustin Pop
    params = [instance_name, [cf.ToDict() for cf in disks]]
808 b2e7666a Iustin Pop
    return self._SingleNodeCall(node, "blockdev_close", params)
809 a8083063 Iustin Pop
810 968a7623 Iustin Pop
  def call_blockdev_getsizes(self, node, disks):
811 968a7623 Iustin Pop
    """Returns the size of the given disks.
812 968a7623 Iustin Pop

813 968a7623 Iustin Pop
    This is a single-node call.
814 968a7623 Iustin Pop

815 968a7623 Iustin Pop
    """
816 968a7623 Iustin Pop
    params = [[cf.ToDict() for cf in disks]]
817 968a7623 Iustin Pop
    return self._SingleNodeCall(node, "blockdev_getsize", params)
818 968a7623 Iustin Pop
819 6b93ec9d Iustin Pop
  def call_drbd_disconnect_net(self, node_list, nodes_ip, disks):
820 6b93ec9d Iustin Pop
    """Disconnects the network of the given drbd devices.
821 6b93ec9d Iustin Pop

822 6b93ec9d Iustin Pop
    This is a multi-node call.
823 6b93ec9d Iustin Pop

824 6b93ec9d Iustin Pop
    """
825 6b93ec9d Iustin Pop
    return self._MultiNodeCall(node_list, "drbd_disconnect_net",
826 6b93ec9d Iustin Pop
                               [nodes_ip, [cf.ToDict() for cf in disks]])
827 6b93ec9d Iustin Pop
828 6b93ec9d Iustin Pop
  def call_drbd_attach_net(self, node_list, nodes_ip,
829 6b93ec9d Iustin Pop
                           disks, instance_name, multimaster):
830 6b93ec9d Iustin Pop
    """Disconnects the given drbd devices.
831 6b93ec9d Iustin Pop

832 6b93ec9d Iustin Pop
    This is a multi-node call.
833 6b93ec9d Iustin Pop

834 6b93ec9d Iustin Pop
    """
835 6b93ec9d Iustin Pop
    return self._MultiNodeCall(node_list, "drbd_attach_net",
836 6b93ec9d Iustin Pop
                               [nodes_ip, [cf.ToDict() for cf in disks],
837 6b93ec9d Iustin Pop
                                instance_name, multimaster])
838 6b93ec9d Iustin Pop
839 6b93ec9d Iustin Pop
  def call_drbd_wait_sync(self, node_list, nodes_ip, disks):
840 6b93ec9d Iustin Pop
    """Waits for the synchronization of drbd devices is complete.
841 6b93ec9d Iustin Pop

842 6b93ec9d Iustin Pop
    This is a multi-node call.
843 6b93ec9d Iustin Pop

844 6b93ec9d Iustin Pop
    """
845 6b93ec9d Iustin Pop
    return self._MultiNodeCall(node_list, "drbd_wait_sync",
846 6b93ec9d Iustin Pop
                               [nodes_ip, [cf.ToDict() for cf in disks]])
847 6b93ec9d Iustin Pop
848 9a525d83 Michael Hanselmann
  @classmethod
849 9a525d83 Michael Hanselmann
  def call_upload_file(cls, node_list, file_name, address_list=None):
850 72737a7f Iustin Pop
    """Upload a file.
851 72737a7f Iustin Pop

852 72737a7f Iustin Pop
    The node will refuse the operation in case the file is not on the
853 72737a7f Iustin Pop
    approved file list.
854 72737a7f Iustin Pop

855 72737a7f Iustin Pop
    This is a multi-node call.
856 a8083063 Iustin Pop

857 6b294c53 Iustin Pop
    @type node_list: list
858 6b294c53 Iustin Pop
    @param node_list: the list of node names to upload to
859 6b294c53 Iustin Pop
    @type file_name: str
860 6b294c53 Iustin Pop
    @param file_name: the filename to upload
861 6b294c53 Iustin Pop
    @type address_list: list or None
862 6b294c53 Iustin Pop
    @keyword address_list: an optional list of node addresses, in order
863 6b294c53 Iustin Pop
        to optimize the RPC speed
864 6b294c53 Iustin Pop

865 72737a7f Iustin Pop
    """
866 12bce260 Michael Hanselmann
    file_contents = utils.ReadFile(file_name)
867 12bce260 Michael Hanselmann
    data = cls._Compress(file_contents)
868 72737a7f Iustin Pop
    st = os.stat(file_name)
869 72737a7f Iustin Pop
    params = [file_name, data, st.st_mode, st.st_uid, st.st_gid,
870 72737a7f Iustin Pop
              st.st_atime, st.st_mtime]
871 9a525d83 Michael Hanselmann
    return cls._StaticMultiNodeCall(node_list, "upload_file", params,
872 9a525d83 Michael Hanselmann
                                    address_list=address_list)
873 72737a7f Iustin Pop
874 6ddc95ec Michael Hanselmann
  @classmethod
875 03d1dba2 Michael Hanselmann
  def call_write_ssconf_files(cls, node_list, values):
876 6ddc95ec Michael Hanselmann
    """Write ssconf files.
877 6ddc95ec Michael Hanselmann

878 6ddc95ec Michael Hanselmann
    This is a multi-node call.
879 6ddc95ec Michael Hanselmann

880 6ddc95ec Michael Hanselmann
    """
881 03d1dba2 Michael Hanselmann
    return cls._StaticMultiNodeCall(node_list, "write_ssconf_files", [values])
882 6ddc95ec Michael Hanselmann
883 72737a7f Iustin Pop
  def call_os_diagnose(self, node_list):
884 72737a7f Iustin Pop
    """Request a diagnose of OS definitions.
885 72737a7f Iustin Pop

886 72737a7f Iustin Pop
    This is a multi-node call.
887 a8083063 Iustin Pop

888 72737a7f Iustin Pop
    """
889 9a525d83 Michael Hanselmann
    result = self._MultiNodeCall(node_list, "os_diagnose", [])
890 9a525d83 Michael Hanselmann
891 fab1e3a4 Iustin Pop
    for node_result in result.values():
892 781de953 Iustin Pop
      if not node_result.failed and node_result.data:
893 781de953 Iustin Pop
        node_result.data = [objects.OS.FromDict(oss)
894 781de953 Iustin Pop
                            for oss in node_result.data]
895 781de953 Iustin Pop
    return result
896 a8083063 Iustin Pop
897 72737a7f Iustin Pop
  def call_os_get(self, node, name):
898 72737a7f Iustin Pop
    """Returns an OS definition.
899 a8083063 Iustin Pop

900 72737a7f Iustin Pop
    This is a single-node call.
901 a8083063 Iustin Pop

902 72737a7f Iustin Pop
    """
903 9a525d83 Michael Hanselmann
    result = self._SingleNodeCall(node, "os_get", [name])
904 781de953 Iustin Pop
    if not result.failed and isinstance(result.data, dict):
905 781de953 Iustin Pop
      result.data = objects.OS.FromDict(result.data)
906 781de953 Iustin Pop
    return result
907 a8083063 Iustin Pop
908 72737a7f Iustin Pop
  def call_hooks_runner(self, node_list, hpath, phase, env):
909 72737a7f Iustin Pop
    """Call the hooks runner.
910 a8083063 Iustin Pop

911 72737a7f Iustin Pop
    Args:
912 72737a7f Iustin Pop
      - op: the OpCode instance
913 72737a7f Iustin Pop
      - env: a dictionary with the environment
914 a8083063 Iustin Pop

915 72737a7f Iustin Pop
    This is a multi-node call.
916 a8083063 Iustin Pop

917 72737a7f Iustin Pop
    """
918 72737a7f Iustin Pop
    params = [hpath, phase, env]
919 9a525d83 Michael Hanselmann
    return self._MultiNodeCall(node_list, "hooks_runner", params)
920 a8083063 Iustin Pop
921 72737a7f Iustin Pop
  def call_iallocator_runner(self, node, name, idata):
922 72737a7f Iustin Pop
    """Call an iallocator on a remote node
923 8d528b7c Iustin Pop

924 72737a7f Iustin Pop
    Args:
925 72737a7f Iustin Pop
      - name: the iallocator name
926 72737a7f Iustin Pop
      - input: the json-encoded input string
927 8d528b7c Iustin Pop

928 72737a7f Iustin Pop
    This is a single-node call.
929 8d528b7c Iustin Pop

930 72737a7f Iustin Pop
    """
931 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "iallocator_runner", [name, idata])
932 8d528b7c Iustin Pop
933 72737a7f Iustin Pop
  def call_blockdev_grow(self, node, cf_bdev, amount):
934 72737a7f Iustin Pop
    """Request a snapshot of the given block device.
935 4c8ba8b3 Iustin Pop

936 72737a7f Iustin Pop
    This is a single-node call.
937 4c8ba8b3 Iustin Pop

938 72737a7f Iustin Pop
    """
939 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "blockdev_grow",
940 9a525d83 Michael Hanselmann
                                [cf_bdev.ToDict(), amount])
941 4c8ba8b3 Iustin Pop
942 72737a7f Iustin Pop
  def call_blockdev_snapshot(self, node, cf_bdev):
943 72737a7f Iustin Pop
    """Request a snapshot of the given block device.
944 a8083063 Iustin Pop

945 72737a7f Iustin Pop
    This is a single-node call.
946 a8083063 Iustin Pop

947 72737a7f Iustin Pop
    """
948 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "blockdev_snapshot", [cf_bdev.ToDict()])
949 a8083063 Iustin Pop
950 72737a7f Iustin Pop
  def call_snapshot_export(self, node, snap_bdev, dest_node, instance,
951 74c47259 Iustin Pop
                           cluster_name, idx):
952 72737a7f Iustin Pop
    """Request the export of a given snapshot.
953 a8083063 Iustin Pop

954 72737a7f Iustin Pop
    This is a single-node call.
955 a8083063 Iustin Pop

956 72737a7f Iustin Pop
    """
957 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "snapshot_export",
958 9a525d83 Michael Hanselmann
                                [snap_bdev.ToDict(), dest_node,
959 9a525d83 Michael Hanselmann
                                 self._InstDict(instance), cluster_name, idx])
960 a8083063 Iustin Pop
961 72737a7f Iustin Pop
  def call_finalize_export(self, node, instance, snap_disks):
962 72737a7f Iustin Pop
    """Request the completion of an export operation.
963 a8083063 Iustin Pop

964 72737a7f Iustin Pop
    This writes the export config file, etc.
965 a8083063 Iustin Pop

966 72737a7f Iustin Pop
    This is a single-node call.
967 a8083063 Iustin Pop

968 72737a7f Iustin Pop
    """
969 72737a7f Iustin Pop
    flat_disks = []
970 72737a7f Iustin Pop
    for disk in snap_disks:
971 a97da6b7 Iustin Pop
      if isinstance(disk, bool):
972 a97da6b7 Iustin Pop
        flat_disks.append(disk)
973 a97da6b7 Iustin Pop
      else:
974 a97da6b7 Iustin Pop
        flat_disks.append(disk.ToDict())
975 9a525d83 Michael Hanselmann
976 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "finalize_export",
977 9a525d83 Michael Hanselmann
                                [self._InstDict(instance), flat_disks])
978 a8083063 Iustin Pop
979 72737a7f Iustin Pop
  def call_export_info(self, node, path):
980 72737a7f Iustin Pop
    """Queries the export information in a given path.
981 a8083063 Iustin Pop

982 72737a7f Iustin Pop
    This is a single-node call.
983 a8083063 Iustin Pop

984 72737a7f Iustin Pop
    """
985 9a525d83 Michael Hanselmann
    result = self._SingleNodeCall(node, "export_info", [path])
986 781de953 Iustin Pop
    if not result.failed and result.data:
987 781de953 Iustin Pop
      result.data = objects.SerializableConfigParser.Loads(str(result.data))
988 781de953 Iustin Pop
    return result
989 a8083063 Iustin Pop
990 6c0af70e Guido Trotter
  def call_instance_os_import(self, node, inst, src_node, src_images,
991 6c0af70e Guido Trotter
                              cluster_name):
992 72737a7f Iustin Pop
    """Request the import of a backup into an instance.
993 a8083063 Iustin Pop

994 72737a7f Iustin Pop
    This is a single-node call.
995 a8083063 Iustin Pop

996 72737a7f Iustin Pop
    """
997 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "instance_os_import",
998 9a525d83 Michael Hanselmann
                                [self._InstDict(inst), src_node, src_images,
999 9a525d83 Michael Hanselmann
                                 cluster_name])
1000 a8083063 Iustin Pop
1001 72737a7f Iustin Pop
  def call_export_list(self, node_list):
1002 72737a7f Iustin Pop
    """Gets the stored exports list.
1003 a8083063 Iustin Pop

1004 72737a7f Iustin Pop
    This is a multi-node call.
1005 a8083063 Iustin Pop

1006 72737a7f Iustin Pop
    """
1007 9a525d83 Michael Hanselmann
    return self._MultiNodeCall(node_list, "export_list", [])
1008 a8083063 Iustin Pop
1009 72737a7f Iustin Pop
  def call_export_remove(self, node, export):
1010 72737a7f Iustin Pop
    """Requests removal of a given export.
1011 a8083063 Iustin Pop

1012 72737a7f Iustin Pop
    This is a single-node call.
1013 a8083063 Iustin Pop

1014 72737a7f Iustin Pop
    """
1015 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "export_remove", [export])
1016 a8083063 Iustin Pop
1017 9a525d83 Michael Hanselmann
  @classmethod
1018 9a525d83 Michael Hanselmann
  def call_node_leave_cluster(cls, node):
1019 72737a7f Iustin Pop
    """Requests a node to clean the cluster information it has.
1020 a8083063 Iustin Pop

1021 72737a7f Iustin Pop
    This will remove the configuration information from the ganeti data
1022 72737a7f Iustin Pop
    dir.
1023 a8083063 Iustin Pop

1024 72737a7f Iustin Pop
    This is a single-node call.
1025 a8083063 Iustin Pop

1026 72737a7f Iustin Pop
    """
1027 9a525d83 Michael Hanselmann
    return cls._StaticSingleNodeCall(node, "node_leave_cluster", [])
1028 dcb93971 Michael Hanselmann
1029 72737a7f Iustin Pop
  def call_node_volumes(self, node_list):
1030 72737a7f Iustin Pop
    """Gets all volumes on node(s).
1031 dcb93971 Michael Hanselmann

1032 72737a7f Iustin Pop
    This is a multi-node call.
1033 dcb93971 Michael Hanselmann

1034 72737a7f Iustin Pop
    """
1035 9a525d83 Michael Hanselmann
    return self._MultiNodeCall(node_list, "node_volumes", [])
1036 06009e27 Iustin Pop
1037 56aa9fd5 Iustin Pop
  def call_node_demote_from_mc(self, node):
1038 56aa9fd5 Iustin Pop
    """Demote a node from the master candidate role.
1039 56aa9fd5 Iustin Pop

1040 56aa9fd5 Iustin Pop
    This is a single-node call.
1041 56aa9fd5 Iustin Pop

1042 56aa9fd5 Iustin Pop
    """
1043 56aa9fd5 Iustin Pop
    return self._SingleNodeCall(node, "node_demote_from_mc", [])
1044 56aa9fd5 Iustin Pop
1045 72737a7f Iustin Pop
  def call_test_delay(self, node_list, duration):
1046 72737a7f Iustin Pop
    """Sleep for a fixed time on given node(s).
1047 06009e27 Iustin Pop

1048 72737a7f Iustin Pop
    This is a multi-node call.
1049 06009e27 Iustin Pop

1050 72737a7f Iustin Pop
    """
1051 9a525d83 Michael Hanselmann
    return self._MultiNodeCall(node_list, "test_delay", [duration])
1052 5e04ed8b Manuel Franceschini
1053 72737a7f Iustin Pop
  def call_file_storage_dir_create(self, node, file_storage_dir):
1054 72737a7f Iustin Pop
    """Create the given file storage directory.
1055 5e04ed8b Manuel Franceschini

1056 72737a7f Iustin Pop
    This is a single-node call.
1057 5e04ed8b Manuel Franceschini

1058 72737a7f Iustin Pop
    """
1059 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "file_storage_dir_create",
1060 9a525d83 Michael Hanselmann
                                [file_storage_dir])
1061 5e04ed8b Manuel Franceschini
1062 72737a7f Iustin Pop
  def call_file_storage_dir_remove(self, node, file_storage_dir):
1063 72737a7f Iustin Pop
    """Remove the given file storage directory.
1064 5e04ed8b Manuel Franceschini

1065 72737a7f Iustin Pop
    This is a single-node call.
1066 5e04ed8b Manuel Franceschini

1067 72737a7f Iustin Pop
    """
1068 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "file_storage_dir_remove",
1069 9a525d83 Michael Hanselmann
                                [file_storage_dir])
1070 5e04ed8b Manuel Franceschini
1071 72737a7f Iustin Pop
  def call_file_storage_dir_rename(self, node, old_file_storage_dir,
1072 72737a7f Iustin Pop
                                   new_file_storage_dir):
1073 72737a7f Iustin Pop
    """Rename file storage directory.
1074 5e04ed8b Manuel Franceschini

1075 72737a7f Iustin Pop
    This is a single-node call.
1076 5e04ed8b Manuel Franceschini

1077 72737a7f Iustin Pop
    """
1078 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "file_storage_dir_rename",
1079 9a525d83 Michael Hanselmann
                                [old_file_storage_dir, new_file_storage_dir])
1080 ca52cdeb Michael Hanselmann
1081 9a525d83 Michael Hanselmann
  @classmethod
1082 9a525d83 Michael Hanselmann
  def call_jobqueue_update(cls, node_list, address_list, file_name, content):
1083 72737a7f Iustin Pop
    """Update job queue.
1084 ca52cdeb Michael Hanselmann

1085 72737a7f Iustin Pop
    This is a multi-node call.
1086 ca52cdeb Michael Hanselmann

1087 72737a7f Iustin Pop
    """
1088 9a525d83 Michael Hanselmann
    return cls._StaticMultiNodeCall(node_list, "jobqueue_update",
1089 12bce260 Michael Hanselmann
                                    [file_name, cls._Compress(content)],
1090 9a525d83 Michael Hanselmann
                                    address_list=address_list)
1091 ca52cdeb Michael Hanselmann
1092 9a525d83 Michael Hanselmann
  @classmethod
1093 9a525d83 Michael Hanselmann
  def call_jobqueue_purge(cls, node):
1094 72737a7f Iustin Pop
    """Purge job queue.
1095 ca52cdeb Michael Hanselmann

1096 72737a7f Iustin Pop
    This is a single-node call.
1097 ca52cdeb Michael Hanselmann

1098 72737a7f Iustin Pop
    """
1099 9a525d83 Michael Hanselmann
    return cls._StaticSingleNodeCall(node, "jobqueue_purge", [])
1100 af5ebcb1 Michael Hanselmann
1101 9a525d83 Michael Hanselmann
  @classmethod
1102 dd875d32 Michael Hanselmann
  def call_jobqueue_rename(cls, node_list, address_list, rename):
1103 72737a7f Iustin Pop
    """Rename a job queue file.
1104 af5ebcb1 Michael Hanselmann

1105 72737a7f Iustin Pop
    This is a multi-node call.
1106 af5ebcb1 Michael Hanselmann

1107 72737a7f Iustin Pop
    """
1108 dd875d32 Michael Hanselmann
    return cls._StaticMultiNodeCall(node_list, "jobqueue_rename", rename,
1109 9a525d83 Michael Hanselmann
                                    address_list=address_list)
1110 6217e295 Iustin Pop
1111 9a525d83 Michael Hanselmann
  @classmethod
1112 9a525d83 Michael Hanselmann
  def call_jobqueue_set_drain(cls, node_list, drain_flag):
1113 5d672980 Iustin Pop
    """Set the drain flag on the queue.
1114 5d672980 Iustin Pop

1115 5d672980 Iustin Pop
    This is a multi-node call.
1116 5d672980 Iustin Pop

1117 5d672980 Iustin Pop
    @type node_list: list
1118 5d672980 Iustin Pop
    @param node_list: the list of nodes to query
1119 5d672980 Iustin Pop
    @type drain_flag: bool
1120 5d672980 Iustin Pop
    @param drain_flag: if True, will set the drain flag, otherwise reset it.
1121 5d672980 Iustin Pop

1122 5d672980 Iustin Pop
    """
1123 9a525d83 Michael Hanselmann
    return cls._StaticMultiNodeCall(node_list, "jobqueue_set_drain",
1124 9a525d83 Michael Hanselmann
                                    [drain_flag])
1125 5d672980 Iustin Pop
1126 6217e295 Iustin Pop
  def call_hypervisor_validate_params(self, node_list, hvname, hvparams):
1127 6217e295 Iustin Pop
    """Validate the hypervisor params.
1128 6217e295 Iustin Pop

1129 6217e295 Iustin Pop
    This is a multi-node call.
1130 6217e295 Iustin Pop

1131 6217e295 Iustin Pop
    @type node_list: list
1132 6217e295 Iustin Pop
    @param node_list: the list of nodes to query
1133 6217e295 Iustin Pop
    @type hvname: string
1134 6217e295 Iustin Pop
    @param hvname: the hypervisor name
1135 6217e295 Iustin Pop
    @type hvparams: dict
1136 6217e295 Iustin Pop
    @param hvparams: the hypervisor parameters to be validated
1137 6217e295 Iustin Pop

1138 6217e295 Iustin Pop
    """
1139 6217e295 Iustin Pop
    cluster = self._cfg.GetClusterInfo()
1140 6217e295 Iustin Pop
    hv_full = cluster.FillDict(cluster.hvparams.get(hvname, {}), hvparams)
1141 9a525d83 Michael Hanselmann
    return self._MultiNodeCall(node_list, "hypervisor_validate_params",
1142 9a525d83 Michael Hanselmann
                               [hvname, hv_full])