Statistics
| Branch: | Tag: | Revision:

root / lib / rpc.py @ 256eb94b

History | View | Annotate | Download (34.4 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 ae88ef45 Michael Hanselmann
import ganeti.http.client
46 ae88ef45 Michael Hanselmann
47 a8083063 Iustin Pop
48 4331f6cd Michael Hanselmann
# Module level variable
49 4331f6cd Michael Hanselmann
_http_manager = None
50 4331f6cd Michael Hanselmann
51 4331f6cd Michael Hanselmann
52 4331f6cd Michael Hanselmann
def Init():
53 4331f6cd Michael Hanselmann
  """Initializes the module-global HTTP client manager.
54 4331f6cd Michael Hanselmann

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

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

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

70 4331f6cd Michael Hanselmann
  """
71 4331f6cd Michael Hanselmann
  global _http_manager
72 4331f6cd Michael Hanselmann
73 4331f6cd Michael Hanselmann
  if _http_manager:
74 4331f6cd Michael Hanselmann
    _http_manager.Shutdown()
75 4331f6cd Michael Hanselmann
    _http_manager = None
76 4331f6cd Michael Hanselmann
77 4331f6cd Michael Hanselmann
78 781de953 Iustin Pop
class RpcResult(object):
79 781de953 Iustin Pop
  """RPC Result class.
80 781de953 Iustin Pop

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

85 5bbd3f7f Michael Hanselmann
  @ivar data: the data payload, for successful results, or None
86 ed83f5cc Iustin Pop
  @ivar call: the name of the RPC call
87 ed83f5cc Iustin Pop
  @ivar node: the name of the node to which we made the call
88 ed83f5cc Iustin Pop
  @ivar offline: whether the operation failed because the node was
89 ed83f5cc Iustin Pop
      offline, as opposed to actual failure; offline=True will always
90 ed83f5cc Iustin Pop
      imply failed=True, in order to allow simpler checking if
91 ed83f5cc Iustin Pop
      the user doesn't care about the exact failure mode
92 4c4e4e1e Iustin Pop
  @ivar fail_msg: the error message if the call failed
93 ed83f5cc Iustin Pop

94 781de953 Iustin Pop
  """
95 ed83f5cc Iustin Pop
  def __init__(self, data=None, failed=False, offline=False,
96 ed83f5cc Iustin Pop
               call=None, node=None):
97 ed83f5cc Iustin Pop
    self.offline = offline
98 ed83f5cc Iustin Pop
    self.call = call
99 ed83f5cc Iustin Pop
    self.node = node
100 ed83f5cc Iustin Pop
    if offline:
101 4c4e4e1e Iustin Pop
      self.fail_msg = "Node is marked offline"
102 f2def43a Iustin Pop
      self.data = self.payload = None
103 ed83f5cc Iustin Pop
    elif failed:
104 4c4e4e1e Iustin Pop
      self.fail_msg = self._EnsureErr(data)
105 f2def43a Iustin Pop
      self.data = self.payload = None
106 781de953 Iustin Pop
    else:
107 781de953 Iustin Pop
      self.data = data
108 d3c8b360 Iustin Pop
      if not isinstance(self.data, (tuple, list)):
109 4c4e4e1e Iustin Pop
        self.fail_msg = ("RPC layer error: invalid result type (%s)" %
110 4c4e4e1e Iustin Pop
                         type(self.data))
111 d3c8b360 Iustin Pop
      elif len(data) != 2:
112 4c4e4e1e Iustin Pop
        self.fail_msg = ("RPC layer error: invalid result length (%d), "
113 4c4e4e1e Iustin Pop
                         "expected 2" % len(self.data))
114 d3c8b360 Iustin Pop
      elif not self.data[0]:
115 4c4e4e1e Iustin Pop
        self.fail_msg = self._EnsureErr(self.data[1])
116 f2def43a Iustin Pop
      else:
117 d3c8b360 Iustin Pop
        # finally success
118 4c4e4e1e Iustin Pop
        self.fail_msg = None
119 d3c8b360 Iustin Pop
        self.payload = data[1]
120 d3c8b360 Iustin Pop
121 d3c8b360 Iustin Pop
  @staticmethod
122 d3c8b360 Iustin Pop
  def _EnsureErr(val):
123 d3c8b360 Iustin Pop
    """Helper to ensure we return a 'True' value for error."""
124 d3c8b360 Iustin Pop
    if val:
125 d3c8b360 Iustin Pop
      return val
126 d3c8b360 Iustin Pop
    else:
127 d3c8b360 Iustin Pop
      return "No error information"
128 781de953 Iustin Pop
129 4c4e4e1e Iustin Pop
  def Raise(self, msg, prereq=False):
130 781de953 Iustin Pop
    """If the result has failed, raise an OpExecError.
131 781de953 Iustin Pop

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

135 781de953 Iustin Pop
    """
136 4c4e4e1e Iustin Pop
    if not self.fail_msg:
137 4c4e4e1e Iustin Pop
      return
138 4c4e4e1e Iustin Pop
139 4c4e4e1e Iustin Pop
    if not msg: # one could pass None for default message
140 4c4e4e1e Iustin Pop
      msg = ("Call '%s' to node '%s' has failed: %s" %
141 4c4e4e1e Iustin Pop
             (self.call, self.node, self.fail_msg))
142 4c4e4e1e Iustin Pop
    else:
143 4c4e4e1e Iustin Pop
      msg = "%s: %s" % (msg, self.fail_msg)
144 4c4e4e1e Iustin Pop
    if prereq:
145 4c4e4e1e Iustin Pop
      ec = errors.OpPrereqError
146 4c4e4e1e Iustin Pop
    else:
147 4c4e4e1e Iustin Pop
      ec = errors.OpExecError
148 4c4e4e1e Iustin Pop
    raise ec(msg)
149 781de953 Iustin Pop
150 781de953 Iustin Pop
151 a8083063 Iustin Pop
class Client:
152 a8083063 Iustin Pop
  """RPC Client class.
153 a8083063 Iustin Pop

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

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

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

176 3ef3c771 Iustin Pop
    @type node_list: list
177 3ef3c771 Iustin Pop
    @param node_list: the list of node names to connect
178 bdf7d8c0 Iustin Pop
    @type address_list: list or None
179 bdf7d8c0 Iustin Pop
    @keyword address_list: either None or a list with node addresses,
180 bdf7d8c0 Iustin Pop
        which must have the same length as the node list
181 3ef3c771 Iustin Pop

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

194 bdf7d8c0 Iustin Pop
    @type name: str
195 bdf7d8c0 Iustin Pop
    @param name: the node name
196 bdf7d8c0 Iustin Pop
    @type address: str
197 bdf7d8c0 Iustin Pop
    @keyword address: the node address, if known
198 bdf7d8c0 Iustin Pop

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

213 ecfe9491 Michael Hanselmann
    @rtype: list
214 5fcc718f Iustin Pop
    @return: List of RPC results
215 a8083063 Iustin Pop

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

249 72737a7f Iustin Pop
    @type cfg:  C{config.ConfigWriter}
250 72737a7f Iustin Pop
    @param cfg: the configuration object that will be used to get data
251 72737a7f Iustin Pop
                about the cluster
252 a8083063 Iustin Pop

253 72737a7f Iustin Pop
    """
254 72737a7f Iustin Pop
    self._cfg = cfg
255 cd50653c Guido Trotter
    self.port = utils.GetDaemonPort(constants.NODED)
256 a8083063 Iustin Pop
257 0eca8e0c Iustin Pop
  def _InstDict(self, instance, hvp=None, bep=None):
258 26ba2bd8 Iustin Pop
    """Convert the given instance to a dict.
259 26ba2bd8 Iustin Pop

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

263 26ba2bd8 Iustin Pop
    @type instance: L{objects.Instance}
264 26ba2bd8 Iustin Pop
    @param instance: an Instance object
265 0eca8e0c Iustin Pop
    @type hvp: dict or None
266 5bbd3f7f Michael Hanselmann
    @param hvp: a dictionary with overridden hypervisor parameters
267 0eca8e0c Iustin Pop
    @type bep: dict or None
268 5bbd3f7f Michael Hanselmann
    @param bep: a dictionary with overridden backend parameters
269 26ba2bd8 Iustin Pop
    @rtype: dict
270 26ba2bd8 Iustin Pop
    @return: the instance dict, with the hvparams filled with the
271 26ba2bd8 Iustin Pop
        cluster defaults
272 26ba2bd8 Iustin Pop

273 26ba2bd8 Iustin Pop
    """
274 26ba2bd8 Iustin Pop
    idict = instance.ToDict()
275 5b442704 Iustin Pop
    cluster = self._cfg.GetClusterInfo()
276 5b442704 Iustin Pop
    idict["hvparams"] = cluster.FillHV(instance)
277 0eca8e0c Iustin Pop
    if hvp is not None:
278 0eca8e0c Iustin Pop
      idict["hvparams"].update(hvp)
279 5b442704 Iustin Pop
    idict["beparams"] = cluster.FillBE(instance)
280 0eca8e0c Iustin Pop
    if bep is not None:
281 0eca8e0c Iustin Pop
      idict["beparams"].update(bep)
282 b848ce79 Guido Trotter
    for nic in idict["nics"]:
283 b848ce79 Guido Trotter
      nic['nicparams'] = objects.FillDict(
284 b848ce79 Guido Trotter
        cluster.nicparams[constants.PP_DEFAULT],
285 b848ce79 Guido Trotter
        nic['nicparams'])
286 26ba2bd8 Iustin Pop
    return idict
287 26ba2bd8 Iustin Pop
288 84b45587 Iustin Pop
  def _ConnectList(self, client, node_list, call):
289 25348212 Iustin Pop
    """Helper for computing node addresses.
290 25348212 Iustin Pop

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

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

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

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

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

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

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

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

386 12bce260 Michael Hanselmann
    Small amounts of data are not compressed.
387 12bce260 Michael Hanselmann

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

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

409 72737a7f Iustin Pop
    This is a multi-node call.
410 a8083063 Iustin Pop

411 72737a7f Iustin Pop
    """
412 b2a6ccd4 Iustin Pop
    return self._MultiNodeCall(node_list, "lv_list", [vg_name])
413 a8083063 Iustin Pop
414 72737a7f Iustin Pop
  def call_vg_list(self, node_list):
415 72737a7f Iustin Pop
    """Gets the volume group list.
416 a8083063 Iustin Pop

417 72737a7f Iustin Pop
    This is a multi-node call.
418 a8083063 Iustin Pop

419 72737a7f Iustin Pop
    """
420 9a525d83 Michael Hanselmann
    return self._MultiNodeCall(node_list, "vg_list", [])
421 a8083063 Iustin Pop
422 e337de97 Michael Hanselmann
  def call_storage_list(self, node_list, su_name, su_args, name, fields):
423 8979196a Michael Hanselmann
    """Get list of storage units.
424 e337de97 Michael Hanselmann

425 e337de97 Michael Hanselmann
    This is a multi-node call.
426 e337de97 Michael Hanselmann

427 e337de97 Michael Hanselmann
    """
428 e337de97 Michael Hanselmann
    return self._MultiNodeCall(node_list, "storage_list",
429 e337de97 Michael Hanselmann
                               [su_name, su_args, name, fields])
430 e337de97 Michael Hanselmann
431 8979196a Michael Hanselmann
  def call_storage_modify(self, node, su_name, su_args, name, changes):
432 8979196a Michael Hanselmann
    """Modify a storage unit.
433 8979196a Michael Hanselmann

434 8979196a Michael Hanselmann
    This is a single-node call.
435 8979196a Michael Hanselmann

436 8979196a Michael Hanselmann
    """
437 8979196a Michael Hanselmann
    return self._SingleNodeCall(node, "storage_modify",
438 8979196a Michael Hanselmann
                                [su_name, su_args, name, changes])
439 8979196a Michael Hanselmann
440 637b8d7e Michael Hanselmann
  def call_storage_execute(self, node, su_name, su_args, name, op):
441 637b8d7e Michael Hanselmann
    """Executes an operation on a storage unit.
442 637b8d7e Michael Hanselmann

443 637b8d7e Michael Hanselmann
    This is a single-node call.
444 637b8d7e Michael Hanselmann

445 637b8d7e Michael Hanselmann
    """
446 637b8d7e Michael Hanselmann
    return self._SingleNodeCall(node, "storage_execute",
447 637b8d7e Michael Hanselmann
                                [su_name, su_args, name, op])
448 637b8d7e Michael Hanselmann
449 72737a7f Iustin Pop
  def call_bridges_exist(self, node, bridges_list):
450 72737a7f Iustin Pop
    """Checks if a node has all the bridges given.
451 a8083063 Iustin Pop

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

456 72737a7f Iustin Pop
    This is a single-node call.
457 a8083063 Iustin Pop

458 72737a7f Iustin Pop
    """
459 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "bridges_exist", [bridges_list])
460 a8083063 Iustin Pop
461 0eca8e0c Iustin Pop
  def call_instance_start(self, node, instance, hvp, bep):
