Statistics
| Branch: | Tag: | Revision:

root / lib / rpc.py @ e4ccf6cd

History | View | Annotate | Download (34.8 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
  @type failed: boolean
87 d3c8b360 Iustin Pop
  @ivar failed: whether the operation failed at transport level (not
88 ed83f5cc Iustin Pop
      application level on the remote node)
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 781de953 Iustin Pop
    self.failed = failed
101 ed83f5cc Iustin Pop
    self.offline = offline
102 ed83f5cc Iustin Pop
    self.call = call
103 ed83f5cc Iustin Pop
    self.node = node
104 ed83f5cc Iustin Pop
    if offline:
105 ed83f5cc Iustin Pop
      self.failed = True
106 4c4e4e1e Iustin Pop
      self.fail_msg = "Node is marked offline"
107 f2def43a Iustin Pop
      self.data = self.payload = None
108 ed83f5cc Iustin Pop
    elif failed:
109 4c4e4e1e Iustin Pop
      self.fail_msg = self._EnsureErr(data)
110 f2def43a Iustin Pop
      self.data = self.payload = None
111 781de953 Iustin Pop
    else:
112 781de953 Iustin Pop
      self.data = data
113 d3c8b360 Iustin Pop
      if not isinstance(self.data, (tuple, list)):
114 fe89794e Michael Hanselmann
        self.failed = True
115 4c4e4e1e Iustin Pop
        self.fail_msg = ("RPC layer error: invalid result type (%s)" %
116 4c4e4e1e Iustin Pop
                         type(self.data))
117 d3c8b360 Iustin Pop
      elif len(data) != 2:
118 fe89794e Michael Hanselmann
        self.failed = True
119 4c4e4e1e Iustin Pop
        self.fail_msg = ("RPC layer error: invalid result length (%d), "
120 4c4e4e1e Iustin Pop
                         "expected 2" % len(self.data))
121 d3c8b360 Iustin Pop
      elif not self.data[0]:
122 fe89794e Michael Hanselmann
        self.failed = True
123 4c4e4e1e Iustin Pop
        self.fail_msg = self._EnsureErr(self.data[1])
124 f2def43a Iustin Pop
      else:
125 d3c8b360 Iustin Pop
        # finally success
126 4c4e4e1e Iustin Pop
        self.fail_msg = None
127 d3c8b360 Iustin Pop
        self.payload = data[1]
128 d3c8b360 Iustin Pop
129 d3c8b360 Iustin Pop
  @staticmethod
130 d3c8b360 Iustin Pop
  def _EnsureErr(val):
131 d3c8b360 Iustin Pop
    """Helper to ensure we return a 'True' value for error."""
132 d3c8b360 Iustin Pop
    if val:
133 d3c8b360 Iustin Pop
      return val
134 d3c8b360 Iustin Pop
    else:
135 d3c8b360 Iustin Pop
      return "No error information"
136 781de953 Iustin Pop
137 4c4e4e1e Iustin Pop
  def Raise(self, msg, prereq=False):
138 781de953 Iustin Pop
    """If the result has failed, raise an OpExecError.
139 781de953 Iustin Pop

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

143 781de953 Iustin Pop
    """
144 4c4e4e1e Iustin Pop
    if not self.fail_msg:
145 4c4e4e1e Iustin Pop
      return
146 4c4e4e1e Iustin Pop
147 4c4e4e1e Iustin Pop
    if not msg: # one could pass None for default message
148 4c4e4e1e Iustin Pop
      msg = ("Call '%s' to node '%s' has failed: %s" %
149 4c4e4e1e Iustin Pop
             (self.call, self.node, self.fail_msg))
150 4c4e4e1e Iustin Pop
    else:
151 4c4e4e1e Iustin Pop
      msg = "%s: %s" % (msg, self.fail_msg)
152 4c4e4e1e Iustin Pop
    if prereq:
153 4c4e4e1e Iustin Pop
      ec = errors.OpPrereqError
154 4c4e4e1e Iustin Pop
    else:
155 4c4e4e1e Iustin Pop
      ec = errors.OpExecError
156 4c4e4e1e Iustin Pop
    raise ec(msg)
157 781de953 Iustin Pop
158 3247bbac Iustin Pop
  def RemoteFailMsg(self):
159 3247bbac Iustin Pop
    """Check if the remote procedure failed.
160 3247bbac Iustin Pop

161 d3c8b360 Iustin Pop
    @return: the fail_msg attribute
162 3247bbac Iustin Pop

163 3247bbac Iustin Pop
    """
164 4c4e4e1e Iustin Pop
    return self.fail_msg
165 3247bbac Iustin Pop
166 781de953 Iustin Pop
167 a8083063 Iustin Pop
class Client:
168 a8083063 Iustin Pop
  """RPC Client class.
169 a8083063 Iustin Pop

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

402 12bce260 Michael Hanselmann
    Small amounts of data are not compressed.
403 12bce260 Michael Hanselmann

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

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

425 72737a7f Iustin Pop
    This is a multi-node call.
426 a8083063 Iustin Pop

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

433 72737a7f Iustin Pop
    This is a multi-node call.
434 a8083063 Iustin Pop

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

441 e337de97 Michael Hanselmann
    This is a multi-node call.
442 e337de97 Michael Hanselmann

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

450 8979196a Michael Hanselmann
    This is a single-node call.
451 8979196a Michael Hanselmann

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

459 637b8d7e Michael Hanselmann
    This is a single-node call.
460 637b8d7e Michael Hanselmann

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

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

472 72737a7f Iustin Pop
    This is a single-node call.
473 a8083063 Iustin Pop

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

480 72737a7f Iustin Pop
    This is a single-node call.
481 a8083063 Iustin Pop

482 72737a7f Iustin Pop
    """
483 0eca8e0c Iustin Pop
    idict = self._InstDict(instance, hvp=hvp, bep=bep)
484 0eca8e0c Iustin Pop
    return self._SingleNodeCall(node, "instance_start", [idict])
485 a8083063 Iustin Pop
486 72737a7f Iustin Pop
  def call_instance_shutdown(self, node, instance):
487 72737a7f Iustin Pop
    """Stops an instance.
488 a8083063 Iustin Pop

489 72737a7f Iustin Pop
    This is a single-node call.
490 2a10865c Iustin Pop

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

498 6906a9d8 Guido Trotter
    This is a single-node call.
499 6906a9d8 Guido Trotter

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

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

512 6906a9d8 Guido Trotter
    This is a single-node call.
513 6906a9d8 Guido Trotter

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

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

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

533 6906a9d8 Guido Trotter
    This is a single-node call.
534 6906a9d8 Guido Trotter

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

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

551 72737a7f Iustin Pop
    This is a single-node call.
552 2a10865c Iustin Pop

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

563 72737a7f Iustin Pop
    """
564 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "instance_migrate",
565 9a525d83 Michael Hanselmann
                                [self._InstDict(instance), target, live])
