Statistics
| Branch: | Tag: | Revision:

root / lib / rpc.py @ 936f3c59

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
  @ivar call: the name of the RPC call
87 ed83f5cc Iustin Pop
  @ivar node: the name of the node to which we made the call
88 ed83f5cc Iustin Pop
  @ivar offline: whether the operation failed because the node was
89 ed83f5cc Iustin Pop
      offline, as opposed to actual failure; offline=True will always
90 ed83f5cc Iustin Pop
      imply failed=True, in order to allow simpler checking if
91 ed83f5cc Iustin Pop
      the user doesn't care about the exact failure mode
92 4c4e4e1e Iustin Pop
  @ivar fail_msg: the error message if the call failed
93 ed83f5cc Iustin Pop

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

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

146 781de953 Iustin Pop
    """
147 4c4e4e1e Iustin Pop
    if not self.fail_msg:
148 4c4e4e1e Iustin Pop
      return
149 4c4e4e1e Iustin Pop
150 4c4e4e1e Iustin Pop
    if not msg: # one could pass None for default message
151 4c4e4e1e Iustin Pop
      msg = ("Call '%s' to node '%s' has failed: %s" %
152 4c4e4e1e Iustin Pop
             (self.call, self.node, self.fail_msg))
153 4c4e4e1e Iustin Pop
    else:
154 4c4e4e1e Iustin Pop
      msg = "%s: %s" % (msg, self.fail_msg)
155 4c4e4e1e Iustin Pop
    if prereq:
156 4c4e4e1e Iustin Pop
      ec = errors.OpPrereqError
157 4c4e4e1e Iustin Pop
    else:
158 4c4e4e1e Iustin Pop
      ec = errors.OpExecError
159 4c4e4e1e Iustin Pop
    raise ec(msg)
160 781de953 Iustin Pop
161 781de953 Iustin Pop
162 a8083063 Iustin Pop
class Client:
163 a8083063 Iustin Pop
  """RPC Client class.
164 a8083063 Iustin Pop

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

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

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

187 3ef3c771 Iustin Pop
    @type node_list: list
188 3ef3c771 Iustin Pop
    @param node_list: the list of node names to connect
189 bdf7d8c0 Iustin Pop
    @type address_list: list or None
190 bdf7d8c0 Iustin Pop
    @keyword address_list: either None or a list with node addresses,
191 bdf7d8c0 Iustin Pop
        which must have the same length as the node list
192 3ef3c771 Iustin Pop

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

205 bdf7d8c0 Iustin Pop
    @type name: str
206 bdf7d8c0 Iustin Pop
    @param name: the node name
207 bdf7d8c0 Iustin Pop
    @type address: str
208 bdf7d8c0 Iustin Pop
    @keyword address: the node address, if known
209 bdf7d8c0 Iustin Pop

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

224 ecfe9491 Michael Hanselmann
    @rtype: list
225 5fcc718f Iustin Pop
    @return: List of RPC results
226 a8083063 Iustin Pop

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

260 72737a7f Iustin Pop
    @type cfg:  C{config.ConfigWriter}
261 72737a7f Iustin Pop
    @param cfg: the configuration object that will be used to get data
262 72737a7f Iustin Pop
                about the cluster
263 a8083063 Iustin Pop

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

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

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

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

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

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

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

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

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

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

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

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

397 12bce260 Michael Hanselmann
    Small amounts of data are not compressed.
398 12bce260 Michael Hanselmann

399 12bce260 Michael Hanselmann
    @type data: str
400 12bce260 Michael Hanselmann
    @param data: Data
401 12bce260 Michael Hanselmann
    @rtype: tuple
402 12bce260 Michael Hanselmann
    @return: Encoded data to send
403 12bce260 Michael Hanselmann

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

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

422 72737a7f Iustin Pop
    """
423 b2a6ccd4 Iustin Pop
    return self._MultiNodeCall(node_list, "lv_list", [vg_name])
424 a8083063 Iustin Pop
425 72737a7f Iustin Pop
  def call_vg_list(self, node_list):
426 72737a7f Iustin Pop
    """Gets the volume group list.
