Statistics
| Branch: | Tag: | Revision:

root / lib / rpc.py @ ec39d63c

History | View | Annotate | Download (35.1 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 8d0a4f99 Michael Hanselmann
  http.InitSsl()
64 8d0a4f99 Michael Hanselmann
65 ae88ef45 Michael Hanselmann
  _http_manager = http.client.HttpClientManager()
66 4331f6cd Michael Hanselmann
67 4331f6cd Michael Hanselmann
68 4331f6cd Michael Hanselmann
def Shutdown():
69 4331f6cd Michael Hanselmann
  """Stops the module-global HTTP client manager.
70 4331f6cd Michael Hanselmann

71 4331f6cd Michael Hanselmann
  Must be called before quitting the program.
72 4331f6cd Michael Hanselmann

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

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

88 5bbd3f7f Michael Hanselmann
  @ivar data: the data payload, for successful results, or None
89 ed83f5cc Iustin Pop
  @ivar call: the name of the RPC call
90 ed83f5cc Iustin Pop
  @ivar node: the name of the node to which we made the call
91 ed83f5cc Iustin Pop
  @ivar offline: whether the operation failed because the node was
92 ed83f5cc Iustin Pop
      offline, as opposed to actual failure; offline=True will always
93 ed83f5cc Iustin Pop
      imply failed=True, in order to allow simpler checking if
94 ed83f5cc Iustin Pop
      the user doesn't care about the exact failure mode
95 4c4e4e1e Iustin Pop
  @ivar fail_msg: the error message if the call failed
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 ed83f5cc Iustin Pop
    self.offline = offline
101 ed83f5cc Iustin Pop
    self.call = call
102 ed83f5cc Iustin Pop
    self.node = node
103 1645d22d Michael Hanselmann
104 ed83f5cc Iustin Pop
    if offline:
105 4c4e4e1e Iustin Pop
      self.fail_msg = "Node is marked offline"
106 f2def43a Iustin Pop
      self.data = self.payload = None
107 ed83f5cc Iustin Pop
    elif failed:
108 4c4e4e1e Iustin Pop
      self.fail_msg = self._EnsureErr(data)
109 f2def43a Iustin Pop
      self.data = self.payload = None
110 781de953 Iustin Pop
    else:
111 781de953 Iustin Pop
      self.data = data
112 d3c8b360 Iustin Pop
      if not isinstance(self.data, (tuple, list)):
113 4c4e4e1e Iustin Pop
        self.fail_msg = ("RPC layer error: invalid result type (%s)" %
114 4c4e4e1e Iustin Pop
                         type(self.data))
115 1645d22d Michael Hanselmann
        self.payload = None
116 d3c8b360 Iustin Pop
      elif len(data) != 2:
117 4c4e4e1e Iustin Pop
        self.fail_msg = ("RPC layer error: invalid result length (%d), "
118 4c4e4e1e Iustin Pop
                         "expected 2" % len(self.data))
119 1645d22d Michael Hanselmann
        self.payload = None
120 d3c8b360 Iustin Pop
      elif not self.data[0]:
121 4c4e4e1e Iustin Pop
        self.fail_msg = self._EnsureErr(self.data[1])
122 1645d22d Michael Hanselmann
        self.payload = None
123 f2def43a Iustin Pop
      else:
124 d3c8b360 Iustin Pop
        # finally success
125 4c4e4e1e Iustin Pop
        self.fail_msg = None
126 d3c8b360 Iustin Pop
        self.payload = data[1]
127 d3c8b360 Iustin Pop
128 1645d22d Michael Hanselmann
    assert hasattr(self, "call")
129 1645d22d Michael Hanselmann
    assert hasattr(self, "data")
130 1645d22d Michael Hanselmann
    assert hasattr(self, "fail_msg")
131 1645d22d Michael Hanselmann
    assert hasattr(self, "node")
132 1645d22d Michael Hanselmann
    assert hasattr(self, "offline")
133 1645d22d Michael Hanselmann
    assert hasattr(self, "payload")
134 1645d22d Michael Hanselmann
135 d3c8b360 Iustin Pop
  @staticmethod
136 d3c8b360 Iustin Pop
  def _EnsureErr(val):
137 d3c8b360 Iustin Pop
    """Helper to ensure we return a 'True' value for error."""
138 d3c8b360 Iustin Pop
    if val:
139 d3c8b360 Iustin Pop
      return val
140 d3c8b360 Iustin Pop
    else:
141 d3c8b360 Iustin Pop
      return "No error information"
142 781de953 Iustin Pop
143 045dd6d9 Iustin Pop
  def Raise(self, msg, prereq=False, ecode=None):
144 781de953 Iustin Pop
    """If the result has failed, raise an OpExecError.
145 781de953 Iustin Pop

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

149 781de953 Iustin Pop
    """
150 4c4e4e1e Iustin Pop
    if not self.fail_msg:
151 4c4e4e1e Iustin Pop
      return
152 4c4e4e1e Iustin Pop
153 4c4e4e1e Iustin Pop
    if not msg: # one could pass None for default message
154 4c4e4e1e Iustin Pop
      msg = ("Call '%s' to node '%s' has failed: %s" %
155 4c4e4e1e Iustin Pop
             (self.call, self.node, self.fail_msg))
156 4c4e4e1e Iustin Pop
    else:
157 4c4e4e1e Iustin Pop
      msg = "%s: %s" % (msg, self.fail_msg)
158 4c4e4e1e Iustin Pop
    if prereq:
159 4c4e4e1e Iustin Pop
      ec = errors.OpPrereqError
160 4c4e4e1e Iustin Pop
    else:
161 4c4e4e1e Iustin Pop
      ec = errors.OpExecError
162 045dd6d9 Iustin Pop
    if ecode is not None:
163 045dd6d9 Iustin Pop
      args = (msg, prereq)
164 045dd6d9 Iustin Pop
    else:
165 045dd6d9 Iustin Pop
      args = (msg, )
166 7260cfbe Iustin Pop
    raise ec(*args) # pylint: disable-msg=W0142
167 781de953 Iustin Pop
168 781de953 Iustin Pop
169 a8083063 Iustin Pop
class Client:
170 a8083063 Iustin Pop
  """RPC Client class.
171 a8083063 Iustin Pop

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

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

180 a8083063 Iustin Pop
  """
181 160e2921 Iustin Pop
  def __init__(self, procedure, body, port):
182 a8083063 Iustin Pop
    self.procedure = procedure
183 160e2921 Iustin Pop
    self.body = body
184 160e2921 Iustin Pop
    self.port = port
185 ecfe9491 Michael Hanselmann
    self.nc = {}
186 a8083063 Iustin Pop
187 d57ae7f7 Michael Hanselmann
    self._ssl_params = \
188 d57ae7f7 Michael Hanselmann
      http.HttpSslParams(ssl_key_path=constants.SSL_CERT_FILE,
189 d57ae7f7 Michael Hanselmann
                         ssl_cert_path=constants.SSL_CERT_FILE)
190 d57ae7f7 Michael Hanselmann
191 bdf7d8c0 Iustin Pop
  def ConnectList(self, node_list, address_list=None):
192 a8083063 Iustin Pop
    """Add a list of nodes to the target nodes.
193 a8083063 Iustin Pop

194 3ef3c771 Iustin Pop
    @type node_list: list
195 3ef3c771 Iustin Pop
    @param node_list: the list of node names to connect
196 bdf7d8c0 Iustin Pop
    @type address_list: list or None
197 bdf7d8c0 Iustin Pop
    @keyword address_list: either None or a list with node addresses,
198 bdf7d8c0 Iustin Pop
        which must have the same length as the node list
199 3ef3c771 Iustin Pop

200 a8083063 Iustin Pop
    """
201 bdf7d8c0 Iustin Pop
    if address_list is None:
202 bdf7d8c0 Iustin Pop
      address_list = [None for _ in node_list]
203 bdf7d8c0 Iustin Pop
    else:
204 bdf7d8c0 Iustin Pop
      assert len(node_list) == len(address_list), \
205 bdf7d8c0 Iustin Pop
             "Name and address lists should have the same length"
206 bdf7d8c0 Iustin Pop
    for node, address in zip(node_list, address_list):
207 bdf7d8c0 Iustin Pop
      self.ConnectNode(node, address)
208 bdf7d8c0 Iustin Pop
209 bdf7d8c0 Iustin Pop
  def ConnectNode(self, name, address=None):
210 a8083063 Iustin Pop
    """Add a node to the target list.
211 a8083063 Iustin Pop

212 bdf7d8c0 Iustin Pop
    @type name: str
213 bdf7d8c0 Iustin Pop
    @param name: the node name
214 bdf7d8c0 Iustin Pop
    @type address: str
215 bdf7d8c0 Iustin Pop
    @keyword address: the node address, if known
216 bdf7d8c0 Iustin Pop

217 a8083063 Iustin Pop
    """
218 ecfe9491 Michael Hanselmann
    if address is None:
219 ecfe9491 Michael Hanselmann
      address = name
220 ecfe9491 Michael Hanselmann
221 ae88ef45 Michael Hanselmann
    self.nc[name] = \
222 ae88ef45 Michael Hanselmann
      http.client.HttpClientRequest(address, self.port, http.HTTP_PUT,
223 ae88ef45 Michael Hanselmann
                                    "/%s" % self.procedure,
224 ae88ef45 Michael Hanselmann
                                    post_data=self.body,
225 ae88ef45 Michael Hanselmann
                                    ssl_params=self._ssl_params,
226 ae88ef45 Michael Hanselmann
                                    ssl_verify_peer=True)
227 a8083063 Iustin Pop
228 3ef3c771 Iustin Pop
  def GetResults(self):
229 ecfe9491 Michael Hanselmann
    """Call nodes and return results.
230 ecfe9491 Michael Hanselmann

231 ecfe9491 Michael Hanselmann
    @rtype: list
232 5fcc718f Iustin Pop
    @return: List of RPC results
233 a8083063 Iustin Pop

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

267 72737a7f Iustin Pop
    @type cfg:  C{config.ConfigWriter}
268 72737a7f Iustin Pop
    @param cfg: the configuration object that will be used to get data
269 72737a7f Iustin Pop
                about the cluster
270 a8083063 Iustin Pop

271 72737a7f Iustin Pop
    """
272 72737a7f Iustin Pop
    self._cfg = cfg
273 cd50653c Guido Trotter
    self.port = utils.GetDaemonPort(constants.NODED)
274 a8083063 Iustin Pop
275 0eca8e0c Iustin Pop
  def _InstDict(self, instance, hvp=None, bep=None):
276 26ba2bd8 Iustin Pop
    """Convert the given instance to a dict.
277 26ba2bd8 Iustin Pop

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

281 26ba2bd8 Iustin Pop
    @type instance: L{objects.Instance}
282 26ba2bd8 Iustin Pop
    @param instance: an Instance object
283 0eca8e0c Iustin Pop
    @type hvp: dict or None
284 5bbd3f7f Michael Hanselmann
    @param hvp: a dictionary with overridden hypervisor parameters
285 0eca8e0c Iustin Pop
    @type bep: dict or None
286 5bbd3f7f Michael Hanselmann
    @param bep: a dictionary with overridden backend parameters
287 26ba2bd8 Iustin Pop
    @rtype: dict
288 26ba2bd8 Iustin Pop
    @return: the instance dict, with the hvparams filled with the
289 26ba2bd8 Iustin Pop
        cluster defaults
290 26ba2bd8 Iustin Pop

291 26ba2bd8 Iustin Pop
    """
292 26ba2bd8 Iustin Pop
    idict = instance.ToDict()
293 5b442704 Iustin Pop
    cluster = self._cfg.GetClusterInfo()
294 5b442704 Iustin Pop
    idict["hvparams"] = cluster.FillHV(instance)
295 0eca8e0c Iustin Pop
    if hvp is not None:
296 0eca8e0c Iustin Pop
      idict["hvparams"].update(hvp)
297 5b442704 Iustin Pop
    idict["beparams"] = cluster.FillBE(instance)
298 0eca8e0c Iustin Pop
    if bep is not None:
299 0eca8e0c Iustin Pop
      idict["beparams"].update(bep)
300 b848ce79 Guido Trotter
    for nic in idict["nics"]:
301 b848ce79 Guido Trotter
      nic['nicparams'] = objects.FillDict(
302 b848ce79 Guido Trotter
        cluster.nicparams[constants.PP_DEFAULT],
303 b848ce79 Guido Trotter
        nic['nicparams'])
304 26ba2bd8 Iustin Pop
    return idict
305 26ba2bd8 Iustin Pop
306 84b45587 Iustin Pop
  def _ConnectList(self, client, node_list, call):
307 25348212 Iustin Pop
    """Helper for computing node addresses.
308 25348212 Iustin Pop

309 6af6270a Iustin Pop
    @type client: L{ganeti.rpc.Client}
310 25348212 Iustin Pop
    @param client: a C{Client} instance
311 25348212 Iustin Pop
    @type node_list: list
312 25348212 Iustin Pop
    @param node_list: the node list we should connect
313 84b45587 Iustin Pop
    @type call: string
314 84b45587 Iustin Pop
    @param call: the name of the remote procedure call, for filling in
315 84b45587 Iustin Pop
        correctly any eventual offline nodes' results
316 25348212 Iustin Pop

317 25348212 Iustin Pop
    """
318 25348212 Iustin Pop
    all_nodes = self._cfg.GetAllNodesInfo()
319 ed83f5cc Iustin Pop
    name_list = []
320 25348212 Iustin Pop
    addr_list = []
321 ed83f5cc Iustin Pop
    skip_dict = {}
322 25348212 Iustin Pop
    for node in node_list:
323 25348212 Iustin Pop
      if node in all_nodes:
324 ed83f5cc Iustin Pop
        if all_nodes[node].offline:
325 84b45587 Iustin Pop
          skip_dict[node] = RpcResult(node=node, offline=True, call=call)
326 ed83f5cc Iustin Pop
          continue
327 25348212 Iustin Pop
        val = all_nodes[node].primary_ip
328 25348212 Iustin Pop
      else:
329 25348212 Iustin Pop
        val = None
330 25348212 Iustin Pop
      addr_list.append(val)
331 ed83f5cc Iustin Pop
      name_list.append(node)
332 ed83f5cc Iustin Pop
    if name_list:
333 ed83f5cc Iustin Pop
      client.ConnectList(name_list, address_list=addr_list)
334 ed83f5cc Iustin Pop
    return skip_dict
335 25348212 Iustin Pop
336 84b45587 Iustin Pop
  def _ConnectNode(self, client, node, call):
337 25348212 Iustin Pop
    """Helper for computing one node's address.
338 25348212 Iustin Pop

339 6af6270a Iustin Pop
    @type client: L{ganeti.rpc.Client}
340 25348212 Iustin Pop
    @param client: a C{Client} instance
341 25348212 Iustin Pop
    @type node: str
342 25348212 Iustin Pop
    @param node: the node we should connect
343 84b45587 Iustin Pop
    @type call: string
344 84b45587 Iustin Pop
    @param call: the name of the remote procedure call, for filling in
345 84b45587 Iustin Pop
        correctly any eventual offline nodes' results
346 25348212 Iustin Pop

347 25348212 Iustin Pop
    """
348 25348212 Iustin Pop
    node_info = self._cfg.GetNodeInfo(node)
349 25348212 Iustin Pop
    if node_info is not None:
350 ed83f5cc Iustin Pop
      if node_info.offline:
351 84b45587 Iustin Pop
        return RpcResult(node=node, offline=True, call=call)
352 25348212 Iustin Pop
      addr = node_info.primary_ip
353 25348212 Iustin Pop
    else:
354 25348212 Iustin Pop
      addr = None
355 25348212 Iustin Pop
    client.ConnectNode(node, address=addr)
356 25348212 Iustin Pop
357 ed83f5cc Iustin Pop
  def _MultiNodeCall(self, node_list, procedure, args):
358 160e2921 Iustin Pop
    """Helper for making a multi-node call
359 160e2921 Iustin Pop

360 160e2921 Iustin Pop
    """
361 160e2921 Iustin Pop
    body = serializer.DumpJson(args, indent=False)
362 160e2921 Iustin Pop
    c = Client(procedure, body, self.port)
363 84b45587 Iustin Pop
    skip_dict = self._ConnectList(c, node_list, procedure)
364 ed83f5cc Iustin Pop
    skip_dict.update(c.GetResults())
365 ed83f5cc Iustin Pop
    return skip_dict
366 9a525d83 Michael Hanselmann
367 9a525d83 Michael Hanselmann
  @classmethod
368 9a525d83 Michael Hanselmann
  def _StaticMultiNodeCall(cls, node_list, procedure, args,
369 9a525d83 Michael Hanselmann
                           address_list=None):
370 160e2921 Iustin Pop
    """Helper for making a multi-node static call
371 160e2921 Iustin Pop

372 160e2921 Iustin Pop
    """
373 160e2921 Iustin Pop
    body = serializer.DumpJson(args, indent=False)
374 cd50653c Guido Trotter
    c = Client(procedure, body, utils.GetDaemonPort(constants.NODED))
375 9a525d83 Michael Hanselmann
    c.ConnectList(node_list, address_list=address_list)
376 9a525d83 Michael Hanselmann
    return c.GetResults()
377 9a525d83 Michael Hanselmann
378 9a525d83 Michael Hanselmann
  def _SingleNodeCall(self, node, procedure, args):
379 160e2921 Iustin Pop
    """Helper for making a single-node call
380 9a525d83 Michael Hanselmann

381 9a525d83 Michael Hanselmann
    """
382 160e2921 Iustin Pop
    body = serializer.DumpJson(args, indent=False)
383 160e2921 Iustin Pop
    c = Client(procedure, body, self.port)
384 84b45587 Iustin Pop
    result = self._ConnectNode(c, node, procedure)
385 ed83f5cc Iustin Pop
    if result is None:
386 ed83f5cc Iustin Pop
      # we did connect, node is not offline
387 ed83f5cc Iustin Pop
      result = c.GetResults()[node]
388 ed83f5cc Iustin Pop
    return result
389 9a525d83 Michael Hanselmann
390 9a525d83 Michael Hanselmann
  @classmethod
391 9a525d83 Michael Hanselmann
  def _StaticSingleNodeCall(cls, node, procedure, args):
392 160e2921 Iustin Pop
    """Helper for making a single-node static call
393 9a525d83 Michael Hanselmann

394 9a525d83 Michael Hanselmann
    """
395 160e2921 Iustin Pop
    body = serializer.DumpJson(args, indent=False)
396 cd50653c Guido Trotter
    c = Client(procedure, body, utils.GetDaemonPort(constants.NODED))
397 3097c858 Michael Hanselmann
    c.ConnectNode(node)
398 ed83f5cc Iustin Pop
    return c.GetResults()[node]
399 9a525d83 Michael Hanselmann
400 12bce260 Michael Hanselmann
  @staticmethod
401 12bce260 Michael Hanselmann
  def _Compress(data):
402 12bce260 Michael Hanselmann
    """Compresses a string for transport over RPC.
403 12bce260 Michael Hanselmann

404 12bce260 Michael Hanselmann
    Small amounts of data are not compressed.
405 12bce260 Michael Hanselmann

406 12bce260 Michael Hanselmann
    @type data: str
407 12bce260 Michael Hanselmann
    @param data: Data
408 12bce260 Michael Hanselmann
    @rtype: tuple
409 12bce260 Michael Hanselmann
    @return: Encoded data to send
410 12bce260 Michael Hanselmann

411 12bce260 Michael Hanselmann
    """
412 12bce260 Michael Hanselmann
    # Small amounts of data are not compressed
413 12bce260 Michael Hanselmann
    if len(data) < 512:
414 12bce260 Michael Hanselmann
      return (constants.RPC_ENCODING_NONE, data)
415 12bce260 Michael Hanselmann
416 12bce260 Michael Hanselmann
    # Compress with zlib and encode in base64
417 12bce260 Michael Hanselmann
    return (constants.RPC_ENCODING_ZLIB_BASE64,
418 12bce260 Michael Hanselmann
            base64.b64encode(zlib.compress(data, 3)))
419 12bce260 Michael Hanselmann
420 781de953 Iustin Pop
  #
421 781de953 Iustin Pop
  # Begin RPC calls
422 781de953 Iustin Pop
  #
423 781de953 Iustin Pop
424 b2a6ccd4 Iustin Pop
  def call_lv_list(self, node_list, vg_name):
425 72737a7f Iustin Pop
    """Gets the logical volumes present in a given volume group.
426 a8083063 Iustin Pop

427 72737a7f Iustin Pop
    This is a multi-node call.
428 a8083063 Iustin Pop

429 72737a7f Iustin Pop
    """
430 b2a6ccd4 Iustin Pop
    return self._MultiNodeCall(node_list, "lv_list", [vg_name])
431 a8083063 Iustin Pop
432 72737a7f Iustin Pop
  def call_vg_list(self, node_list):
433 72737a7f Iustin Pop
    """Gets the volume group list.
434 a8083063 Iustin Pop

435 72737a7f Iustin Pop
    This is a multi-node call.
436 a8083063 Iustin Pop

437 72737a7f Iustin Pop
    """
438 9a525d83 Michael Hanselmann
    return self._MultiNodeCall(node_list, "vg_list", [])
439 a8083063 Iustin Pop
440 e337de97 Michael Hanselmann
  def call_storage_list(self, node_list, su_name, su_args, name, fields):
441 8979196a Michael Hanselmann
    """Get list of storage units.
442 e337de97 Michael Hanselmann

443 e337de97 Michael Hanselmann
    This is a multi-node call.
444 e337de97 Michael Hanselmann

445 e337de97 Michael Hanselmann
    """
446 e337de97 Michael Hanselmann
    return self._MultiNodeCall(node_list, "storage_list",
447 e337de97 Michael Hanselmann
                               [su_name, su_args, name, fields])
448 e337de97 Michael Hanselmann
449 8979196a Michael Hanselmann
  def call_storage_modify(self, node, su_name, su_args, name, changes):
450 8979196a Michael Hanselmann
    """Modify a storage unit.
451 8979196a Michael Hanselmann

452 8979196a Michael Hanselmann
    This is a single-node call.
453 8979196a Michael Hanselmann

454 8979196a Michael Hanselmann
    """
455 8979196a Michael Hanselmann
    return self._SingleNodeCall(node, "storage_modify",
456 8979196a Michael Hanselmann
                                [su_name, su_args, name, changes])
457 8979196a Michael Hanselmann
458 637b8d7e Michael Hanselmann
  def call_storage_execute(self, node, su_name, su_args, name, op):
459 637b8d7e Michael Hanselmann
    """Executes an operation on a storage unit.
460 637b8d7e Michael Hanselmann

461 637b8d7e Michael Hanselmann
    This is a single-node call.
462 637b8d7e Michael Hanselmann

463 637b8d7e Michael Hanselmann
    """
464 637b8d7e Michael Hanselmann
    return self._SingleNodeCall(node, "storage_execute",
465 637b8d7e Michael Hanselmann
                                [su_name, su_args, name, op])
466 637b8d7e Michael Hanselmann
467 72737a7f Iustin Pop
  def call_bridges_exist(self, node, bridges_list):
468 72737a7f Iustin Pop
    """Checks if a node has all the bridges given.
469 a8083063 Iustin Pop

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

474 72737a7f Iustin Pop
    This is a single-node call.
475 a8083063 Iustin Pop

476 72737a7f Iustin Pop
    """
477 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "bridges_exist", [bridges_list])
478 a8083063 Iustin Pop
479 0eca8e0c Iustin Pop
  def call_instance_start(self, node, instance, hvp, bep):
480 72737a7f Iustin Pop
    """Starts an instance.
481 a8083063 Iustin Pop

482 72737a7f Iustin Pop
    This is a single-node call.
483 a8083063 Iustin Pop

484 72737a7f Iustin Pop
    """
485 0eca8e0c Iustin Pop
    idict = self._InstDict(instance, hvp=hvp, bep=bep)
486 0eca8e0c Iustin Pop
    return self._SingleNodeCall(node, "instance_start", [idict])
487 a8083063 Iustin Pop
488 6263189c Guido Trotter
  def call_instance_shutdown(self, node, instance, timeout):
489 72737a7f Iustin Pop
    """Stops an instance.
490 a8083063 Iustin Pop

491 72737a7f Iustin Pop
    This is a single-node call.
492 2a10865c Iustin Pop

493 72737a7f Iustin Pop
    """
494 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "instance_shutdown",
495 6263189c Guido Trotter
                                [self._InstDict(instance), timeout])
496 2a10865c Iustin Pop
497 6906a9d8 Guido Trotter
  def call_migration_info(self, node, instance):
498 6906a9d8 Guido Trotter
    """Gather the information necessary to prepare an instance migration.
499 6906a9d8 Guido Trotter

500 6906a9d8 Guido Trotter
    This is a single-node call.
501 6906a9d8 Guido Trotter

502 6906a9d8 Guido Trotter
    @type node: string
503 6906a9d8 Guido Trotter
    @param node: the node on which the instance is currently running
504 6906a9d8 Guido Trotter
    @type instance: C{objects.Instance}
505 6906a9d8 Guido Trotter
    @param instance: the instance definition
506 6906a9d8 Guido Trotter

507 6906a9d8 Guido Trotter
    """
508 6906a9d8 Guido Trotter
    return self._SingleNodeCall(node, "migration_info",
509 6906a9d8 Guido Trotter
                                [self._InstDict(instance)])
510 6906a9d8 Guido Trotter
511 6906a9d8 Guido Trotter
  def call_accept_instance(self, node, instance, info, target):
512 6906a9d8 Guido Trotter
    """Prepare a node to accept an instance.
513 6906a9d8 Guido Trotter

514 6906a9d8 Guido Trotter
    This is a single-node call.
515 6906a9d8 Guido Trotter

516 6906a9d8 Guido Trotter
    @type node: string
517 6906a9d8 Guido Trotter
    @param node: the target node for the migration
518 6906a9d8 Guido Trotter
    @type instance: C{objects.Instance}
519 6906a9d8 Guido Trotter
    @param instance: the instance definition
520 6906a9d8 Guido Trotter
    @type info: opaque/hypervisor specific (string/data)
521 6906a9d8 Guido Trotter
    @param info: result for the call_migration_info call
522 6906a9d8 Guido Trotter
    @type target: string
523 6906a9d8 Guido Trotter
    @param target: target hostname (usually ip address) (on the node itself)
524 6906a9d8 Guido Trotter

525 6906a9d8 Guido Trotter
    """
526 6906a9d8 Guido Trotter
    return self._SingleNodeCall(node, "accept_instance",
527 6906a9d8 Guido Trotter
                                [self._InstDict(instance), info, target])
528 6906a9d8 Guido Trotter
529 6906a9d8 Guido Trotter
  def call_finalize_migration(self, node, instance, info, success):
530 6906a9d8 Guido Trotter
    """Finalize any target-node migration specific operation.
531 6906a9d8 Guido Trotter

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

535 6906a9d8 Guido Trotter
    This is a single-node call.
536 6906a9d8 Guido Trotter

537 6906a9d8 Guido Trotter
    @type node: string
538 6906a9d8 Guido Trotter
    @param node: the target node for the migration
539 6906a9d8 Guido Trotter
    @type instance: C{objects.Instance}
540 6906a9d8 Guido Trotter
    @param instance: the instance definition
541 6906a9d8 Guido Trotter
    @type info: opaque/hypervisor specific (string/data)
542 6906a9d8 Guido Trotter
    @param info: result for the call_migration_info call
543 6906a9d8 Guido Trotter
    @type success: boolean
544 6906a9d8 Guido Trotter
    @param success: whether the migration was a success or a failure
545 6906a9d8 Guido Trotter

546 6906a9d8 Guido Trotter
    """
547 6906a9d8 Guido Trotter
    return self._SingleNodeCall(node, "finalize_migration",
548 6906a9d8 Guido Trotter
                                [self._InstDict(instance), info, success])
549 6906a9d8 Guido Trotter
550 72737a7f Iustin Pop
  def call_instance_migrate(self, node, instance, target, live):
551 72737a7f Iustin Pop
    """Migrate an instance.
552 2a10865c Iustin Pop

553 72737a7f Iustin Pop
    This is a single-node call.
554 2a10865c Iustin Pop

555 72737a7f Iustin Pop
    @type node: string
556 72737a7f Iustin Pop
    @param node: the node on which the instance is currently running
557 72737a7f Iustin Pop
    @type instance: C{objects.Instance}
558 72737a7f Iustin Pop
    @param instance: the instance definition
559 72737a7f Iustin Pop
    @type target: string
560 72737a7f Iustin Pop
    @param target: the target node name
561 72737a7f Iustin Pop
    @type live: boolean
562 72737a7f Iustin Pop
    @param live: whether the migration should be done live or not (the
563 72737a7f Iustin Pop
        interpretation of this parameter is left to the hypervisor)
564 007a2f3e Alexander Schreiber

565 72737a7f Iustin Pop
    """
566 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "instance_migrate",
567 9a525d83 Michael Hanselmann
                                [self._InstDict(instance), target, live])
568 007a2f3e Alexander Schreiber
569 17c3f802 Guido Trotter
  def call_instance_reboot(self, node, inst, reboot_type, shutdown_timeout):
570 72737a7f Iustin Pop
    """Reboots an instance.
571 007a2f3e Alexander Schreiber

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_reboot",
576 17c3f802 Guido Trotter
                                [self._InstDict(inst), reboot_type,
577 17c3f802 Guido Trotter
                                 shutdown_timeout])