566 007a2f3e Alexander Schreiber
567 07813a9e Iustin Pop
  def call_instance_reboot(self, node, instance, reboot_type):
568 72737a7f Iustin Pop
    """Reboots an instance.
569 007a2f3e Alexander Schreiber

570 72737a7f Iustin Pop
    This is a single-node call.
571 a8083063 Iustin Pop

572 72737a7f Iustin Pop
    """
573 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "instance_reboot",
574 07813a9e Iustin Pop
                                [self._InstDict(instance), reboot_type])
575 a8083063 Iustin Pop
576 e557bae9 Guido Trotter
  def call_instance_os_add(self, node, inst, reinstall):
577 72737a7f Iustin Pop
    """Installs an OS on the given instance.
578 a8083063 Iustin Pop

579 72737a7f Iustin Pop
    This is a single-node call.
580 decd5f45 Iustin Pop

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

588 72737a7f Iustin Pop
    This is a single-node call.
589 a8083063 Iustin Pop

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

597 72737a7f Iustin Pop
    This is a single-node call.
598 a8083063 Iustin Pop

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

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

612 56e7640c Iustin Pop
    This is a single-node call.
613 56e7640c Iustin Pop

614 56e7640c Iustin Pop
    @param node: the node to query
615 56e7640c Iustin Pop
    @type instance: L{objects.Instance}
616 56e7640c Iustin Pop
    @param instance: the instance to check
617 56e7640c Iustin Pop

618 56e7640c Iustin Pop

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

626 72737a7f Iustin Pop
    This is a multi-node call.
627 a8083063 Iustin Pop

628 72737a7f Iustin Pop
    @type node_list: list
629 72737a7f Iustin Pop
    @param node_list: the list of nodes to query
630 72737a7f Iustin Pop
    @type hypervisor_list: list
631 72737a7f Iustin Pop
    @param hypervisor_list: the hypervisors to query for instances
632 a8083063 Iustin Pop

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

640 72737a7f Iustin Pop
    This is a multi-node call.
641 a8083063 Iustin Pop

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

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

654 72737a7f Iustin Pop
    This is a single-node call.
655 caad16e2 Iustin Pop

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

664 caad16e2 Iustin Pop
    This is a single-node call.
665 caad16e2 Iustin Pop

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

672 72737a7f Iustin Pop
    This will return memory information and volume group size and free
673 72737a7f Iustin Pop
    space.
674 a8083063 Iustin Pop

675 72737a7f Iustin Pop
    This is a multi-node call.
676 a8083063 Iustin Pop

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

686 72737a7f Iustin Pop
    """