427 a8083063 Iustin Pop

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

430 72737a7f Iustin Pop
    """
431 9a525d83 Michael Hanselmann
    return self._MultiNodeCall(node_list, "vg_list", [])
432 a8083063 Iustin Pop
433 e337de97 Michael Hanselmann
  def call_storage_list(self, node_list, su_name, su_args, name, fields):
434 8979196a Michael Hanselmann
    """Get list of storage units.
435 e337de97 Michael Hanselmann

436 e337de97 Michael Hanselmann
    This is a multi-node call.
437 e337de97 Michael Hanselmann

438 e337de97 Michael Hanselmann
    """
439 e337de97 Michael Hanselmann
    return self._MultiNodeCall(node_list, "storage_list",
440 e337de97 Michael Hanselmann
                               [su_name, su_args, name, fields])
441 e337de97 Michael Hanselmann
442 8979196a Michael Hanselmann
  def call_storage_modify(self, node, su_name, su_args, name, changes):
443 8979196a Michael Hanselmann
    """Modify a storage unit.
444 8979196a Michael Hanselmann

445 8979196a Michael Hanselmann
    This is a single-node call.
446 8979196a Michael Hanselmann

447 8979196a Michael Hanselmann
    """
448 8979196a Michael Hanselmann
    return self._SingleNodeCall(node, "storage_modify",
449 8979196a Michael Hanselmann
                                [su_name, su_args, name, changes])
450 8979196a Michael Hanselmann
451 637b8d7e Michael Hanselmann
  def call_storage_execute(self, node, su_name, su_args, name, op):
452 637b8d7e Michael Hanselmann
    """Executes an operation on a storage unit.
453 637b8d7e Michael Hanselmann

454 637b8d7e Michael Hanselmann
    This is a single-node call.
455 637b8d7e Michael Hanselmann

456 637b8d7e Michael Hanselmann
    """
457 637b8d7e Michael Hanselmann
    return self._SingleNodeCall(node, "storage_execute",
458 637b8d7e Michael Hanselmann
                                [su_name, su_args, name, op])
459 637b8d7e Michael Hanselmann
460 72737a7f Iustin Pop
  def call_bridges_exist(self, node, bridges_list):
461 72737a7f Iustin Pop
    """Checks if a node has all the bridges given.
462 a8083063 Iustin Pop

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

467 72737a7f Iustin Pop
    This is a single-node call.
468 a8083063 Iustin Pop

469 72737a7f Iustin Pop
    """
470 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "bridges_exist", [bridges_list])
471 a8083063 Iustin Pop
472 0eca8e0c Iustin Pop
  def call_instance_start(self, node, instance, hvp, bep):
473 72737a7f Iustin Pop
    """Starts an instance.
474 a8083063 Iustin Pop

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

477 72737a7f Iustin Pop
    """
478 0eca8e0c Iustin Pop
    idict = self._InstDict(instance, hvp=hvp, bep=bep)
479 0eca8e0c Iustin Pop
    return self._SingleNodeCall(node, "instance_start", [idict])
480 a8083063 Iustin Pop
481 6263189c Guido Trotter
  def call_instance_shutdown(self, node, instance, timeout):
482 72737a7f Iustin Pop
    """Stops an instance.
483 a8083063 Iustin Pop

484 72737a7f Iustin Pop
    This is a single-node call.
485 2a10865c Iustin Pop

486 72737a7f Iustin Pop
    """
487 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "instance_shutdown",
488 6263189c Guido Trotter
                                [self._InstDict(instance), timeout])
489 2a10865c Iustin Pop
490 6906a9d8 Guido Trotter
  def call_migration_info(self, node, instance):
491 6906a9d8 Guido Trotter
    """Gather the information necessary to prepare an instance migration.
492 6906a9d8 Guido Trotter

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

495 6906a9d8 Guido Trotter
    @type node: string
496 6906a9d8 Guido Trotter
    @param node: the node on which the instance is currently running
497 6906a9d8 Guido Trotter
    @type instance: C{objects.Instance}
498 6906a9d8 Guido Trotter
    @param instance: the instance definition