462 72737a7f Iustin Pop
    """Starts an instance.
463 a8083063 Iustin Pop

464 72737a7f Iustin Pop
    This is a single-node call.
465 a8083063 Iustin Pop

466 72737a7f Iustin Pop
    """
467 0eca8e0c Iustin Pop
    idict = self._InstDict(instance, hvp=hvp, bep=bep)
468 0eca8e0c Iustin Pop
    return self._SingleNodeCall(node, "instance_start", [idict])
469 a8083063 Iustin Pop
470 72737a7f Iustin Pop
  def call_instance_shutdown(self, node, instance):
471 72737a7f Iustin Pop
    """Stops an instance.
472 a8083063 Iustin Pop

473 72737a7f Iustin Pop
    This is a single-node call.
474 2a10865c Iustin Pop

475 72737a7f Iustin Pop
    """
476 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "instance_shutdown",
477 9a525d83 Michael Hanselmann
                                [self._InstDict(instance)])
478 2a10865c Iustin Pop
479 6906a9d8 Guido Trotter
  def call_migration_info(self, node, instance):
480 6906a9d8 Guido Trotter
    """Gather the information necessary to prepare an instance migration.
481 6906a9d8 Guido Trotter

482 6906a9d8 Guido Trotter
    This is a single-node call.
483 6906a9d8 Guido Trotter

484 6906a9d8 Guido Trotter
    @type node: string
485 6906a9d8 Guido Trotter
    @param node: the node on which the instance is currently running
486 6906a9d8 Guido Trotter
    @type instance: C{objects.Instance}
487 6906a9d8 Guido Trotter
    @param instance: the instance definition
488 6906a9d8 Guido Trotter

489 6906a9d8 Guido Trotter
    """