687 070e998b Iustin Pop
    return self._MultiNodeCall(node_list, "node_info",
688 070e998b Iustin Pop
                               [vg_name, hypervisor_type])
689 a8083063 Iustin Pop
690 72737a7f Iustin Pop
  def call_node_add(self, node, dsa, dsapub, rsa, rsapub, ssh, sshpub):
691 72737a7f Iustin Pop
    """Add a node to the cluster.
692 a8083063 Iustin Pop

693 72737a7f Iustin Pop
    This is a single-node call.
694 a8083063 Iustin Pop

695 72737a7f Iustin Pop
    """
696 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "node_add",
697 9a525d83 Michael Hanselmann
                                [dsa, dsapub, rsa, rsapub, ssh, sshpub])
698 a8083063 Iustin Pop
699 72737a7f Iustin Pop
  def call_node_verify(self, node_list, checkdict, cluster_name):
700 72737a7f Iustin Pop
    """Request verification of given parameters.
701 a8083063 Iustin Pop

702 72737a7f Iustin Pop
    This is a multi-node call.
703 a8083063 Iustin Pop

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

712 72737a7f Iustin Pop
    This is a single-node call.
713 a8083063 Iustin Pop

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

722 72737a7f Iustin Pop
    This is a single-node call.
723 4e071d3b Iustin Pop

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

731 72737a7f Iustin Pop
    This is a multi-node call.
732 a8083063 Iustin Pop

733 72737a7f Iustin Pop
    """
734 72737a7f Iustin Pop
    # TODO: should this method query down nodes?
735 9a525d83 Michael Hanselmann
    return cls._StaticMultiNodeCall(node_list, "master_info", [])
736 a8083063 Iustin Pop
737 72737a7f Iustin Pop
  def call_version(self, node_list):
738 72737a7f Iustin Pop
    """Query node version.
739 a8083063 Iustin Pop

740 72737a7f Iustin Pop
    This is a multi-node call.
741 a8083063 Iustin Pop

742 72737a7f Iustin Pop
    """
743 9a525d83 Michael Hanselmann
    return self._MultiNodeCall(node_list, "version", [])
744 a8083063 Iustin Pop
745 72737a7f Iustin Pop
  def call_blockdev_create(self, node, bdev, size, owner, on_primary, info):