578 a8083063 Iustin Pop
579 e557bae9 Guido Trotter
  def call_instance_os_add(self, node, inst, reinstall):
580 72737a7f Iustin Pop
    """Installs an OS on the given instance.
581 a8083063 Iustin Pop

582 72737a7f Iustin Pop
    This is a single-node call.
583 decd5f45 Iustin Pop

584 72737a7f Iustin Pop
    """
585 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "instance_os_add",
586 e557bae9 Guido Trotter
                                [self._InstDict(inst), reinstall])
587 decd5f45 Iustin Pop
588 d15a9ad3 Guido Trotter
  def call_instance_run_rename(self, node, inst, old_name):
589 72737a7f Iustin Pop
    """Run the OS rename script for an instance.
590 decd5f45 Iustin Pop

591 72737a7f Iustin Pop
    This is a single-node call.
592 a8083063 Iustin Pop

593 72737a7f Iustin Pop
    """
594 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "instance_run_rename",
595 9a525d83 Michael Hanselmann
                                [self._InstDict(inst), old_name])
596 a8083063 Iustin Pop
597 72737a7f Iustin Pop
  def call_instance_info(self, node, instance, hname):
598 72737a7f Iustin Pop
    """Returns information about a single instance.
599 a8083063 Iustin Pop

600 72737a7f Iustin Pop
    This is a single-node call.
601 a8083063 Iustin Pop

602 9a525d83 Michael Hanselmann
    @type node: list
603 9a525d83 Michael Hanselmann
    @param node: the list of nodes to query
604 72737a7f Iustin Pop
    @type instance: string
605 72737a7f Iustin Pop
    @param instance: the instance name
606 72737a7f Iustin Pop
    @type hname: string
607 72737a7f Iustin Pop
    @param hname: the hypervisor type of the instance
608 a8083063 Iustin Pop

609 72737a7f Iustin Pop
    """