490 6906a9d8 Guido Trotter
    return self._SingleNodeCall(node, "migration_info",
491 6906a9d8 Guido Trotter
                                [self._InstDict(instance)])
492 6906a9d8 Guido Trotter
493 6906a9d8 Guido Trotter
  def call_accept_instance(self, node, instance, info, target):
494 6906a9d8 Guido Trotter
    """Prepare a node to accept an instance.
495 6906a9d8 Guido Trotter

496 6906a9d8 Guido Trotter
    This is a single-node call.
497 6906a9d8 Guido Trotter

498 6906a9d8 Guido Trotter
    @type node: string
499 6906a9d8 Guido Trotter
    @param node: the target node for the migration
500 6906a9d8 Guido Trotter
    @type instance: C{objects.Instance}
501 6906a9d8 Guido Trotter
    @param instance: the instance definition
502 6906a9d8 Guido Trotter
    @type info: opaque/hypervisor specific (string/data)
503 6906a9d8 Guido Trotter
    @param info: result for the call_migration_info call
504 6906a9d8 Guido Trotter
    @type target: string
505 6906a9d8 Guido Trotter
    @param target: target hostname (usually ip address) (on the node itself)
506 6906a9d8 Guido Trotter

507 6906a9d8 Guido Trotter
    """
508 6906a9d8 Guido Trotter
    return self._SingleNodeCall(node, "accept_instance",
509 6906a9d8 Guido Trotter
                                [self._InstDict(instance), info, target])
510 6906a9d8 Guido Trotter
511 6906a9d8 Guido Trotter
  def call_finalize_migration(self, node, instance, info, success):
512 6906a9d8 Guido Trotter
    """Finalize any target-node migration specific operation.
513 6906a9d8 Guido Trotter

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

517 6906a9d8 Guido Trotter
    This is a single-node call.
518 6906a9d8 Guido Trotter

519 6906a9d8 Guido Trotter
    @type node: string
520 6906a9d8 Guido Trotter
    @param node: the target node for the migration
521 6906a9d8 Guido Trotter
    @type instance: C{objects.Instance}
522 6906a9d8 Guido Trotter
    @param instance: the instance definition
523 6906a9d8 Guido Trotter
    @type info: opaque/hypervisor specific (string/data)
524 6906a9d8 Guido Trotter
    @param info: result for the call_migration_info call
525 6906a9d8 Guido Trotter
    @type success: boolean
526 6906a9d8 Guido Trotter
    @param success: whether the migration was a success or a failure
527 6906a9d8 Guido Trotter

528 6906a9d8 Guido Trotter
    """
529 6906a9d8 Guido Trotter
    return self._SingleNodeCall(node, "finalize_migration",
530 6906a9d8 Guido Trotter
                                [self._InstDict(instance), info, success])
531 6906a9d8 Guido Trotter
532 72737a7f Iustin Pop
  def call_instance_migrate(self, node, instance, target, live):
533 72737a7f Iustin Pop
    """Migrate an instance.
534 2a10865c Iustin Pop

535 72737a7f Iustin Pop
    This is a single-node call.
536 2a10865c Iustin Pop

537 72737a7f Iustin Pop
    @type node: string
538 72737a7f Iustin Pop
    @param node: the node on which the instance is currently running
539 72737a7f Iustin Pop
    @type instance: C{objects.Instance}
540 72737a7f Iustin Pop
    @param instance: the instance definition
541 72737a7f Iustin Pop
    @type target: string
542 72737a7f Iustin Pop
    @param target: the target node name
543 72737a7f Iustin Pop
    @type live: boolean
544 72737a7f Iustin Pop
    @param live: whether the migration should be done live or not (the
545 72737a7f Iustin Pop
        interpretation of this parameter is left to the hypervisor)
546 007a2f3e Alexander Schreiber

547 72737a7f Iustin Pop
    """
548 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "instance_migrate",
549 9a525d83 Michael Hanselmann
                                [self._InstDict(instance), target, live])
550 007a2f3e Alexander Schreiber
551 07813a9e Iustin Pop
  def call_instance_reboot(self, node, instance, reboot_type):
552 72737a7f Iustin Pop
    """Reboots an instance.
553 007a2f3e Alexander Schreiber

554 72737a7f Iustin Pop
    This is a single-node call.
555 a8083063 Iustin Pop

556 72737a7f Iustin Pop
    """
557 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "instance_reboot",
558 07813a9e Iustin Pop
                                [self._InstDict(instance), reboot_type])
559 a8083063 Iustin Pop
560 e557bae9 Guido Trotter
  def call_instance_os_add(self, node, inst, reinstall):
561 72737a7f Iustin Pop
    """Installs an OS on the given instance.
562 a8083063 Iustin Pop

563 72737a7f Iustin Pop
    This is a single-node call.
564 decd5f45 Iustin Pop

565 72737a7f Iustin Pop
    """
566 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "instance_os_add",
567 e557bae9 Guido Trotter
                                [self._InstDict(inst), reinstall])
568 decd5f45 Iustin Pop
569 d15a9ad3 Guido Trotter
  def call_instance_run_rename(self, node, inst, old_name):
570 72737a7f Iustin Pop
    """Run the OS rename script for an instance.
571 decd5f45 Iustin Pop

572 72737a7f Iustin Pop
    This is a single-node call.
573 a8083063 Iustin Pop

574 72737a7f Iustin Pop
    """
575 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "instance_run_rename",
576 9a525d83 Michael Hanselmann
                                [self._InstDict(inst), old_name])
577 a8083063 Iustin Pop
578 72737a7f Iustin Pop
  def call_instance_info(self, node, instance, hname):
579 72737a7f Iustin Pop
    """Returns information about a single instance.
580 a8083063 Iustin Pop

581 72737a7f Iustin Pop
    This is a single-node call.
582 a8083063 Iustin Pop

583 9a525d83 Michael Hanselmann
    @type node: list
584 9a525d83 Michael Hanselmann
    @param node: the list of nodes to query
585 72737a7f Iustin Pop
    @type instance: string
586 72737a7f Iustin Pop
    @param instance: the instance name
587 72737a7f Iustin Pop
    @type hname: string
588 72737a7f Iustin Pop
    @param hname: the hypervisor type of the instance
589 a8083063 Iustin Pop

590 72737a7f Iustin Pop
    """
591 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "instance_info", [instance, hname])
592 e69d05fd Iustin Pop
593 56e7640c Iustin Pop
  def call_instance_migratable(self, node, instance):