746 72737a7f Iustin Pop
    """Request creation of a given block device.
747 a8083063 Iustin Pop

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

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

757 72737a7f Iustin Pop
    This is a single-node call.
758 f3e513ad Iustin Pop

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

765 72737a7f Iustin Pop
    This is a single-node call.
766 a8083063 Iustin Pop

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

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

776 72737a7f Iustin Pop
    """
777 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "blockdev_assemble",
778 9a525d83 Michael Hanselmann
                                [disk.ToDict(), owner, on_primary])
779 a8083063 Iustin Pop
780 72737a7f Iustin Pop
  def call_blockdev_shutdown(self, node, disk):
781 72737a7f Iustin Pop
    """Request shutdown of a given block device.
782 a8083063 Iustin Pop

783 72737a7f Iustin Pop
    This is a single-node call.
784 a8083063 Iustin Pop

785 72737a7f Iustin Pop
    """
786 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "blockdev_shutdown", [disk.ToDict()])
787 a8083063 Iustin Pop
788 72737a7f Iustin Pop
  def call_blockdev_addchildren(self, node, bdev, ndevs):
789 72737a7f Iustin Pop
    """Request adding a list of children to a (mirroring) device.
790 a8083063 Iustin Pop

791 72737a7f Iustin Pop
    This is a single-node call.
792 a8083063 Iustin Pop

793 72737a7f Iustin Pop
    """
794 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "blockdev_addchildren",
795 9a525d83 Michael Hanselmann
                                [bdev.ToDict(),
796 9a525d83 Michael Hanselmann
                                 [disk.ToDict() for disk in ndevs]])
797 a8083063 Iustin Pop
798 72737a7f Iustin Pop
  def call_blockdev_removechildren(self, node, bdev, ndevs):
799 72737a7f Iustin Pop
    """Request removing a list of children from a (mirroring) device.
800 a8083063 Iustin Pop

801 72737a7f Iustin Pop
    This is a single-node call.
802 a8083063 Iustin Pop

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

811 72737a7f Iustin Pop
    This is a single-node call.
812 a8083063 Iustin Pop

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

824 72737a7f Iustin Pop
    This is a single-node call.
825 a8083063 Iustin Pop

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

835 72737a7f Iustin Pop
    This is a single-node call.
836 d61cbe76 Iustin Pop

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

844 968a7623 Iustin Pop
    This is a single-node call.
845 968a7623 Iustin Pop

846 968a7623 Iustin Pop
    """
847 968a7623 Iustin Pop
    params = [[cf.ToDict() for cf in disks]]
848 968a7623 Iustin Pop
    return self._SingleNodeCall(node, "blockdev_getsize", params)
849 968a7623 Iustin Pop
850 6b93ec9d Iustin Pop
  def call_drbd_disconnect_net(self, node_list, nodes_ip, disks):
851 6b93ec9d Iustin Pop
    """Disconnects the network of the given drbd devices.
852 6b93ec9d Iustin Pop

853 6b93ec9d Iustin Pop
    This is a multi-node call.
854 6b93ec9d Iustin Pop

855 6b93ec9d Iustin Pop
    """
856 6b93ec9d Iustin Pop
    return self._MultiNodeCall(node_list, "drbd_disconnect_net",
857 6b93ec9d Iustin Pop
                               [nodes_ip, [cf.ToDict() for cf in disks]])
858 6b93ec9d Iustin Pop
859 6b93ec9d Iustin Pop
  def call_drbd_attach_net(self, node_list, nodes_ip,
860 6b93ec9d Iustin Pop
                           disks, instance_name, multimaster):
861 6b93ec9d Iustin Pop
    """Disconnects the given drbd devices.
862 6b93ec9d Iustin Pop

863 6b93ec9d Iustin Pop
    This is a multi-node call.
864 6b93ec9d Iustin Pop

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

873 6b93ec9d Iustin Pop
    This is a multi-node call.
874 6b93ec9d Iustin Pop

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

883 72737a7f Iustin Pop
    The node will refuse the operation in case the file is not on the
884 72737a7f Iustin Pop
    approved file list.
885 72737a7f Iustin Pop

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

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

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

909 6ddc95ec Michael Hanselmann
    This is a multi-node call.
910 6ddc95ec Michael Hanselmann

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

917 72737a7f Iustin Pop
    This is a multi-node call.
918 a8083063 Iustin Pop

919 72737a7f Iustin Pop
    """