610 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "instance_info", [instance, hname])
611 e69d05fd Iustin Pop
612 56e7640c Iustin Pop
  def call_instance_migratable(self, node, instance):
613 56e7640c Iustin Pop
    """Checks whether the given instance can be migrated.
614 56e7640c Iustin Pop

615 56e7640c Iustin Pop
    This is a single-node call.
616 56e7640c Iustin Pop

617 56e7640c Iustin Pop
    @param node: the node to query
618 56e7640c Iustin Pop
    @type instance: L{objects.Instance}
619 56e7640c Iustin Pop
    @param instance: the instance to check
620 56e7640c Iustin Pop

621 56e7640c Iustin Pop

622 56e7640c Iustin Pop
    """
623 56e7640c Iustin Pop
    return self._SingleNodeCall(node, "instance_migratable",
624 56e7640c Iustin Pop
                                [self._InstDict(instance)])
625 56e7640c Iustin Pop
626 72737a7f Iustin Pop
  def call_all_instances_info(self, node_list, hypervisor_list):
627 72737a7f Iustin Pop
    """Returns information about all instances on the given nodes.
628 a8083063 Iustin Pop

629 72737a7f Iustin Pop
    This is a multi-node call.
630 a8083063 Iustin Pop

631 72737a7f Iustin Pop
    @type node_list: list
632 72737a7f Iustin Pop
    @param node_list: the list of nodes to query
633 72737a7f Iustin Pop
    @type hypervisor_list: list
634 72737a7f Iustin Pop
    @param hypervisor_list: the hypervisors to query for instances
635 a8083063 Iustin Pop

636 72737a7f Iustin Pop
    """