594 56e7640c Iustin Pop
    """Checks whether the given instance can be migrated.
595 56e7640c Iustin Pop

596 56e7640c Iustin Pop
    This is a single-node call.
597 56e7640c Iustin Pop

598 56e7640c Iustin Pop
    @param node: the node to query
599 56e7640c Iustin Pop
    @type instance: L{objects.Instance}
600 56e7640c Iustin Pop
    @param instance: the instance to check
601 56e7640c Iustin Pop

602 56e7640c Iustin Pop

603 56e7640c Iustin Pop
    """
604 56e7640c Iustin Pop
    return self._SingleNodeCall(node, "instance_migratable",
605 56e7640c Iustin Pop
                                [self._InstDict(instance)])
606 56e7640c Iustin Pop
607 72737a7f Iustin Pop
  def call_all_instances_info(self, node_list, hypervisor_list):
608 72737a7f Iustin Pop
    """Returns information about all instances on the given nodes.
609 a8083063 Iustin Pop

610 72737a7f Iustin Pop
    This is a multi-node call.
611 a8083063 Iustin Pop

612 72737a7f Iustin Pop
    @type node_list: list
613 72737a7f Iustin Pop
    @param node_list: the list of nodes to query
614 72737a7f Iustin Pop
    @type hypervisor_list: list
615 72737a7f Iustin Pop
    @param hypervisor_list: the hypervisors to query for instances
616 a8083063 Iustin Pop

617 72737a7f Iustin Pop
    """
618 9a525d83 Michael Hanselmann
    return self._MultiNodeCall(node_list, "all_instances_info",
619 9a525d83 Michael Hanselmann
                               [hypervisor_list])
620 e69d05fd Iustin Pop
621 72737a7f Iustin Pop
  def call_instance_list(self, node_list, hypervisor_list):
622 72737a7f Iustin Pop
    """Returns the list of running instances on a given node.
623 a8083063 Iustin Pop

624 72737a7f Iustin Pop
    This is a multi-node call.
625 a8083063 Iustin Pop

626 72737a7f Iustin Pop
    @type node_list: list
627 72737a7f Iustin Pop
    @param node_list: the list of nodes to query
628 72737a7f Iustin Pop
    @type hypervisor_list: list
629 72737a7f Iustin Pop
    @param hypervisor_list: the hypervisors to query for instances
630 16abfbc2 Alexander Schreiber

631 72737a7f Iustin Pop
    """
632 9a525d83 Michael Hanselmann
    return self._MultiNodeCall(node_list, "instance_list", [hypervisor_list])
633 16abfbc2 Alexander Schreiber
634 72737a7f Iustin Pop
  def call_node_tcp_ping(self, node, source, target, port, timeout,
635 72737a7f Iustin Pop
                         live_port_needed):
636 72737a7f Iustin Pop
    """Do a TcpPing on the remote node
637 a8083063 Iustin Pop

638 72737a7f Iustin Pop
    This is a single-node call.
639 caad16e2 Iustin Pop

640 72737a7f Iustin Pop
    """
641 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "node_tcp_ping",
642 9a525d83 Michael Hanselmann
                                [source, target, port, timeout,
643 72737a7f Iustin Pop
                                 live_port_needed])
644 a8083063 Iustin Pop
645 caad16e2 Iustin Pop
  def call_node_has_ip_address(self, node, address):
646 caad16e2 Iustin Pop
    """Checks if a node has the given IP address.
647 caad16e2 Iustin Pop

648 caad16e2 Iustin Pop
    This is a single-node call.
649 caad16e2 Iustin Pop

650 caad16e2 Iustin Pop
    """
651 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "node_has_ip_address", [address])
652 a8083063 Iustin Pop
653 72737a7f Iustin Pop
  def call_node_info(self, node_list, vg_name, hypervisor_type):
654 72737a7f Iustin Pop
    """Return node information.
655 e69d05fd Iustin Pop

656 72737a7f Iustin Pop
    This will return memory information and volume group size and free
657 72737a7f Iustin Pop
    space.
658 a8083063 Iustin Pop

659 72737a7f Iustin Pop
    This is a multi-node call.
660 a8083063 Iustin Pop

661 72737a7f Iustin Pop
    @type node_list: list
662 72737a7f Iustin Pop
    @param node_list: the list of nodes to query
663 c41eea6e Iustin Pop
    @type vg_name: C{string}
664 c41eea6e Iustin Pop
    @param vg_name: the name of the volume group to ask for disk space
665 72737a7f Iustin Pop
        information
666 72737a7f Iustin Pop
    @type hypervisor_type: C{str}
667 72737a7f Iustin Pop
    @param hypervisor_type: the name of the hypervisor to ask for
668 72737a7f Iustin Pop
        memory information
669 a8083063 Iustin Pop

670 72737a7f Iustin Pop
    """
671 070e998b Iustin Pop
    return self._MultiNodeCall(node_list, "node_info",
672 070e998b Iustin Pop
                               [vg_name, hypervisor_type])
673 a8083063 Iustin Pop
674 72737a7f Iustin Pop
  def call_node_add(self, node, dsa, dsapub, rsa, rsapub, ssh, sshpub):
675 72737a7f Iustin Pop
    """Add a node to the cluster.
676 a8083063 Iustin Pop

677 72737a7f Iustin Pop
    This is a single-node call.
678 a8083063 Iustin Pop

679 72737a7f Iustin Pop
    """
680 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "node_add",
681 9a525d83 Michael Hanselmann
                                [dsa, dsapub, rsa, rsapub, ssh, sshpub])
682 a8083063 Iustin Pop
683 72737a7f Iustin Pop
  def call_node_verify(self, node_list, checkdict, cluster_name):
684 72737a7f Iustin Pop
    """Request verification of given parameters.
685 a8083063 Iustin Pop

686 72737a7f Iustin Pop
    This is a multi-node call.
687 a8083063 Iustin Pop

688 72737a7f Iustin Pop
    """
689 9a525d83 Michael Hanselmann
    return self._MultiNodeCall(node_list, "node_verify",
690 9a525d83 Michael Hanselmann
                               [checkdict, cluster_name])
691 a8083063 Iustin Pop
692 9a525d83 Michael Hanselmann
  @classmethod
693 3583908a Guido Trotter
  def call_node_start_master(cls, node, start_daemons, no_voting):
694 72737a7f Iustin Pop
    """Tells a node to activate itself as a master.
695 a8083063 Iustin Pop

696 72737a7f Iustin Pop
    This is a single-node call.
697 a8083063 Iustin Pop

698 72737a7f Iustin Pop
    """
699 9a525d83 Michael Hanselmann
    return cls._StaticSingleNodeCall(node, "node_start_master",
700 3583908a Guido Trotter
                                     [start_daemons, no_voting])
701 a8083063 Iustin Pop
702 9a525d83 Michael Hanselmann
  @classmethod
703 9a525d83 Michael Hanselmann
  def call_node_stop_master(cls, node, stop_daemons):
704 72737a7f Iustin Pop
    """Tells a node to demote itself from master status.
705 a8083063 Iustin Pop

706 72737a7f Iustin Pop
    This is a single-node call.
707 4e071d3b Iustin Pop

708 72737a7f Iustin Pop
    """
709 9a525d83 Michael Hanselmann
    return cls._StaticSingleNodeCall(node, "node_stop_master", [stop_daemons])