920 83d92ad8 Iustin Pop
    return self._MultiNodeCall(node_list, "os_diagnose", [])
921 a8083063 Iustin Pop
922 72737a7f Iustin Pop
  def call_os_get(self, node, name):
923 72737a7f Iustin Pop
    """Returns an OS definition.
924 a8083063 Iustin Pop

925 72737a7f Iustin Pop
    This is a single-node call.
926 a8083063 Iustin Pop

927 72737a7f Iustin Pop
    """
928 9a525d83 Michael Hanselmann
    result = self._SingleNodeCall(node, "os_get", [name])
929 781de953 Iustin Pop
    if not result.failed and isinstance(result.data, dict):
930 781de953 Iustin Pop
      result.data = objects.OS.FromDict(result.data)
931 781de953 Iustin Pop
    return result
932 a8083063 Iustin Pop
933 72737a7f Iustin Pop
  def call_hooks_runner(self, node_list, hpath, phase, env):
934 72737a7f Iustin Pop
    """Call the hooks runner.
935 a8083063 Iustin Pop

936 72737a7f Iustin Pop
    Args:
937 72737a7f Iustin Pop
      - op: the OpCode instance
938 72737a7f Iustin Pop
      - env: a dictionary with the environment
939 a8083063 Iustin Pop

940 72737a7f Iustin Pop
    This is a multi-node call.
941 a8083063 Iustin Pop

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

949 72737a7f Iustin Pop
    Args:
950 72737a7f Iustin Pop
      - name: the iallocator name
951 72737a7f Iustin Pop
      - input: the json-encoded input string
952 8d528b7c Iustin Pop

953 72737a7f Iustin Pop
    This is a single-node call.
954 8d528b7c Iustin Pop

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

961 72737a7f Iustin Pop
    This is a single-node call.
962 4c8ba8b3 Iustin Pop

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

971 858f3d18 Iustin Pop
    This is a single-node call.
972 858f3d18 Iustin Pop

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

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

983 72737a7f Iustin Pop
    """
984 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "blockdev_snapshot", [cf_bdev.ToDict()])
985 a8083063 Iustin Pop
986 72737a7f Iustin Pop
  def call_snapshot_export(self, node, snap_bdev, dest_node, instance,
987 74c47259 Iustin Pop
                           cluster_name, idx):
988 72737a7f Iustin Pop
    """Request the export of a given snapshot.
989 a8083063 Iustin Pop

990 72737a7f Iustin Pop
    This is a single-node call.
991 a8083063 Iustin Pop

992 72737a7f Iustin Pop
    """
993 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "snapshot_export",
994 9a525d83 Michael Hanselmann
                                [snap_bdev.ToDict(), dest_node,
995 9a525d83 Michael Hanselmann
                                 self._InstDict(instance), cluster_name, idx])
996 a8083063 Iustin Pop
997 72737a7f Iustin Pop
  def call_finalize_export(self, node, instance, snap_disks):
998 72737a7f Iustin Pop
    """Request the completion of an export operation.
999 a8083063 Iustin Pop

1000 72737a7f Iustin Pop
    This writes the export config file, etc.
1001 a8083063 Iustin Pop

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

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

1018 72737a7f Iustin Pop
    This is a single-node call.
1019 a8083063 Iustin Pop

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

1027 72737a7f Iustin Pop
    This is a single-node call.
1028 a8083063 Iustin Pop

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

1037 72737a7f Iustin Pop
    This is a multi-node call.
1038 a8083063 Iustin Pop

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

1045 72737a7f Iustin Pop
    This is a single-node call.
1046 a8083063 Iustin Pop

1047 72737a7f Iustin Pop
    """
