Statistics
| Branch: | Tag: | Revision:

root / lib / rpc.py @ 728489a3

History | View | Annotate | Download (35.2 kB)

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

574 72737a7f Iustin Pop
    """
575 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "instance_reboot",
576 17c3f802 Guido Trotter
                                [self._InstDict(inst), reboot_type,
577 17c3f802 Guido Trotter
                                 shutdown_timeout])
578 a8083063 Iustin Pop
579 4a0e011f Iustin Pop
  def call_instance_os_add(self, node, inst, reinstall, debug):
580 72737a7f Iustin Pop
    """Installs an OS on the given instance.
581 a8083063 Iustin Pop

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

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

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

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

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

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

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

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

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

621 56e7640c Iustin Pop

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

987 72737a7f Iustin Pop
    """
988 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "blockdev_snapshot", [cf_bdev.ToDict()])
989 a8083063 Iustin Pop
990 72737a7f Iustin Pop
  def call_snapshot_export(self, node, snap_bdev, dest_node, instance,
991 4a0e011f Iustin Pop
                           cluster_name, idx, debug):
992 72737a7f Iustin Pop
    """Request the export of a given snapshot.
993 a8083063 Iustin Pop

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

996 72737a7f Iustin Pop
    """
997 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "snapshot_export",
998 9a525d83 Michael Hanselmann
                                [snap_bdev.ToDict(), dest_node,
999 4a0e011f Iustin Pop
                                 self._InstDict(instance), cluster_name,
1000 4a0e011f Iustin Pop
                                 idx, debug])
1001 a8083063 Iustin Pop
1002 72737a7f Iustin Pop
  def call_finalize_export(self, node, instance, snap_disks):
1003 72737a7f Iustin Pop
    """Request the completion of an export operation.
1004 a8083063 Iustin Pop

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1099 72737a7f Iustin Pop
    """
1100 9a525d83 Michael Hanselmann
    return self._MultiNodeCall(node_list, "test_delay", [duration])
1101 5e04ed8b Manuel Franceschini
1102 72737a7f Iustin Pop
  def call_file_storage_dir_create(self, node, file_storage_dir):
1103 72737a7f Iustin Pop
    """Create 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_create",
1109 9a525d83 Michael Hanselmann
                                [file_storage_dir])
1110 5e04ed8b Manuel Franceschini
1111 72737a7f Iustin Pop
  def call_file_storage_dir_remove(self, node, file_storage_dir):
1112 72737a7f Iustin Pop
    """Remove the given file storage directory.
1113 5e04ed8b Manuel Franceschini

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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