637 9a525d83 Michael Hanselmann
    return self._MultiNodeCall(node_list, "all_instances_info",
638 9a525d83 Michael Hanselmann
                               [hypervisor_list])
639 e69d05fd Iustin Pop
640 72737a7f Iustin Pop
  def call_instance_list(self, node_list, hypervisor_list):
641 72737a7f Iustin Pop
    """Returns the list of running instances on a given node.
642 a8083063 Iustin Pop

643 72737a7f Iustin Pop
    This is a multi-node call.
644 a8083063 Iustin Pop

645 72737a7f Iustin Pop
    @type node_list: list
646 72737a7f Iustin Pop
    @param node_list: the list of nodes to query
647 72737a7f Iustin Pop
    @type hypervisor_list: list
648 72737a7f Iustin Pop
    @param hypervisor_list: the hypervisors to query for instances
649 16abfbc2 Alexander Schreiber

650 72737a7f Iustin Pop
    """
651 9a525d83 Michael Hanselmann
    return self._MultiNodeCall(node_list, "instance_list", [hypervisor_list])
652 16abfbc2 Alexander Schreiber
653 72737a7f Iustin Pop
  def call_node_tcp_ping(self, node, source, target, port, timeout,
654 72737a7f Iustin Pop
                         live_port_needed):