1048 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "export_remove", [export])
1049 a8083063 Iustin Pop
1050 9a525d83 Michael Hanselmann
  @classmethod
1051 9a525d83 Michael Hanselmann
  def call_node_leave_cluster(cls, node):
1052 72737a7f Iustin Pop
    """Requests a node to clean the cluster information it has.
1053 a8083063 Iustin Pop

1054 72737a7f Iustin Pop
    This will remove the configuration information from the ganeti data
1055 72737a7f Iustin Pop
    dir.
1056 a8083063 Iustin Pop

1057 72737a7f Iustin Pop
    This is a single-node call.
1058 a8083063 Iustin Pop

1059 72737a7f Iustin Pop
    """
1060 9a525d83 Michael Hanselmann
    return cls._StaticSingleNodeCall(node, "node_leave_cluster", [])
1061 dcb93971 Michael Hanselmann
1062 72737a7f Iustin Pop
  def call_node_volumes(self, node_list):
1063 72737a7f Iustin Pop
    """Gets all volumes on node(s).
1064 dcb93971 Michael Hanselmann

1065 72737a7f Iustin Pop
    This is a multi-node call.
1066 dcb93971 Michael Hanselmann

1067 72737a7f Iustin Pop
    """
1068 9a525d83 Michael Hanselmann
    return self._MultiNodeCall(node_list, "node_volumes", [])
1069 06009e27 Iustin Pop
1070 56aa9fd5 Iustin Pop
  def call_node_demote_from_mc(self, node):
1071 56aa9fd5 Iustin Pop
    """Demote a node from the master candidate role.
1072 56aa9fd5 Iustin Pop

1073 56aa9fd5 Iustin Pop
    This is a single-node call.
1074 56aa9fd5 Iustin Pop

1075 56aa9fd5 Iustin Pop
    """
1076 56aa9fd5 Iustin Pop
    return self._SingleNodeCall(node, "node_demote_from_mc", [])
1077 56aa9fd5 Iustin Pop
1078 f5118ade Iustin Pop
1079 f5118ade Iustin Pop
  def call_node_powercycle(self, node, hypervisor):
1080 f5118ade Iustin Pop
    """Tries to powercycle a node.
1081 f5118ade Iustin Pop

1082 f5118ade Iustin Pop
    This is a single-node call.
1083 f5118ade Iustin Pop

1084 f5118ade Iustin Pop
    """
1085 f5118ade Iustin Pop
    return self._SingleNodeCall(node, "node_powercycle", [hypervisor])
1086 f5118ade Iustin Pop
1087 f5118ade Iustin Pop
1088 72737a7f Iustin Pop
  def call_test_delay(self, node_list, duration):
1089 72737a7f Iustin Pop
    """Sleep for a fixed time on given node(s).
1090 06009e27 Iustin Pop

1091 72737a7f Iustin Pop
    This is a multi-node call.
1092 06009e27 Iustin Pop

1093 72737a7f Iustin Pop
    """
1094 9a525d83 Michael Hanselmann
    return self._MultiNodeCall(node_list, "test_delay", [duration])
1095 5e04ed8b Manuel Franceschini
1096 72737a7f Iustin Pop
  def call_file_storage_dir_create(self, node, file_storage_dir):
1097 72737a7f Iustin Pop
    """Create the given file storage directory.
1098 5e04ed8b Manuel Franceschini

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

1101 72737a7f Iustin Pop
    """
1102 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "file_storage_dir_create",
1103 9a525d83 Michael Hanselmann
                                [file_storage_dir])
1104 5e04ed8b Manuel Franceschini
1105 72737a7f Iustin Pop
  def call_file_storage_dir_remove(self, node, file_storage_dir):
1106 72737a7f Iustin Pop
    """Remove the given file storage directory.
1107 5e04ed8b Manuel Franceschini

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

1110 72737a7f Iustin Pop
    """