499 6906a9d8 Guido Trotter

500 6906a9d8 Guido Trotter
    """
501 6906a9d8 Guido Trotter
    return self._SingleNodeCall(node, "migration_info",
502 6906a9d8 Guido Trotter
                                [self._InstDict(instance)])
503 6906a9d8 Guido Trotter
504 6906a9d8 Guido Trotter
  def call_accept_instance(self, node, instance, info, target):
505 6906a9d8 Guido Trotter
    """Prepare a node to accept an instance.
506 6906a9d8 Guido Trotter

507 6906a9d8 Guido Trotter
    This is a single-node call.
508 6906a9d8 Guido Trotter

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

518 6906a9d8 Guido Trotter
    """
519 6906a9d8 Guido Trotter
    return self._SingleNodeCall(node, "accept_instance",
520 6906a9d8 Guido Trotter
                                [self._InstDict(instance), info, target])
521 6906a9d8 Guido Trotter
522 6906a9d8 Guido Trotter
  def call_finalize_migration(self, node, instance, info, success):
523 6906a9d8 Guido Trotter
    """Finalize any target-node migration specific operation.
524 6906a9d8 Guido Trotter

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

528 6906a9d8 Guido Trotter
    This is a single-node call.
529 6906a9d8 Guido Trotter

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

539 6906a9d8 Guido Trotter
    """
540 6906a9d8 Guido Trotter
    return self._SingleNodeCall(node, "finalize_migration",
541 6906a9d8 Guido Trotter
                                [self._InstDict(instance), info, success])
542 6906a9d8 Guido Trotter
543 72737a7f Iustin Pop
  def call_instance_migrate(self, node, instance, target, live):
544 72737a7f Iustin Pop
    """Migrate an instance.
545 2a10865c Iustin Pop

546 72737a7f Iustin Pop
    This is a single-node call.
547 2a10865c Iustin Pop

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

558 72737a7f Iustin Pop
    """
559 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "instance_migrate",
560 9a525d83 Michael Hanselmann
                                [self._InstDict(instance), target, live])
561 007a2f3e Alexander Schreiber
562 17c3f802 Guido Trotter
  def call_instance_reboot(self, node, inst, reboot_type, shutdown_timeout):
563 72737a7f Iustin Pop
    """Reboots an instance.
564 007a2f3e Alexander Schreiber

565 72737a7f Iustin Pop
    This is a single-node call.
566 a8083063 Iustin Pop

567 72737a7f Iustin Pop
    """
568 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "instance_reboot",
569 17c3f802 Guido Trotter
                                [self._InstDict(inst), reboot_type,
570 17c3f802 Guido Trotter
                                 shutdown_timeout])
571 a8083063 Iustin Pop
572 e557bae9 Guido Trotter
  def call_instance_os_add(self, node, inst, reinstall):
573 72737a7f Iustin Pop
    """Installs an OS on the given instance.
574 a8083063 Iustin Pop

575 72737a7f Iustin Pop
    This is a single-node call.
576 decd5f45 Iustin Pop

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

584 72737a7f Iustin Pop
    This is a single-node call.
585 a8083063 Iustin Pop

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

593 72737a7f Iustin Pop
    This is a single-node call.
594 a8083063 Iustin Pop

595 9a525d83 Michael Hanselmann
    @type node: list
596 9a525d83 Michael Hanselmann
    @param node: the list of nodes to query
597 72737a7f Iustin Pop
    @type instance: string
598 72737a7f Iustin Pop
    @param instance: the instance name
599 72737a7f Iustin Pop
    @type hname: string
600 72737a7f Iustin Pop
    @param hname: the hypervisor type of the instance
601 a8083063 Iustin Pop

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

608 56e7640c Iustin Pop
    This is a single-node call.
609 56e7640c Iustin Pop

610 56e7640c Iustin Pop
    @param node: the node to query
611 56e7640c Iustin Pop
    @type instance: L{objects.Instance}
612 56e7640c Iustin Pop
    @param instance: the instance to check
613 56e7640c Iustin Pop

614 56e7640c Iustin Pop

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