710 4e071d3b Iustin Pop
711 9a525d83 Michael Hanselmann
  @classmethod
712 9a525d83 Michael Hanselmann
  def call_master_info(cls, node_list):
713 72737a7f Iustin Pop
    """Query master info.
714 4e071d3b Iustin Pop

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

717 72737a7f Iustin Pop
    """
718 72737a7f Iustin Pop
    # TODO: should this method query down nodes?
719 9a525d83 Michael Hanselmann
    return cls._StaticMultiNodeCall(node_list, "master_info", [])
720 a8083063 Iustin Pop
721 72737a7f Iustin Pop
  def call_version(self, node_list):
722 72737a7f Iustin Pop
    """Query node version.
723 a8083063 Iustin Pop

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

726 72737a7f Iustin Pop
    """
727 9a525d83 Michael Hanselmann
    return self._MultiNodeCall(node_list, "version", [])
728 a8083063 Iustin Pop
729 72737a7f Iustin Pop
  def call_blockdev_create(self, node, bdev, size, owner, on_primary, info):
730 72737a7f Iustin Pop
    """Request creation of a given block device.
731 a8083063 Iustin Pop

732 72737a7f Iustin Pop
    This is a single-node call.
733 a8083063 Iustin Pop

734 72737a7f Iustin Pop
    """
735 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "blockdev_create",
736 9a525d83 Michael Hanselmann
                                [bdev.ToDict(), size, owner, on_primary, info])
737 a8083063 Iustin Pop
738 72737a7f Iustin Pop
  def call_blockdev_remove(self, node, bdev):
739 72737a7f Iustin Pop
    """Request removal of a given block device.
740 a8083063 Iustin Pop

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

743 72737a7f Iustin Pop
    """
744 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "blockdev_remove", [bdev.ToDict()])
745 f3e513ad Iustin Pop
746 72737a7f Iustin Pop
  def call_blockdev_rename(self, node, devlist):
747 72737a7f Iustin Pop
    """Request rename of the given block devices.
748 f3e513ad Iustin Pop

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

751 72737a7f Iustin Pop
    """
752 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "blockdev_rename",
753 9a525d83 Michael Hanselmann
                                [(d.ToDict(), uid) for d, uid in devlist])
754 a8083063 Iustin Pop
755 72737a7f Iustin Pop
  def call_blockdev_assemble(self, node, disk, owner, on_primary):
756 72737a7f Iustin Pop
    """Request assembling of a given block device.
757 a8083063 Iustin Pop

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

760 72737a7f Iustin Pop
    """
761 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "blockdev_assemble",
762 9a525d83 Michael Hanselmann
                                [disk.ToDict(), owner, on_primary])
763 a8083063 Iustin Pop
764 72737a7f Iustin Pop
  def call_blockdev_shutdown(self, node, disk):
765 72737a7f Iustin Pop
    """Request shutdown of a given block 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_shutdown", [disk.ToDict()])
771 a8083063 Iustin Pop
772 72737a7f Iustin Pop
  def call_blockdev_addchildren(self, node, bdev, ndevs):
773 72737a7f Iustin Pop
    """Request adding a list of children to a (mirroring) device.
774 a8083063 Iustin Pop

775 72737a7f Iustin Pop
    This is a single-node call.
776 a8083063 Iustin Pop

777 72737a7f Iustin Pop
    """
778 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "blockdev_addchildren",
779 9a525d83 Michael Hanselmann
                                [bdev.ToDict(),
780 9a525d83 Michael Hanselmann
                                 [disk.ToDict() for disk in ndevs]])
781 a8083063 Iustin Pop
782 72737a7f Iustin Pop
  def call_blockdev_removechildren(self, node, bdev, ndevs):
783 72737a7f Iustin Pop
    """Request removing a list of children from a (mirroring) device.
784 a8083063 Iustin Pop

785 72737a7f Iustin Pop
    This is a single-node call.
786 a8083063 Iustin Pop

787 72737a7f Iustin Pop
    """
788 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "blockdev_removechildren",
789 9a525d83 Michael Hanselmann
                                [bdev.ToDict(),
790 9a525d83 Michael Hanselmann
                                 [disk.ToDict() for disk in ndevs]])
791 a8083063 Iustin Pop
792 72737a7f Iustin Pop
  def call_blockdev_getmirrorstatus(self, node, disks):
793 72737a7f Iustin Pop
    """Request status of a (mirroring) device.
794 a8083063 Iustin Pop

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

797 72737a7f Iustin Pop
    """
798 36145b12 Michael Hanselmann
    result = self._SingleNodeCall(node, "blockdev_getmirrorstatus",
799 36145b12 Michael Hanselmann
                                  [dsk.ToDict() for dsk in disks])
800 edb4b374 Michael Hanselmann
    if not result.fail_msg:
801 36145b12 Michael Hanselmann
      result.payload = [objects.BlockDevStatus.FromDict(i)
802 36145b12 Michael Hanselmann
                        for i in result.payload]
803 36145b12 Michael Hanselmann
    return result
804 a8083063 Iustin Pop
805 72737a7f Iustin Pop
  def call_blockdev_find(self, node, disk):
806 72737a7f Iustin Pop
    """Request identification of a given block device.
807 72737a7f Iustin Pop

808 72737a7f Iustin Pop
    This is a single-node call.
809 a8083063 Iustin Pop

810 72737a7f Iustin Pop
    """
811 96acbc09 Michael Hanselmann
    result = self._SingleNodeCall(node, "blockdev_find", [disk.ToDict()])
812 edb4b374 Michael Hanselmann
    if not result.fail_msg and result.payload is not None:
813 96acbc09 Michael Hanselmann
      result.payload = objects.BlockDevStatus.FromDict(result.payload)
814 96acbc09 Michael Hanselmann
    return result
815 d61cbe76 Iustin Pop
816 b2e7666a Iustin Pop
  def call_blockdev_close(self, node, instance_name, disks):
817 72737a7f Iustin Pop
    """Closes the given block devices.
818 d61cbe76 Iustin Pop

819 72737a7f Iustin Pop
    This is a single-node call.
820 d61cbe76 Iustin Pop

821 72737a7f Iustin Pop
    """
822 b2e7666a Iustin Pop
    params = [instance_name, [cf.ToDict() for cf in disks]]
823 b2e7666a Iustin Pop
    return self._SingleNodeCall(node, "blockdev_close", params)
824 a8083063 Iustin Pop
825 968a7623 Iustin Pop
  def call_blockdev_getsizes(self, node, disks):
826 968a7623 Iustin Pop
    """Returns the size of the given disks.
827 968a7623 Iustin Pop

828 968a7623 Iustin Pop
    This is a single-node call.
829 968a7623 Iustin Pop

830 968a7623 Iustin Pop
    """
831 968a7623 Iustin Pop
    params = [[cf.ToDict() for cf in disks]]
832 968a7623 Iustin Pop
    return self._SingleNodeCall(node, "blockdev_getsize", params)
833 968a7623 Iustin Pop
834 6b93ec9d Iustin Pop
  def call_drbd_disconnect_net(self, node_list, nodes_ip, disks):
835 6b93ec9d Iustin Pop
    """Disconnects the network of the given drbd devices.