1111 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "file_storage_dir_remove",
1112 9a525d83 Michael Hanselmann
                                [file_storage_dir])
1113 5e04ed8b Manuel Franceschini
1114 72737a7f Iustin Pop
  def call_file_storage_dir_rename(self, node, old_file_storage_dir,
1115 72737a7f Iustin Pop
                                   new_file_storage_dir):
1116 72737a7f Iustin Pop
    """Rename file storage directory.
1117 5e04ed8b Manuel Franceschini

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

1120 72737a7f Iustin Pop
    """
1121 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "file_storage_dir_rename",
1122 9a525d83 Michael Hanselmann
                                [old_file_storage_dir, new_file_storage_dir])
1123 ca52cdeb Michael Hanselmann
1124 9a525d83 Michael Hanselmann
  @classmethod
1125 9a525d83 Michael Hanselmann
  def call_jobqueue_update(cls, node_list, address_list, file_name, content):
1126 72737a7f Iustin Pop
    """Update job queue.
1127 ca52cdeb Michael Hanselmann

1128 72737a7f Iustin Pop
    This is a multi-node call.
1129 ca52cdeb Michael Hanselmann

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

1139 72737a7f Iustin Pop
    This is a single-node call.
1140 ca52cdeb Michael Hanselmann

1141 72737a7f Iustin Pop
    """
1142 9a525d83 Michael Hanselmann
    return cls._StaticSingleNodeCall(node, "jobqueue_purge", [])
1143 af5ebcb1 Michael Hanselmann
1144 9a525d83 Michael Hanselmann
  @classmethod
1145 dd875d32 Michael Hanselmann
  def call_jobqueue_rename(cls, node_list, address_list, rename):
1146 72737a7f Iustin Pop
    """Rename a job queue file.
1147 af5ebcb1 Michael Hanselmann

1148 72737a7f Iustin Pop
    This is a multi-node call.
1149 af5ebcb1 Michael Hanselmann

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

1158 5d672980 Iustin Pop
    This is a multi-node call.
1159 5d672980 Iustin Pop

1160 5d672980 Iustin Pop
    @type node_list: list
1161 5d672980 Iustin Pop
    @param node_list: the list of nodes to query
1162 5d672980 Iustin Pop
    @type drain_flag: bool
1163 5d672980 Iustin Pop
    @param drain_flag: if True, will set the drain flag, otherwise reset it.
1164 5d672980 Iustin Pop

1165 5d672980 Iustin Pop
    """
1166 9a525d83 Michael Hanselmann
    return cls._StaticMultiNodeCall(node_list, "jobqueue_set_drain",
1167 9a525d83 Michael Hanselmann
                                    [drain_flag])
1168 5d672980 Iustin Pop
1169 6217e295 Iustin Pop
  def call_hypervisor_validate_params(self, node_list, hvname, hvparams):
1170 6217e295 Iustin Pop
    """Validate the hypervisor params.
1171 6217e295 Iustin Pop

1172 6217e295 Iustin Pop
    This is a multi-node call.
1173 6217e295 Iustin Pop

1174 6217e295 Iustin Pop
    @type node_list: list
1175 6217e295 Iustin Pop
    @param node_list: the list of nodes to query
1176 6217e295 Iustin Pop
    @type hvname: string
1177 6217e295 Iustin Pop
    @param hvname: the hypervisor name
1178 6217e295 Iustin Pop
    @type hvparams: dict
1179 6217e295 Iustin Pop
    @param hvparams: the hypervisor parameters to be validated
1180 6217e295 Iustin Pop

1181 6217e295 Iustin Pop
    """
1182 6217e295 Iustin Pop
    cluster = self._cfg.GetClusterInfo()
1183 abe609b2 Guido Trotter
    hv_full = objects.FillDict(cluster.hvparams.get(hvname, {}), hvparams)
1184 9a525d83 Michael Hanselmann
    return self._MultiNodeCall(node_list, "hypervisor_validate_params",
1185 9a525d83 Michael Hanselmann
                               [hvname, hv_full])