655 72737a7f Iustin Pop
    """Do a TcpPing on the remote node
656 a8083063 Iustin Pop

657 72737a7f Iustin Pop
    This is a single-node call.
658 caad16e2 Iustin Pop

659 72737a7f Iustin Pop
    """
660 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "node_tcp_ping",
661 9a525d83 Michael Hanselmann
                                [source, target, port, timeout,
662 72737a7f Iustin Pop
                                 live_port_needed])
663 a8083063 Iustin Pop
664 caad16e2 Iustin Pop
  def call_node_has_ip_address(self, node, address):
665 caad16e2 Iustin Pop
    """Checks if a node has the given IP address.
666 caad16e2 Iustin Pop

667 caad16e2 Iustin Pop
    This is a single-node call.
668 caad16e2 Iustin Pop

669 caad16e2 Iustin Pop
    """
670 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "node_has_ip_address", [address])
671 a8083063 Iustin Pop
672 72737a7f Iustin Pop
  def call_node_info(self, node_list, vg_name, hypervisor_type):
673 72737a7f Iustin Pop
    """Return node information.
674 e69d05fd Iustin Pop

675 72737a7f Iustin Pop
    This will return memory information and volume group size and free
676 72737a7f Iustin Pop
    space.
677 a8083063 Iustin Pop

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

680 72737a7f Iustin Pop
    @type node_list: list
681 72737a7f Iustin Pop
    @param node_list: the list of nodes to query
682 c41eea6e Iustin Pop
    @type vg_name: C{string}
683 c41eea6e Iustin Pop
    @param vg_name: the name of the volume group to ask for disk space
684 72737a7f Iustin Pop
        information
685 72737a7f Iustin Pop
    @type hypervisor_type: C{str}
686 72737a7f Iustin Pop
    @param hypervisor_type: the name of the hypervisor to ask for
687 72737a7f Iustin Pop
        memory information
688 a8083063 Iustin Pop

689 72737a7f Iustin Pop
    """
690 070e998b Iustin Pop
    return self._MultiNodeCall(node_list, "node_info",
691 070e998b Iustin Pop
                               [vg_name, hypervisor_type])
692 a8083063 Iustin Pop
693 72737a7f Iustin Pop
  def call_node_add(self, node, dsa, dsapub, rsa, rsapub, ssh, sshpub):
694 72737a7f Iustin Pop
    """Add a node to the cluster.
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 self._SingleNodeCall(node, "node_add",
700 9a525d83 Michael Hanselmann
                                [dsa, dsapub, rsa, rsapub, ssh, sshpub])
701 a8083063 Iustin Pop
702 72737a7f Iustin Pop
  def call_node_verify(self, node_list, checkdict, cluster_name):
703 72737a7f Iustin Pop
    """Request verification of given parameters.
704 a8083063 Iustin Pop

705 72737a7f Iustin Pop
    This is a multi-node call.
706 a8083063 Iustin Pop

707 72737a7f Iustin Pop
    """
708 9a525d83 Michael Hanselmann
    return self._MultiNodeCall(node_list, "node_verify",
709 9a525d83 Michael Hanselmann
                               [checkdict, cluster_name])
710 a8083063 Iustin Pop
711 9a525d83 Michael Hanselmann
  @classmethod
712 3583908a Guido Trotter
  def call_node_start_master(cls, node, start_daemons, no_voting):
713 72737a7f Iustin Pop
    """Tells a node to activate itself as a master.
714 a8083063 Iustin Pop

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

717 72737a7f Iustin Pop
    """
718 9a525d83 Michael Hanselmann
    return cls._StaticSingleNodeCall(node, "node_start_master",
719 3583908a Guido Trotter
                                     [start_daemons, no_voting])
720 a8083063 Iustin Pop
721 9a525d83 Michael Hanselmann
  @classmethod
722 9a525d83 Michael Hanselmann
  def call_node_stop_master(cls, node, stop_daemons):
723 72737a7f Iustin Pop
    """Tells a node to demote itself from master status.
724 a8083063 Iustin Pop

725 72737a7f Iustin Pop
    This is a single-node call.
726 4e071d3b Iustin Pop

727 72737a7f Iustin Pop
    """
728 9a525d83 Michael Hanselmann
    return cls._StaticSingleNodeCall(node, "node_stop_master", [stop_daemons])
729 4e071d3b Iustin Pop
730 9a525d83 Michael Hanselmann
  @classmethod
731 9a525d83 Michael Hanselmann
  def call_master_info(cls, node_list):
732 72737a7f Iustin Pop
    """Query master info.
733 4e071d3b Iustin Pop

734 72737a7f Iustin Pop
    This is a multi-node call.
735 a8083063 Iustin Pop

736 72737a7f Iustin Pop
    """
737 72737a7f Iustin Pop
    # TODO: should this method query down nodes?
738 9a525d83 Michael Hanselmann
    return cls._StaticMultiNodeCall(node_list, "master_info", [])
739 a8083063 Iustin Pop
740 8f215968 Michael Hanselmann
  @classmethod
741 8f215968 Michael Hanselmann
  def call_version(cls, node_list):
742 72737a7f Iustin Pop
    """Query node version.
743 a8083063 Iustin Pop

744 72737a7f Iustin Pop
    This is a multi-node call.
745 a8083063 Iustin Pop

746 72737a7f Iustin Pop
    """
747 8f215968 Michael Hanselmann
    return cls._StaticMultiNodeCall(node_list, "version", [])
748 a8083063 Iustin Pop
749 72737a7f Iustin Pop
  def call_blockdev_create(self, node, bdev, size, owner, on_primary, info):
750 72737a7f Iustin Pop
    """Request creation of a given block device.
751 a8083063 Iustin Pop

752 72737a7f Iustin Pop
    This is a single-node call.
753 a8083063 Iustin Pop

754 72737a7f Iustin Pop
    """
755 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "blockdev_create",
756 9a525d83 Michael Hanselmann
                                [bdev.ToDict(), size, owner, on_primary, info])
757 a8083063 Iustin Pop
758 72737a7f Iustin Pop
  def call_blockdev_remove(self, node, bdev):
759 72737a7f Iustin Pop
    """Request removal of a given block device.
760 a8083063 Iustin Pop

761 72737a7f Iustin Pop
    This is a single-node call.
762 f3e513ad Iustin Pop

763 72737a7f Iustin Pop
    """
764 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "blockdev_remove", [bdev.ToDict()])
765 f3e513ad Iustin Pop
766 72737a7f Iustin Pop
  def call_blockdev_rename(self, node, devlist):
767 72737a7f Iustin Pop
    """Request rename of the given block devices.
768 f3e513ad Iustin Pop

769 72737a7f Iustin Pop
    This is a single-node call.
770 a8083063 Iustin Pop

771 72737a7f Iustin Pop
    """
772 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "blockdev_rename",
773 9a525d83 Michael Hanselmann
                                [(d.ToDict(), uid) for d, uid in devlist])
774 a8083063 Iustin Pop
775 72737a7f Iustin Pop
  def call_blockdev_assemble(self, node, disk, owner, on_primary):
776 72737a7f Iustin Pop
    """Request assembling of a given block device.
777 a8083063 Iustin Pop

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

780 72737a7f Iustin Pop
    """
781 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "blockdev_assemble",
782 9a525d83 Michael Hanselmann
                                [disk.ToDict(), owner, on_primary])
783 a8083063 Iustin Pop
784 72737a7f Iustin Pop
  def call_blockdev_shutdown(self, node, disk):
785 72737a7f Iustin Pop
    """Request shutdown of a given block 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_shutdown", [disk.ToDict()])