836 6b93ec9d Iustin Pop

837 6b93ec9d Iustin Pop
    This is a multi-node call.
838 6b93ec9d Iustin Pop

839 6b93ec9d Iustin Pop
    """
840 6b93ec9d Iustin Pop
    return self._MultiNodeCall(node_list, "drbd_disconnect_net",
841 6b93ec9d Iustin Pop
                               [nodes_ip, [cf.ToDict() for cf in disks]])
842 6b93ec9d Iustin Pop
843 6b93ec9d Iustin Pop
  def call_drbd_attach_net(self, node_list, nodes_ip,
844 6b93ec9d Iustin Pop
                           disks, instance_name, multimaster):
845 6b93ec9d Iustin Pop
    """Disconnects the given drbd devices.
846 6b93ec9d Iustin Pop

847 6b93ec9d Iustin Pop
    This is a multi-node call.
848 6b93ec9d Iustin Pop

849 6b93ec9d Iustin Pop
    """
850 6b93ec9d Iustin Pop
    return self._MultiNodeCall(node_list, "drbd_attach_net",
851 6b93ec9d Iustin Pop
                               [nodes_ip, [cf.ToDict() for cf in disks],
852 6b93ec9d Iustin Pop
                                instance_name, multimaster])
853 6b93ec9d Iustin Pop
854 6b93ec9d Iustin Pop
  def call_drbd_wait_sync(self, node_list, nodes_ip, disks):
855 6b93ec9d Iustin Pop
    """Waits for the synchronization of drbd devices is complete.
856 6b93ec9d Iustin Pop

857 6b93ec9d Iustin Pop
    This is a multi-node call.
858 6b93ec9d Iustin Pop

859 6b93ec9d Iustin Pop
    """
860 6b93ec9d Iustin Pop
    return self._MultiNodeCall(node_list, "drbd_wait_sync",
861 6b93ec9d Iustin Pop
                               [nodes_ip, [cf.ToDict() for cf in disks]])
862 6b93ec9d Iustin Pop
863 9a525d83 Michael Hanselmann
  @classmethod
864 9a525d83 Michael Hanselmann
  def call_upload_file(cls, node_list, file_name, address_list=None):
865 72737a7f Iustin Pop
    """Upload a file.
866 72737a7f Iustin Pop

867 72737a7f Iustin Pop
    The node will refuse the operation in case the file is not on the
868 72737a7f Iustin Pop
    approved file list.
869 72737a7f Iustin Pop

870 72737a7f Iustin Pop
    This is a multi-node call.
871 a8083063 Iustin Pop

872 6b294c53 Iustin Pop
    @type node_list: list
873 6b294c53 Iustin Pop
    @param node_list: the list of node names to upload to
874 6b294c53 Iustin Pop
    @type file_name: str
875 6b294c53 Iustin Pop
    @param file_name: the filename to upload
876 6b294c53 Iustin Pop
    @type address_list: list or None
877 6b294c53 Iustin Pop
    @keyword address_list: an optional list of node addresses, in order
878 6b294c53 Iustin Pop
        to optimize the RPC speed
879 6b294c53 Iustin Pop

880 72737a7f Iustin Pop
    """
881 12bce260 Michael Hanselmann
    file_contents = utils.ReadFile(file_name)
882 12bce260 Michael Hanselmann
    data = cls._Compress(file_contents)
883 72737a7f Iustin Pop
    st = os.stat(file_name)
884 72737a7f Iustin Pop
    params = [file_name, data, st.st_mode, st.st_uid, st.st_gid,
885 72737a7f Iustin Pop
              st.st_atime, st.st_mtime]
886 9a525d83 Michael Hanselmann
    return cls._StaticMultiNodeCall(node_list, "upload_file", params,
887 9a525d83 Michael Hanselmann
                                    address_list=address_list)
888 72737a7f Iustin Pop
889 6ddc95ec Michael Hanselmann
  @classmethod
890 03d1dba2 Michael Hanselmann
  def call_write_ssconf_files(cls, node_list, values):
891 6ddc95ec Michael Hanselmann
    """Write ssconf files.
892 6ddc95ec Michael Hanselmann

893 6ddc95ec Michael Hanselmann
    This is a multi-node call.
894 6ddc95ec Michael Hanselmann

895 6ddc95ec Michael Hanselmann
    """
896 03d1dba2 Michael Hanselmann
    return cls._StaticMultiNodeCall(node_list, "write_ssconf_files", [values])
897 6ddc95ec Michael Hanselmann
898 72737a7f Iustin Pop
  def call_os_diagnose(self, node_list):
899 72737a7f Iustin Pop
    """Request a diagnose of OS definitions.
900 72737a7f Iustin Pop

901 72737a7f Iustin Pop
    This is a multi-node call.
902 a8083063 Iustin Pop

903 72737a7f Iustin Pop
    """
904 83d92ad8 Iustin Pop
    return self._MultiNodeCall(node_list, "os_diagnose", [])
905 a8083063 Iustin Pop
906 72737a7f Iustin Pop
  def call_os_get(self, node, name):
907 72737a7f Iustin Pop
    """Returns an OS definition.
908 a8083063 Iustin Pop

909 72737a7f Iustin Pop
    This is a single-node call.
910 a8083063 Iustin Pop

911 72737a7f Iustin Pop
    """
912 9a525d83 Michael Hanselmann
    result = self._SingleNodeCall(node, "os_get", [name])
913 84e3f66f Guido Trotter
    if not result.fail_msg and isinstance(result.payload, dict):
914 84e3f66f Guido Trotter
      result.payload = objects.OS.FromDict(result.payload)
915 781de953 Iustin Pop
    return result
916 a8083063 Iustin Pop
917 72737a7f Iustin Pop
  def call_hooks_runner(self, node_list, hpath, phase, env):
918 72737a7f Iustin Pop
    """Call the hooks runner.
919 a8083063 Iustin Pop

920 72737a7f Iustin Pop
    Args:
921 72737a7f Iustin Pop
      - op: the OpCode instance
922 72737a7f Iustin Pop
      - env: a dictionary with the environment
923 a8083063 Iustin Pop

924 72737a7f Iustin Pop
    This is a multi-node call.
925 a8083063 Iustin Pop

926 72737a7f Iustin Pop
    """
927 72737a7f Iustin Pop
    params = [hpath, phase, env]
928 9a525d83 Michael Hanselmann
    return self._MultiNodeCall(node_list, "hooks_runner", params)
929 a8083063 Iustin Pop
930 72737a7f Iustin Pop
  def call_iallocator_runner(self, node, name, idata):
931 72737a7f Iustin Pop
    """Call an iallocator on a remote node
932 8d528b7c Iustin Pop

933 72737a7f Iustin Pop
    Args:
934 72737a7f Iustin Pop
      - name: the iallocator name
935 72737a7f Iustin Pop
      - input: the json-encoded input string
936 8d528b7c Iustin Pop

937 72737a7f Iustin Pop
    This is a single-node call.
938 8d528b7c Iustin Pop