622 72737a7f Iustin Pop
    This is a multi-node call.
623 a8083063 Iustin Pop

624 72737a7f Iustin Pop
    @type node_list: list
625 72737a7f Iustin Pop
    @param node_list: the list of nodes to query
626 72737a7f Iustin Pop
    @type hypervisor_list: list
627 72737a7f Iustin Pop
    @param hypervisor_list: the hypervisors to query for instances
628 a8083063 Iustin Pop

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

636 72737a7f Iustin Pop
    This is a multi-node call.
637 a8083063 Iustin Pop

638 72737a7f Iustin Pop
    @type node_list: list
639 72737a7f Iustin Pop
    @param node_list: the list of nodes to query
640 72737a7f Iustin Pop
    @type hypervisor_list: list
641 72737a7f Iustin Pop
    @param hypervisor_list: the hypervisors to query for instances
642 16abfbc2 Alexander Schreiber

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

650 72737a7f Iustin Pop
    This is a single-node call.
651 caad16e2 Iustin Pop

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

660 caad16e2 Iustin Pop
    This is a single-node call.
661 caad16e2 Iustin Pop

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

668 72737a7f Iustin Pop
    This will return memory information and volume group size and free
669 72737a7f Iustin Pop
    space.
670 a8083063 Iustin Pop

671 72737a7f Iustin Pop
    This is a multi-node call.
672 a8083063 Iustin Pop

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

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

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

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

698 72737a7f Iustin Pop
    This is a multi-node call.
699 a8083063 Iustin Pop

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

708 72737a7f Iustin Pop
    This is a single-node call.
709 a8083063 Iustin Pop

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

718 72737a7f Iustin Pop
    This is a single-node call.
719 4e071d3b Iustin Pop

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

727 72737a7f Iustin Pop
    This is a multi-node call.
728 a8083063 Iustin Pop

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

736 72737a7f Iustin Pop
    This is a multi-node call.
737 a8083063 Iustin Pop

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

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

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

753 72737a7f Iustin Pop
    This is a single-node call.
754 f3e513ad Iustin Pop

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

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

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

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

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

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

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

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

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

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

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

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

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

820 72737a7f Iustin Pop
    This is a single-node call.
821 a8083063 Iustin Pop

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

831 72737a7f Iustin Pop
    This is a single-node call.
832 d61cbe76 Iustin Pop

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

840 968a7623 Iustin Pop
    This is a single-node call.
841 968a7623 Iustin Pop

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

849 6b93ec9d Iustin Pop
    This is a multi-node call.
850 6b93ec9d Iustin Pop

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

859 6b93ec9d Iustin Pop
    This is a multi-node call.
860 6b93ec9d Iustin Pop

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

869 6b93ec9d Iustin Pop
    This is a multi-node call.
870 6b93ec9d Iustin Pop

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

879 72737a7f Iustin Pop
    The node will refuse the operation in case the file is not on the
880 72737a7f Iustin Pop
    approved file list.
881 72737a7f Iustin Pop

882 72737a7f Iustin Pop
    This is a multi-node call.
883 a8083063 Iustin Pop

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

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

905 6ddc95ec Michael Hanselmann
    This is a multi-node call.
906 6ddc95ec Michael Hanselmann

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

913 72737a7f Iustin Pop
    This is a multi-node call.
914 a8083063 Iustin Pop

915 72737a7f Iustin Pop
    """
916 83d92ad8 Iustin Pop
    return self._MultiNodeCall(node_list, "os_diagnose", [])
917 a8083063 Iustin Pop
918 72737a7f Iustin Pop
  def call_os_get(self, node, name):
919 72737a7f Iustin Pop
    """Returns an OS definition.
920 a8083063 Iustin Pop

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

923 72737a7f Iustin Pop
    """
924 9a525d83 Michael Hanselmann
    result = self._SingleNodeCall(node, "os_get", [name])
925 84e3f66f Guido Trotter
    if not result.fail_msg and isinstance(result.payload, dict):
926 84e3f66f Guido Trotter
      result.payload = objects.OS.FromDict(result.payload)
927 781de953 Iustin Pop
    return result
928 a8083063 Iustin Pop
929 72737a7f Iustin Pop
  def call_hooks_runner(self, node_list, hpath, phase, env):
930 72737a7f Iustin Pop
    """Call the hooks runner.