791 a8083063 Iustin Pop
792 72737a7f Iustin Pop
  def call_blockdev_addchildren(self, node, bdev, ndevs):
793 72737a7f Iustin Pop
    """Request adding a list of children to 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 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "blockdev_addchildren",
799 9a525d83 Michael Hanselmann
                                [bdev.ToDict(),
800 9a525d83 Michael Hanselmann
                                 [disk.ToDict() for disk in ndevs]])
801 a8083063 Iustin Pop
802 72737a7f Iustin Pop
  def call_blockdev_removechildren(self, node, bdev, ndevs):
803 72737a7f Iustin Pop
    """Request removing a list of children from a (mirroring) device.
804 a8083063 Iustin Pop

805 72737a7f Iustin Pop
    This is a single-node call.
806 a8083063 Iustin Pop

807 72737a7f Iustin Pop
    """
808 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "blockdev_removechildren",
809 9a525d83 Michael Hanselmann
                                [bdev.ToDict(),
810 9a525d83 Michael Hanselmann
                                 [disk.ToDict() for disk in ndevs]])
811 a8083063 Iustin Pop
812 72737a7f Iustin Pop
  def call_blockdev_getmirrorstatus(self, node, disks):
813 72737a7f Iustin Pop
    """Request status of a (mirroring) device.
814 a8083063 Iustin Pop

815 72737a7f Iustin Pop
    This is a single-node call.
816 a8083063 Iustin Pop

817 72737a7f Iustin Pop
    """
818 36145b12 Michael Hanselmann
    result = self._SingleNodeCall(node, "blockdev_getmirrorstatus",
819 36145b12 Michael Hanselmann
                                  [dsk.ToDict() for dsk in disks])
820 edb4b374 Michael Hanselmann
    if not result.fail_msg:
821 36145b12 Michael Hanselmann
      result.payload = [objects.BlockDevStatus.FromDict(i)
822 36145b12 Michael Hanselmann
                        for i in result.payload]
823 36145b12 Michael Hanselmann
    return result
824 a8083063 Iustin Pop
825 72737a7f Iustin Pop
  def call_blockdev_find(self, node, disk):
826 72737a7f Iustin Pop
    """Request identification of a given block device.
827 72737a7f Iustin Pop

828 72737a7f Iustin Pop
    This is a single-node call.
829 a8083063 Iustin Pop

830 72737a7f Iustin Pop
    """
831 96acbc09 Michael Hanselmann
    result = self._SingleNodeCall(node, "blockdev_find", [disk.ToDict()])
832 edb4b374 Michael Hanselmann
    if not result.fail_msg and result.payload is not None:
833 96acbc09 Michael Hanselmann
      result.payload = objects.BlockDevStatus.FromDict(result.payload)
834 96acbc09 Michael Hanselmann
    return result
835 d61cbe76 Iustin Pop
836 b2e7666a Iustin Pop
  def call_blockdev_close(self, node, instance_name, disks):
837 72737a7f Iustin Pop
    """Closes the given block devices.
838 d61cbe76 Iustin Pop

839 72737a7f Iustin Pop
    This is a single-node call.
840 d61cbe76 Iustin Pop

841 72737a7f Iustin Pop
    """
842 b2e7666a Iustin Pop
    params = [instance_name, [cf.ToDict() for cf in disks]]
843 b2e7666a Iustin Pop
    return self._SingleNodeCall(node, "blockdev_close", params)
844 a8083063 Iustin Pop
845 968a7623 Iustin Pop
  def call_blockdev_getsizes(self, node, disks):
846 968a7623 Iustin Pop
    """Returns the size of the given disks.
847 968a7623 Iustin Pop

848 968a7623 Iustin Pop
    This is a single-node call.
849 968a7623 Iustin Pop

850 968a7623 Iustin Pop
    """
851 968a7623 Iustin Pop
    params = [[cf.ToDict() for cf in disks]]
852 968a7623 Iustin Pop
    return self._SingleNodeCall(node, "blockdev_getsize", params)
853 968a7623 Iustin Pop
854 6b93ec9d Iustin Pop
  def call_drbd_disconnect_net(self, node_list, nodes_ip, disks):
855 6b93ec9d Iustin Pop
    """Disconnects the network of the given drbd devices.
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_disconnect_net",
861 6b93ec9d Iustin Pop
                               [nodes_ip, [cf.ToDict() for cf in disks]])
862 6b93ec9d Iustin Pop
863 6b93ec9d Iustin Pop
  def call_drbd_attach_net(self, node_list, nodes_ip,
864 6b93ec9d Iustin Pop
                           disks, instance_name, multimaster):
865 6b93ec9d Iustin Pop
    """Disconnects the given drbd devices.
866 6b93ec9d Iustin Pop

867 6b93ec9d Iustin Pop
    This is a multi-node call.
868 6b93ec9d Iustin Pop

869 6b93ec9d Iustin Pop
    """
870 6b93ec9d Iustin Pop
    return self._MultiNodeCall(node_list, "drbd_attach_net",
871 6b93ec9d Iustin Pop
                               [nodes_ip, [cf.ToDict() for cf in disks],
872 6b93ec9d Iustin Pop
                                instance_name, multimaster])
873 6b93ec9d Iustin Pop
874 6b93ec9d Iustin Pop
  def call_drbd_wait_sync(self, node_list, nodes_ip, disks):
875 6b93ec9d Iustin Pop
    """Waits for the synchronization of drbd devices is complete.
876 6b93ec9d Iustin Pop

877 6b93ec9d Iustin Pop
    This is a multi-node call.
878 6b93ec9d Iustin Pop

879 6b93ec9d Iustin Pop
    """
880 6b93ec9d Iustin Pop
    return self._MultiNodeCall(node_list, "drbd_wait_sync",
881 6b93ec9d Iustin Pop
                               [nodes_ip, [cf.ToDict() for cf in disks]])
882 6b93ec9d Iustin Pop
883 9a525d83 Michael Hanselmann
  @classmethod
884 9a525d83 Michael Hanselmann
  def call_upload_file(cls, node_list, file_name, address_list=None):
885 72737a7f Iustin Pop
    """Upload a file.
886 72737a7f Iustin Pop

887 72737a7f Iustin Pop
    The node will refuse the operation in case the file is not on the
888 72737a7f Iustin Pop
    approved file list.
889 72737a7f Iustin Pop

890 72737a7f Iustin Pop
    This is a multi-node call.
891 a8083063 Iustin Pop

892 6b294c53 Iustin Pop
    @type node_list: list
893 6b294c53 Iustin Pop
    @param node_list: the list of node names to upload to
894 6b294c53 Iustin Pop
    @type file_name: str
895 6b294c53 Iustin Pop
    @param file_name: the filename to upload
896 6b294c53 Iustin Pop
    @type address_list: list or None
897 6b294c53 Iustin Pop
    @keyword address_list: an optional list of node addresses, in order
898 6b294c53 Iustin Pop
        to optimize the RPC speed
899 6b294c53 Iustin Pop

900 72737a7f Iustin Pop
    """
901 12bce260 Michael Hanselmann
    file_contents = utils.ReadFile(file_name)
902 12bce260 Michael Hanselmann
    data = cls._Compress(file_contents)
903 72737a7f Iustin Pop
    st = os.stat(file_name)
904 72737a7f Iustin Pop
    params = [file_name, data, st.st_mode, st.st_uid, st.st_gid,
905 72737a7f Iustin Pop
              st.st_atime, st.st_mtime]
906 9a525d83 Michael Hanselmann
    return cls._StaticMultiNodeCall(node_list, "upload_file", params,
907 9a525d83 Michael Hanselmann
                                    address_list=address_list)
908 72737a7f Iustin Pop
909 6ddc95ec Michael Hanselmann
  @classmethod
910 03d1dba2 Michael Hanselmann
  def call_write_ssconf_files(cls, node_list, values):
911 6ddc95ec Michael Hanselmann
    """Write ssconf files.
912 6ddc95ec Michael Hanselmann

913 6ddc95ec Michael Hanselmann
    This is a multi-node call.
914 6ddc95ec Michael Hanselmann

915 6ddc95ec Michael Hanselmann
    """
916 03d1dba2 Michael Hanselmann
    return cls._StaticMultiNodeCall(node_list, "write_ssconf_files", [values])