939 72737a7f Iustin Pop
    """
940 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "iallocator_runner", [name, idata])
941 8d528b7c Iustin Pop
942 72737a7f Iustin Pop
  def call_blockdev_grow(self, node, cf_bdev, amount):
943 72737a7f Iustin Pop
    """Request a snapshot of the given block device.
944 4c8ba8b3 Iustin Pop

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

947 72737a7f Iustin Pop
    """
948 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "blockdev_grow",
949 9a525d83 Michael Hanselmann
                                [cf_bdev.ToDict(), amount])
950 4c8ba8b3 Iustin Pop
951 858f3d18 Iustin Pop
  def call_blockdev_export(self, node, cf_bdev,
952 858f3d18 Iustin Pop
                           dest_node, dest_path, cluster_name):
953 858f3d18 Iustin Pop
    """Export a given disk to another node.
954 858f3d18 Iustin Pop

955 858f3d18 Iustin Pop
    This is a single-node call.
956 858f3d18 Iustin Pop

957 858f3d18 Iustin Pop
    """
958 858f3d18 Iustin Pop
    return self._SingleNodeCall(node, "blockdev_export",
959 858f3d18 Iustin Pop
                                [cf_bdev.ToDict(), dest_node, dest_path,
960 858f3d18 Iustin Pop
                                 cluster_name])
961 858f3d18 Iustin Pop
962 72737a7f Iustin Pop
  def call_blockdev_snapshot(self, node, cf_bdev):
963 72737a7f Iustin Pop
    """Request a snapshot of the given block device.
964 a8083063 Iustin Pop

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

967 72737a7f Iustin Pop
    """
968 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "blockdev_snapshot", [cf_bdev.ToDict()])
969 a8083063 Iustin Pop
970 72737a7f Iustin Pop
  def call_snapshot_export(self, node, snap_bdev, dest_node, instance,
971 74c47259 Iustin Pop
                           cluster_name, idx):
972 72737a7f Iustin Pop
    """Request the export of a given snapshot.
973 a8083063 Iustin Pop

974 72737a7f Iustin Pop
    This is a single-node call.
975 a8083063 Iustin Pop

976 72737a7f Iustin Pop
    """
977 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "snapshot_export",
978 9a525d83 Michael Hanselmann
                                [snap_bdev.ToDict(), dest_node,
979 9a525d83 Michael Hanselmann
                                 self._InstDict(instance), cluster_name, idx])
980 a8083063 Iustin Pop
981 72737a7f Iustin Pop
  def call_finalize_export(self, node, instance, snap_disks):
982 72737a7f Iustin Pop
    """Request the completion of an export operation.
983 a8083063 Iustin Pop

984 72737a7f Iustin Pop
    This writes the export config file, etc.
985 a8083063 Iustin Pop

986 72737a7f Iustin Pop
    This is a single-node call.
987 a8083063 Iustin Pop

988 72737a7f Iustin Pop
    """
989 72737a7f Iustin Pop
    flat_disks = []
990 72737a7f Iustin Pop
    for disk in snap_disks:
991 a97da6b7 Iustin Pop
      if isinstance(disk, bool):
992 a97da6b7 Iustin Pop
        flat_disks.append(disk)
993 a97da6b7 Iustin Pop
      else:
994 a97da6b7 Iustin Pop
        flat_disks.append(disk.ToDict())
995 9a525d83 Michael Hanselmann
996 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "finalize_export",
997 9a525d83 Michael Hanselmann
                                [self._InstDict(instance), flat_disks])
998 a8083063 Iustin Pop
999 72737a7f Iustin Pop
  def call_export_info(self, node, path):
1000 72737a7f Iustin Pop
    """Queries the export information in a given path.
1001 a8083063 Iustin Pop

1002 72737a7f Iustin Pop
    This is a single-node call.
1003 a8083063 Iustin Pop

1004 72737a7f Iustin Pop
    """
1005 3eccac06 Iustin Pop
    return self._SingleNodeCall(node, "export_info", [path])
1006 a8083063 Iustin Pop
1007 6c0af70e Guido Trotter
  def call_instance_os_import(self, node, inst, src_node, src_images,
1008 6c0af70e Guido Trotter
                              cluster_name):
1009 72737a7f Iustin Pop
    """Request the import of a backup into an instance.
1010 a8083063 Iustin Pop

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

1013 72737a7f Iustin Pop
    """
1014 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "instance_os_import",
1015 9a525d83 Michael Hanselmann
                                [self._InstDict(inst), src_node, src_images,
1016 9a525d83 Michael Hanselmann
                                 cluster_name])
1017 a8083063 Iustin Pop
1018 72737a7f Iustin Pop
  def call_export_list(self, node_list):
1019 72737a7f Iustin Pop
    """Gets the stored exports list.
1020 a8083063 Iustin Pop

1021 72737a7f Iustin Pop
    This is a multi-node call.
1022 a8083063 Iustin Pop

1023 72737a7f Iustin Pop
    """
1024 9a525d83 Michael Hanselmann
    return self._MultiNodeCall(node_list, "export_list", [])
1025 a8083063 Iustin Pop
1026 72737a7f Iustin Pop
  def call_export_remove(self, node, export):
1027 72737a7f Iustin Pop
    """Requests removal of a given export.
1028 a8083063 Iustin Pop

1029 72737a7f Iustin Pop
    This is a single-node call.
1030 a8083063 Iustin Pop

1031 72737a7f Iustin Pop
    """
1032 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "export_remove", [export])
1033 a8083063 Iustin Pop
1034 9a525d83 Michael Hanselmann
  @classmethod
1035 9a525d83 Michael Hanselmann
  def call_node_leave_cluster(cls, node):
1036 72737a7f Iustin Pop
    """Requests a node to clean the cluster information it has.
1037 a8083063 Iustin Pop

1038 72737a7f Iustin Pop
    This will remove the configuration information from the ganeti data
1039 72737a7f Iustin Pop
    dir.
1040 a8083063 Iustin Pop

1041 72737a7f Iustin Pop
    This is a single-node call.
1042 a8083063 Iustin Pop

1043 72737a7f Iustin Pop
    """
1044 9a525d83 Michael Hanselmann
    return cls._StaticSingleNodeCall(node, "node_leave_cluster", [])
1045 dcb93971 Michael Hanselmann
1046 72737a7f Iustin Pop
  def call_node_volumes(self, node_list):
1047 72737a7f Iustin Pop
    """Gets all volumes on node(s).
1048 dcb93971 Michael Hanselmann

1049 72737a7f Iustin Pop
    This is a multi-node call.
1050 dcb93971 Michael Hanselmann

1051 72737a7f Iustin Pop
    """
1052 9a525d83 Michael Hanselmann
    return self._MultiNodeCall(node_list, "node_volumes", [])
1053 06009e27 Iustin Pop
1054 56aa9fd5 Iustin Pop
  def call_node_demote_from_mc(self, node):
1055 56aa9fd5 Iustin Pop
    """Demote a node from the master candidate role.
1056 56aa9fd5 Iustin Pop

1057 56aa9fd5 Iustin Pop
    This is a single-node call.
1058 56aa9fd5 Iustin Pop