931 a8083063 Iustin Pop

932 72737a7f Iustin Pop
    Args:
933 72737a7f Iustin Pop
      - op: the OpCode instance
934 72737a7f Iustin Pop
      - env: a dictionary with the environment
935 a8083063 Iustin Pop

936 72737a7f Iustin Pop
    This is a multi-node call.
937 a8083063 Iustin Pop

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

945 72737a7f Iustin Pop
    Args:
946 72737a7f Iustin Pop
      - name: the iallocator name
947 72737a7f Iustin Pop
      - input: the json-encoded input string
948 8d528b7c Iustin Pop

949 72737a7f Iustin Pop
    This is a single-node call.
950 8d528b7c Iustin Pop

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

957 72737a7f Iustin Pop
    This is a single-node call.
958 4c8ba8b3 Iustin Pop

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

967 858f3d18 Iustin Pop
    This is a single-node call.
968 858f3d18 Iustin Pop

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

977 72737a7f Iustin Pop
    This is a single-node call.
978 a8083063 Iustin Pop

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

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

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

996 72737a7f Iustin Pop
    This writes the export config file, etc.
997 a8083063 Iustin Pop

998 72737a7f Iustin Pop
    This is a single-node call.
999 a8083063 Iustin Pop

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

1014 72737a7f Iustin Pop
    This is a single-node call.
1015 a8083063 Iustin Pop

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

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

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

1033 72737a7f Iustin Pop
    This is a multi-node call.
1034 a8083063 Iustin Pop

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

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

1043 72737a7f Iustin Pop
    """
1044 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "export_remove", [export])
1045 a8083063 Iustin Pop
1046 9a525d83 Michael Hanselmann
  @classmethod
1047 b989b9d9 Ken Wehr
  def call_node_leave_cluster(cls, node, modify_ssh_setup):
1048 72737a7f Iustin Pop
    """Requests a node to clean the cluster information it has.
1049 a8083063 Iustin Pop

1050 72737a7f Iustin Pop
    This will remove the configuration information from the ganeti data
1051 72737a7f Iustin Pop
    dir.
1052 a8083063 Iustin Pop

1053 72737a7f Iustin Pop
    This is a single-node call.
1054 a8083063 Iustin Pop

1055 72737a7f Iustin Pop
    """
1056 b989b9d9 Ken Wehr
    return cls._StaticSingleNodeCall(node, "node_leave_cluster",
1057 b989b9d9 Ken Wehr
                                     [modify_ssh_setup])
1058 dcb93971 Michael Hanselmann
1059 72737a7f Iustin Pop
  def call_node_volumes(self, node_list):
1060 72737a7f Iustin Pop
    """Gets all volumes on node(s).
1061 dcb93971 Michael Hanselmann

1062 72737a7f Iustin Pop
    This is a multi-node call.
1063 dcb93971 Michael Hanselmann

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

1070 56aa9fd5 Iustin Pop
    This is a single-node call.
1071 56aa9fd5 Iustin Pop

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

1079 f5118ade Iustin Pop
    This is a single-node call.
1080 f5118ade Iustin Pop

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

1088 72737a7f Iustin Pop
    This is a multi-node call.
1089 06009e27 Iustin Pop

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

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

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

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

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

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

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

1125 72737a7f Iustin Pop
    This is a multi-node call.
1126 ca52cdeb Michael Hanselmann

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

1136 72737a7f Iustin Pop
    This is a single-node call.
1137 ca52cdeb Michael Hanselmann

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

1145 72737a7f Iustin Pop
    This is a multi-node call.
1146 af5ebcb1 Michael Hanselmann

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

1155 5d672980 Iustin Pop
    This is a multi-node call.
1156 5d672980 Iustin Pop

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

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

1169 6217e295 Iustin Pop
    This is a multi-node call.
1170 6217e295 Iustin Pop

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

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