917 6ddc95ec Michael Hanselmann
918 72737a7f Iustin Pop
  def call_os_diagnose(self, node_list):
919 72737a7f Iustin Pop
    """Request a diagnose of OS definitions.
920 72737a7f Iustin Pop

921 72737a7f Iustin Pop
    This is a multi-node call.
922 a8083063 Iustin Pop

923 72737a7f Iustin Pop
    """
924 83d92ad8 Iustin Pop
    return self._MultiNodeCall(node_list, "os_diagnose", [])
925 a8083063 Iustin Pop
926 72737a7f Iustin Pop
  def call_os_get(self, node, name):
927 72737a7f Iustin Pop
    """Returns an OS definition.
928 a8083063 Iustin Pop

929 72737a7f Iustin Pop
    This is a single-node call.
930 a8083063 Iustin Pop

931 72737a7f Iustin Pop
    """
932 9a525d83 Michael Hanselmann
    result = self._SingleNodeCall(node, "os_get", [name])
933 84e3f66f Guido Trotter
    if not result.fail_msg and isinstance(result.payload, dict):
934 84e3f66f Guido Trotter
      result.payload = objects.OS.FromDict(result.payload)
935 781de953 Iustin Pop
    return result
936 a8083063 Iustin Pop
937 72737a7f Iustin Pop
  def call_hooks_runner(self, node_list, hpath, phase, env):
938 72737a7f Iustin Pop
    """Call the hooks runner.
939 a8083063 Iustin Pop

940 72737a7f Iustin Pop
    Args:
941 72737a7f Iustin Pop
      - op: the OpCode instance
942 72737a7f Iustin Pop
      - env: a dictionary with the environment
943 a8083063 Iustin Pop

944 72737a7f Iustin Pop
    This is a multi-node call.
945 a8083063 Iustin Pop

946 72737a7f Iustin Pop
    """
947 72737a7f Iustin Pop
    params = [hpath, phase, env]
948 9a525d83 Michael Hanselmann
    return self._MultiNodeCall(node_list, "hooks_runner", params)
949 a8083063 Iustin Pop
950 72737a7f Iustin Pop
  def call_iallocator_runner(self, node, name, idata):
951 72737a7f Iustin Pop
    """Call an iallocator on a remote node
952 8d528b7c Iustin Pop

953 72737a7f Iustin Pop
    Args:
954 72737a7f Iustin Pop
      - name: the iallocator name
955 72737a7f Iustin Pop
      - input: the json-encoded input string
956 8d528b7c Iustin Pop

957 72737a7f Iustin Pop
    This is a single-node call.
958 8d528b7c Iustin Pop

959 72737a7f Iustin Pop
    """
960 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "iallocator_runner", [name, idata])
961 8d528b7c Iustin Pop
962 72737a7f Iustin Pop
  def call_blockdev_grow(self, node, cf_bdev, amount):
963 72737a7f Iustin Pop
    """Request a snapshot of the given block device.
964 4c8ba8b3 Iustin Pop

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

967 72737a7f Iustin Pop
    """
968 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "blockdev_grow",
969 9a525d83 Michael Hanselmann
                                [cf_bdev.ToDict(), amount])
970 4c8ba8b3 Iustin Pop
971 858f3d18 Iustin Pop
  def call_blockdev_export(self, node, cf_bdev,
972 858f3d18 Iustin Pop
                           dest_node, dest_path, cluster_name):
973 858f3d18 Iustin Pop
    """Export a given disk to another node.
974 858f3d18 Iustin Pop

975 858f3d18 Iustin Pop
    This is a single-node call.
976 858f3d18 Iustin Pop

977 858f3d18 Iustin Pop
    """
978 858f3d18 Iustin Pop
    return self._SingleNodeCall(node, "blockdev_export",
979 858f3d18 Iustin Pop
                                [cf_bdev.ToDict(), dest_node, dest_path,
980 858f3d18 Iustin Pop
                                 cluster_name])
981 858f3d18 Iustin Pop
982 72737a7f Iustin Pop
  def call_blockdev_snapshot(self, node, cf_bdev):
983 72737a7f Iustin Pop
    """Request a snapshot of the given block device.
984 a8083063 Iustin Pop

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

987 72737a7f Iustin Pop
    """
988 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "blockdev_snapshot", [cf_bdev.ToDict()])
989 a8083063 Iustin Pop
990 72737a7f Iustin Pop
  def call_snapshot_export(self, node, snap_bdev, dest_node, instance,
991 74c47259 Iustin Pop
                           cluster_name, idx):
992 72737a7f Iustin Pop
    """Request the export of a given snapshot.
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, "snapshot_export",
998 9a525d83 Michael Hanselmann
                                [snap_bdev.ToDict(), dest_node,
999 9a525d83 Michael Hanselmann
                                 self._InstDict(instance), cluster_name, idx])
1000 a8083063 Iustin Pop
1001 72737a7f Iustin Pop
  def call_finalize_export(self, node, instance, snap_disks):
1002 72737a7f Iustin Pop
    """Request the completion of an export operation.
1003 a8083063 Iustin Pop

1004 72737a7f Iustin Pop
    This writes the export config file, etc.
1005 a8083063 Iustin Pop

1006 72737a7f Iustin Pop
    This is a single-node call.
1007 a8083063 Iustin Pop

1008 72737a7f Iustin Pop
    """
1009 72737a7f Iustin Pop
    flat_disks = []
1010 72737a7f Iustin Pop
    for disk in snap_disks:
1011 a97da6b7 Iustin Pop
      if isinstance(disk, bool):
1012 a97da6b7 Iustin Pop
        flat_disks.append(disk)
1013 a97da6b7 Iustin Pop
      else:
1014 a97da6b7 Iustin Pop
        flat_disks.append(disk.ToDict())
1015 9a525d83 Michael Hanselmann
1016 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "finalize_export",
1017 9a525d83 Michael Hanselmann
                                [self._InstDict(instance), flat_disks])
1018 a8083063 Iustin Pop
1019 72737a7f Iustin Pop
  def call_export_info(self, node, path):
1020 72737a7f Iustin Pop
    """Queries the export information in a given path.
1021 a8083063 Iustin Pop

1022 72737a7f Iustin Pop
    This is a single-node call.
1023 a8083063 Iustin Pop

1024 72737a7f Iustin Pop
    """
1025 3eccac06 Iustin Pop
    return self._SingleNodeCall(node, "export_info", [path])
1026 a8083063 Iustin Pop
1027 6c0af70e Guido Trotter
  def call_instance_os_import(self, node, inst, src_node, src_images,
1028 6c0af70e Guido Trotter
                              cluster_name):
1029 72737a7f Iustin Pop
    """Request the import of a backup into an instance.
1030 a8083063 Iustin Pop

1031 72737a7f Iustin Pop
    This is a single-node call.
1032 a8083063 Iustin Pop

1033 72737a7f Iustin Pop
    """
1034 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "instance_os_import",
1035 9a525d83 Michael Hanselmann
                                [self._InstDict(inst), src_node, src_images,
1036 9a525d83 Michael Hanselmann
                                 cluster_name])
1037 a8083063 Iustin Pop
1038 72737a7f Iustin Pop
  def call_export_list(self, node_list):
1039 72737a7f Iustin Pop
    """Gets the stored exports list.
1040 a8083063 Iustin Pop

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

1043 72737a7f Iustin Pop
    """
1044 9a525d83 Michael Hanselmann
    return self._MultiNodeCall(node_list, "export_list", [])
1045 a8083063 Iustin Pop
1046 72737a7f Iustin Pop
  def call_export_remove(self, node, export):
1047 72737a7f Iustin Pop
    """Requests removal of a given export.
1048 a8083063 Iustin Pop

1049 72737a7f Iustin Pop
    This is a single-node call.
1050 a8083063 Iustin Pop

1051 72737a7f Iustin Pop
    """
1052 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "export_remove", [export])
1053 a8083063 Iustin Pop
1054 9a525d83 Michael Hanselmann
  @classmethod
1055 b989b9d9 Ken Wehr
  def call_node_leave_cluster(cls, node, modify_ssh_setup):
1056 72737a7f Iustin Pop
    """Requests a node to clean the cluster information it has.
1057 a8083063 Iustin Pop

1058 72737a7f Iustin Pop
    This will remove the configuration information from the ganeti data
1059 72737a7f Iustin Pop
    dir.
1060 a8083063 Iustin Pop

1061 72737a7f Iustin Pop
    This is a single-node call.
1062 a8083063 Iustin Pop