1059 56aa9fd5 Iustin Pop
    """
1060 56aa9fd5 Iustin Pop
    return self._SingleNodeCall(node, "node_demote_from_mc", [])
1061 56aa9fd5 Iustin Pop
1062 f5118ade Iustin Pop
1063 f5118ade Iustin Pop
  def call_node_powercycle(self, node, hypervisor):
1064 f5118ade Iustin Pop
    """Tries to powercycle a node.
1065 f5118ade Iustin Pop

1066 f5118ade Iustin Pop
    This is a single-node call.
1067 f5118ade Iustin Pop

1068 f5118ade Iustin Pop
    """
1069 f5118ade Iustin Pop
    return self._SingleNodeCall(node, "node_powercycle", [hypervisor])
1070 f5118ade Iustin Pop
1071 f5118ade Iustin Pop
1072 72737a7f Iustin Pop
  def call_test_delay(self, node_list, duration):
1073 72737a7f Iustin Pop
    """Sleep for a fixed time on given node(s).
1074 06009e27 Iustin Pop

1075 72737a7f Iustin Pop
    This is a multi-node call.
1076 06009e27 Iustin Pop

1077 72737a7f Iustin Pop
    """
1078 9a525d83 Michael Hanselmann
    return self._MultiNodeCall(node_list, "test_delay", [duration])
1079 5e04ed8b Manuel Franceschini
1080 72737a7f Iustin Pop
  def call_file_storage_dir_create(self, node, file_storage_dir):
1081 72737a7f Iustin Pop
    """Create the given file storage directory.
1082 5e04ed8b Manuel Franceschini

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

1085 72737a7f Iustin Pop
    """
1086 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "file_storage_dir_create",
1087 9a525d83 Michael Hanselmann
                                [file_storage_dir])
1088 5e04ed8b Manuel Franceschini
1089 72737a7f Iustin Pop
  def call_file_storage_dir_remove(self, node, file_storage_dir):
1090 72737a7f Iustin Pop
    """Remove the given file storage directory.
1091 5e04ed8b Manuel Franceschini

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

1094 72737a7f Iustin Pop
    """
1095 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "file_storage_dir_remove",
1096 9a525d83 Michael Hanselmann
                                [file_storage_dir])
1097 5e04ed8b Manuel Franceschini
1098 72737a7f Iustin Pop
  def call_file_storage_dir_rename(self, node, old_file_storage_dir,
1099 72737a7f Iustin Pop
                                   new_file_storage_dir):
1100 72737a7f Iustin Pop
    """Rename file storage directory.
1101 5e04ed8b Manuel Franceschini

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

1104 72737a7f Iustin Pop
    """
1105 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "file_storage_dir_rename",
1106 9a525d83 Michael Hanselmann
                                [old_file_storage_dir, new_file_storage_dir])
1107 ca52cdeb Michael Hanselmann
1108 9a525d83 Michael Hanselmann
  @classmethod
1109 9a525d83 Michael Hanselmann
  def call_jobqueue_update(cls, node_list, address_list, file_name, content):
1110 72737a7f Iustin Pop
    """Update job queue.
1111 ca52cdeb Michael Hanselmann

1112 72737a7f Iustin Pop
    This is a multi-node call.
1113 ca52cdeb Michael Hanselmann

1114 72737a7f Iustin Pop
    """
1115 9a525d83 Michael Hanselmann
    return cls._StaticMultiNodeCall(node_list, "jobqueue_update",
1116 12bce260 Michael Hanselmann
                                    [file_name, cls._Compress(content)],
1117 9a525d83 Michael Hanselmann
                                    address_list=address_list)
1118 ca52cdeb Michael Hanselmann
1119 9a525d83 Michael Hanselmann
  @classmethod
1120 9a525d83 Michael Hanselmann
  def call_jobqueue_purge(cls, node):
1121 72737a7f Iustin Pop
    """Purge job queue.
1122 ca52cdeb Michael Hanselmann

1123 72737a7f Iustin Pop
    This is a single-node call.
1124 ca52cdeb Michael Hanselmann

1125 72737a7f Iustin Pop
    """
1126 9a525d83 Michael Hanselmann
    return cls._StaticSingleNodeCall(node, "jobqueue_purge", [])
1127 af5ebcb1 Michael Hanselmann
1128 9a525d83 Michael Hanselmann
  @classmethod
1129 dd875d32 Michael Hanselmann
  def call_jobqueue_rename(cls, node_list, address_list, rename):
1130 72737a7f Iustin Pop
    """Rename a job queue file.
1131 af5ebcb1 Michael Hanselmann

1132 72737a7f Iustin Pop
    This is a multi-node call.
1133 af5ebcb1 Michael Hanselmann

1134 72737a7f Iustin Pop
    """
1135 dd875d32 Michael Hanselmann
    return cls._StaticMultiNodeCall(node_list, "jobqueue_rename", rename,
1136 9a525d83 Michael Hanselmann
                                    address_list=address_list)
1137 6217e295 Iustin Pop
1138 9a525d83 Michael Hanselmann
  @classmethod
1139 9a525d83 Michael Hanselmann
  def call_jobqueue_set_drain(cls, node_list, drain_flag):
1140 5d672980 Iustin Pop
    """Set the drain flag on the queue.
1141 5d672980 Iustin Pop

1142 5d672980 Iustin Pop
    This is a multi-node call.
1143 5d672980 Iustin Pop

1144 5d672980 Iustin Pop
    @type node_list: list
1145 5d672980 Iustin Pop
    @param node_list: the list of nodes to query
1146 5d672980 Iustin Pop
    @type drain_flag: bool
1147 5d672980 Iustin Pop
    @param drain_flag: if True, will set the drain flag, otherwise reset it.
1148 5d672980 Iustin Pop

1149 5d672980 Iustin Pop
    """
1150 9a525d83 Michael Hanselmann
    return cls._StaticMultiNodeCall(node_list, "jobqueue_set_drain",
1151 9a525d83 Michael Hanselmann
                                    [drain_flag])
1152 5d672980 Iustin Pop
1153 6217e295 Iustin Pop
  def call_hypervisor_validate_params(self, node_list, hvname, hvparams):
1154 6217e295 Iustin Pop
    """Validate the hypervisor params.
1155 6217e295 Iustin Pop

1156 6217e295 Iustin Pop
    This is a multi-node call.
1157 6217e295 Iustin Pop

1158 6217e295 Iustin Pop
    @type node_list: list
1159 6217e295 Iustin Pop
    @param node_list: the list of nodes to query
1160 6217e295 Iustin Pop
    @type hvname: string
1161 6217e295 Iustin Pop
    @param hvname: the hypervisor name
1162 6217e295 Iustin Pop
    @type hvparams: dict
1163 6217e295 Iustin Pop
    @param hvparams: the hypervisor parameters to be validated
1164 6217e295 Iustin Pop

1165 6217e295 Iustin Pop
    """
1166 6217e295 Iustin Pop
    cluster = self._cfg.GetClusterInfo()
1167 abe609b2 Guido Trotter
    hv_full = objects.FillDict(cluster.hvparams.get(hvname, {}), hvparams)
1168 9a525d83 Michael Hanselmann
    return self._MultiNodeCall(node_list, "hypervisor_validate_params",
1169 9a525d83 Michael Hanselmann
                               [hvname, hv_full])