1063 72737a7f Iustin Pop
    """
1064 b989b9d9 Ken Wehr
    return cls._StaticSingleNodeCall(node, "node_leave_cluster",
1065 b989b9d9 Ken Wehr
                                     [modify_ssh_setup])
1066 dcb93971 Michael Hanselmann
1067 72737a7f Iustin Pop
  def call_node_volumes(self, node_list):
1068 72737a7f Iustin Pop
    """Gets all volumes on node(s).
1069 dcb93971 Michael Hanselmann

1070 72737a7f Iustin Pop
    This is a multi-node call.
1071 dcb93971 Michael Hanselmann

1072 72737a7f Iustin Pop
    """
1073 9a525d83 Michael Hanselmann
    return self._MultiNodeCall(node_list, "node_volumes", [])
1074 06009e27 Iustin Pop
1075 56aa9fd5 Iustin Pop
  def call_node_demote_from_mc(self, node):
1076 56aa9fd5 Iustin Pop
    """Demote a node from the master candidate role.
1077 56aa9fd5 Iustin Pop

1078 56aa9fd5 Iustin Pop
    This is a single-node call.
1079 56aa9fd5 Iustin Pop

1080 56aa9fd5 Iustin Pop
    """
1081 56aa9fd5 Iustin Pop
    return self._SingleNodeCall(node, "node_demote_from_mc", [])
1082 56aa9fd5 Iustin Pop
1083 f5118ade Iustin Pop
1084 f5118ade Iustin Pop
  def call_node_powercycle(self, node, hypervisor):
1085 f5118ade Iustin Pop
    """Tries to powercycle a node.
1086 f5118ade Iustin Pop

1087 f5118ade Iustin Pop
    This is a single-node call.
1088 f5118ade Iustin Pop

1089 f5118ade Iustin Pop
    """
1090 f5118ade Iustin Pop
    return self._SingleNodeCall(node, "node_powercycle", [hypervisor])
1091 f5118ade Iustin Pop
1092 f5118ade Iustin Pop
1093 72737a7f Iustin Pop
  def call_test_delay(self, node_list, duration):
1094 72737a7f Iustin Pop
    """Sleep for a fixed time on given node(s).
1095 06009e27 Iustin Pop

1096 72737a7f Iustin Pop
    This is a multi-node call.
1097 06009e27 Iustin Pop

1098 72737a7f Iustin Pop
    """
1099 9a525d83 Michael Hanselmann
    return self._MultiNodeCall(node_list, "test_delay", [duration])
1100 5e04ed8b Manuel Franceschini
1101 72737a7f Iustin Pop
  def call_file_storage_dir_create(self, node, file_storage_dir):
1102 72737a7f Iustin Pop
    """Create the given file storage directory.
1103 5e04ed8b Manuel Franceschini

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

1106 72737a7f Iustin Pop
    """
1107 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "file_storage_dir_create",
1108 9a525d83 Michael Hanselmann
                                [file_storage_dir])
1109 5e04ed8b Manuel Franceschini
1110 72737a7f Iustin Pop
  def call_file_storage_dir_remove(self, node, file_storage_dir):
1111 72737a7f Iustin Pop
    """Remove the given file storage directory.
1112 5e04ed8b Manuel Franceschini

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

1115 72737a7f Iustin Pop
    """
1116 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "file_storage_dir_remove",
1117 9a525d83 Michael Hanselmann
                                [file_storage_dir])
1118 5e04ed8b Manuel Franceschini
1119 72737a7f Iustin Pop
  def call_file_storage_dir_rename(self, node, old_file_storage_dir,
1120 72737a7f Iustin Pop
                                   new_file_storage_dir):
1121 72737a7f Iustin Pop
    """Rename file storage directory.
1122 5e04ed8b Manuel Franceschini

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

1125 72737a7f Iustin Pop
    """
1126 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "file_storage_dir_rename",
1127 9a525d83 Michael Hanselmann
                                [old_file_storage_dir, new_file_storage_dir])
1128 ca52cdeb Michael Hanselmann
1129 9a525d83 Michael Hanselmann
  @classmethod
1130 9a525d83 Michael Hanselmann
  def call_jobqueue_update(cls, node_list, address_list, file_name, content):
1131 72737a7f Iustin Pop
    """Update job queue.
1132 ca52cdeb Michael Hanselmann

1133 72737a7f Iustin Pop
    This is a multi-node call.
1134 ca52cdeb Michael Hanselmann

1135 72737a7f Iustin Pop
    """
1136 9a525d83 Michael Hanselmann
    return cls._StaticMultiNodeCall(node_list, "jobqueue_update",
1137 12bce260 Michael Hanselmann
                                    [file_name, cls._Compress(content)],
1138 9a525d83 Michael Hanselmann
                                    address_list=address_list)
1139 ca52cdeb Michael Hanselmann
1140 9a525d83 Michael Hanselmann
  @classmethod
1141 9a525d83 Michael Hanselmann
  def call_jobqueue_purge(cls, node):
1142 72737a7f Iustin Pop
    """Purge job queue.
1143 ca52cdeb Michael Hanselmann

1144 72737a7f Iustin Pop
    This is a single-node call.
1145 ca52cdeb Michael Hanselmann

1146 72737a7f Iustin Pop
    """
1147 9a525d83 Michael Hanselmann
    return cls._StaticSingleNodeCall(node, "jobqueue_purge", [])
1148 af5ebcb1 Michael Hanselmann
1149 9a525d83 Michael Hanselmann
  @classmethod
1150 dd875d32 Michael Hanselmann
  def call_jobqueue_rename(cls, node_list, address_list, rename):
1151 72737a7f Iustin Pop
    """Rename a job queue file.
1152 af5ebcb1 Michael Hanselmann

1153 72737a7f Iustin Pop
    This is a multi-node call.
1154 af5ebcb1 Michael Hanselmann

1155 72737a7f Iustin Pop
    """
1156 dd875d32 Michael Hanselmann
    return cls._StaticMultiNodeCall(node_list, "jobqueue_rename", rename,
1157 9a525d83 Michael Hanselmann
                                    address_list=address_list)
1158 6217e295 Iustin Pop
1159 9a525d83 Michael Hanselmann
  @classmethod
1160 9a525d83 Michael Hanselmann
  def call_jobqueue_set_drain(cls, node_list, drain_flag):
1161 5d672980 Iustin Pop
    """Set the drain flag on the queue.
1162 5d672980 Iustin Pop

1163 5d672980 Iustin Pop
    This is a multi-node call.
1164 5d672980 Iustin Pop

1165 5d672980 Iustin Pop
    @type node_list: list
1166 5d672980 Iustin Pop
    @param node_list: the list of nodes to query
1167 5d672980 Iustin Pop
    @type drain_flag: bool
1168 5d672980 Iustin Pop
    @param drain_flag: if True, will set the drain flag, otherwise reset it.
1169 5d672980 Iustin Pop

1170 5d672980 Iustin Pop
    """
1171 9a525d83 Michael Hanselmann
    return cls._StaticMultiNodeCall(node_list, "jobqueue_set_drain",
1172 9a525d83 Michael Hanselmann
                                    [drain_flag])
1173 5d672980 Iustin Pop
1174 6217e295 Iustin Pop
  def call_hypervisor_validate_params(self, node_list, hvname, hvparams):
1175 6217e295 Iustin Pop
    """Validate the hypervisor params.
1176 6217e295 Iustin Pop

1177 6217e295 Iustin Pop
    This is a multi-node call.
1178 6217e295 Iustin Pop

1179 6217e295 Iustin Pop
    @type node_list: list
1180 6217e295 Iustin Pop
    @param node_list: the list of nodes to query
1181 6217e295 Iustin Pop
    @type hvname: string
1182 6217e295 Iustin Pop
    @param hvname: the hypervisor name
1183 6217e295 Iustin Pop
    @type hvparams: dict
1184 6217e295 Iustin Pop
    @param hvparams: the hypervisor parameters to be validated
1185 6217e295 Iustin Pop

1186 6217e295 Iustin Pop
    """
1187 6217e295 Iustin Pop
    cluster = self._cfg.GetClusterInfo()
1188 abe609b2 Guido Trotter
    hv_full = objects.FillDict(cluster.hvparams.get(hvname, {}), hvparams)
1189 9a525d83 Michael Hanselmann
    return self._MultiNodeCall(node_list, "hypervisor_validate_params",
1190 9a525d83 Michael Hanselmann
                               [hvname, hv_full])