Statistics
| Branch: | Tag: | Revision:

root / lib / rpc.py @ 2971c913

History | View | Annotate | Download (33.1 kB)

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

24 a8083063 Iustin Pop
"""
25 a8083063 Iustin Pop
26 72737a7f Iustin Pop
# pylint: disable-msg=C0103,R0201,R0904
27 72737a7f Iustin Pop
# C0103: Invalid name, since call_ are not valid
28 72737a7f Iustin Pop
# R0201: Method could be a function, we keep all rpcs instance methods
29 72737a7f Iustin Pop
# as not to change them back and forth between static/instance methods
30 72737a7f Iustin Pop
# if they need to start using instance attributes
31 72737a7f Iustin Pop
# R0904: Too many public methods
32 a8083063 Iustin Pop
33 a8083063 Iustin Pop
import os
34 81010134 Iustin Pop
import socket
35 58b311ca Iustin Pop
import logging
36 12bce260 Michael Hanselmann
import zlib
37 12bce260 Michael Hanselmann
import base64
38 a8083063 Iustin Pop
39 a8083063 Iustin Pop
from ganeti import utils
40 a8083063 Iustin Pop
from ganeti import objects
41 ecfe9491 Michael Hanselmann
from ganeti import http
42 7c28c575 Michael Hanselmann
from ganeti import serializer
43 eafd8762 Michael Hanselmann
from ganeti import constants
44 781de953 Iustin Pop
from ganeti import errors
45 a8083063 Iustin Pop
46 ae88ef45 Michael Hanselmann
import ganeti.http.client
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 4331f6cd Michael Hanselmann
  global _http_manager
60 4331f6cd Michael Hanselmann
61 4331f6cd Michael Hanselmann
  assert not _http_manager, "RPC module initialized more than once"
62 4331f6cd Michael Hanselmann
63 ae88ef45 Michael Hanselmann
  _http_manager = http.client.HttpClientManager()
64 4331f6cd Michael Hanselmann
65 4331f6cd Michael Hanselmann
66 4331f6cd Michael Hanselmann
def Shutdown():
67 4331f6cd Michael Hanselmann
  """Stops the module-global HTTP client manager.
68 4331f6cd Michael Hanselmann

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

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

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

86 ed83f5cc Iustin Pop
  @ivar data: the data payload, for successfull results, or None
87 ed83f5cc Iustin Pop
  @type failed: boolean
88 ed83f5cc Iustin Pop
  @ivar failed: whether the operation failed at RPC level (not
89 ed83f5cc Iustin Pop
      application level on the remote node)
90 ed83f5cc Iustin Pop
  @ivar call: the name of the RPC call
91 ed83f5cc Iustin Pop
  @ivar node: the name of the node to which we made the call
92 ed83f5cc Iustin Pop
  @ivar offline: whether the operation failed because the node was
93 ed83f5cc Iustin Pop
      offline, as opposed to actual failure; offline=True will always
94 ed83f5cc Iustin Pop
      imply failed=True, in order to allow simpler checking if
95 ed83f5cc Iustin Pop
      the user doesn't care about the exact failure mode
96 ed83f5cc Iustin Pop

97 781de953 Iustin Pop
  """
98 ed83f5cc Iustin Pop
  def __init__(self, data=None, failed=False, offline=False,
99 ed83f5cc Iustin Pop
               call=None, node=None):
100 781de953 Iustin Pop
    self.failed = failed
101 ed83f5cc Iustin Pop
    self.offline = offline
102 ed83f5cc Iustin Pop
    self.call = call
103 ed83f5cc Iustin Pop
    self.node = node
104 ed83f5cc Iustin Pop
    if offline:
105 ed83f5cc Iustin Pop
      self.failed = True
106 ed83f5cc Iustin Pop
      self.error = "Node is marked offline"
107 f2def43a Iustin Pop
      self.data = self.payload = None
108 ed83f5cc Iustin Pop
    elif failed:
109 781de953 Iustin Pop
      self.error = data
110 f2def43a Iustin Pop
      self.data = self.payload = None
111 781de953 Iustin Pop
    else:
112 781de953 Iustin Pop
      self.data = data
113 781de953 Iustin Pop
      self.error = None
114 f2def43a Iustin Pop
      if isinstance(data, (tuple, list)) and len(data) == 2:
115 f2def43a Iustin Pop
        self.payload = data[1]
116 f2def43a Iustin Pop
      else:
117 f2def43a Iustin Pop
        self.payload = None
118 781de953 Iustin Pop
119 781de953 Iustin Pop
  def Raise(self):
120 781de953 Iustin Pop
    """If the result has failed, raise an OpExecError.
121 781de953 Iustin Pop

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

125 781de953 Iustin Pop
    """
126 781de953 Iustin Pop
    if self.failed:
127 781de953 Iustin Pop
      raise errors.OpExecError("Call '%s' to node '%s' has failed: %s" %
128 781de953 Iustin Pop
                               (self.call, self.node, self.error))
129 781de953 Iustin Pop
130 3247bbac Iustin Pop
  def RemoteFailMsg(self):
131 3247bbac Iustin Pop
    """Check if the remote procedure failed.
132 3247bbac Iustin Pop

133 3247bbac Iustin Pop
    This is valid only for RPC calls which return result of the form
134 3247bbac Iustin Pop
    (status, data | error_msg).
135 3247bbac Iustin Pop

136 3247bbac Iustin Pop
    @return: empty string for succcess, otherwise an error message
137 3247bbac Iustin Pop

138 3247bbac Iustin Pop
    """
139 3247bbac Iustin Pop
    def _EnsureErr(val):
140 3247bbac Iustin Pop
      """Helper to ensure we return a 'True' value for error."""
141 3247bbac Iustin Pop
      if val:
142 3247bbac Iustin Pop
        return val
143 3247bbac Iustin Pop
      else:
144 3247bbac Iustin Pop
        return "No error information"
145 3247bbac Iustin Pop
146 3247bbac Iustin Pop
    if self.failed:
147 3247bbac Iustin Pop
      return _EnsureErr(self.error)
148 3247bbac Iustin Pop
    if not isinstance(self.data, (tuple, list)):
149 3247bbac Iustin Pop
      return "Invalid result type (%s)" % type(self.data)
150 3247bbac Iustin Pop
    if len(self.data) != 2:
151 3247bbac Iustin Pop
      return "Invalid result length (%d), expected 2" % len(self.data)
152 3247bbac Iustin Pop
    if not self.data[0]:
153 3247bbac Iustin Pop
      return _EnsureErr(self.data[1])
154 3247bbac Iustin Pop
    return ""
155 3247bbac Iustin Pop
156 781de953 Iustin Pop
157 a8083063 Iustin Pop
class Client:
158 a8083063 Iustin Pop
  """RPC Client class.
159 a8083063 Iustin Pop

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

164 a8083063 Iustin Pop
  One current bug is that generic failure is still signalled by
165 a8083063 Iustin Pop
  'False' result, which is not good. This overloading of values can
166 a8083063 Iustin Pop
  cause bugs.
167 a8083063 Iustin Pop

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

182 3ef3c771 Iustin Pop
    @type node_list: list
183 3ef3c771 Iustin Pop
    @param node_list: the list of node names to connect
184 bdf7d8c0 Iustin Pop
    @type address_list: list or None
185 bdf7d8c0 Iustin Pop
    @keyword address_list: either None or a list with node addresses,
186 bdf7d8c0 Iustin Pop
        which must have the same length as the node list
187 3ef3c771 Iustin Pop

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

200 bdf7d8c0 Iustin Pop
    @type name: str
201 bdf7d8c0 Iustin Pop
    @param name: the node name
202 bdf7d8c0 Iustin Pop
    @type address: str
203 bdf7d8c0 Iustin Pop
    @keyword address: the node address, if known
204 bdf7d8c0 Iustin Pop

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

219 ecfe9491 Michael Hanselmann
    @rtype: list
220 5fcc718f Iustin Pop
    @return: List of RPC results
221 a8083063 Iustin Pop

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

255 72737a7f Iustin Pop
    @type cfg:  C{config.ConfigWriter}
256 72737a7f Iustin Pop
    @param cfg: the configuration object that will be used to get data
257 72737a7f Iustin Pop
                about the cluster
258 a8083063 Iustin Pop

259 72737a7f Iustin Pop
    """
260 72737a7f Iustin Pop
    self._cfg = cfg
261 160e2921 Iustin Pop
    self.port = utils.GetNodeDaemonPort()
262 a8083063 Iustin Pop
263 0eca8e0c Iustin Pop
  def _InstDict(self, instance, hvp=None, bep=None):
264 26ba2bd8 Iustin Pop
    """Convert the given instance to a dict.
265 26ba2bd8 Iustin Pop

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

269 26ba2bd8 Iustin Pop
    @type instance: L{objects.Instance}
270 26ba2bd8 Iustin Pop
    @param instance: an Instance object
271 0eca8e0c Iustin Pop
    @type hvp: dict or None
272 0eca8e0c Iustin Pop
    @param hvp: a dictionary with overriden hypervisor parameters
273 0eca8e0c Iustin Pop
    @type bep: dict or None
274 0eca8e0c Iustin Pop
    @param bep: a dictionary with overriden backend parameters
275 26ba2bd8 Iustin Pop
    @rtype: dict
276 26ba2bd8 Iustin Pop
    @return: the instance dict, with the hvparams filled with the
277 26ba2bd8 Iustin Pop
        cluster defaults
278 26ba2bd8 Iustin Pop

279 26ba2bd8 Iustin Pop
    """
280 26ba2bd8 Iustin Pop
    idict = instance.ToDict()
281 5b442704 Iustin Pop
    cluster = self._cfg.GetClusterInfo()
282 5b442704 Iustin Pop
    idict["hvparams"] = cluster.FillHV(instance)
283 0eca8e0c Iustin Pop
    if hvp is not None:
284 0eca8e0c Iustin Pop
      idict["hvparams"].update(hvp)
285 5b442704 Iustin Pop
    idict["beparams"] = cluster.FillBE(instance)
286 0eca8e0c Iustin Pop
    if bep is not None:
287 0eca8e0c Iustin Pop
      idict["beparams"].update(bep)
288 26ba2bd8 Iustin Pop
    return idict
289 26ba2bd8 Iustin Pop
290 84b45587 Iustin Pop
  def _ConnectList(self, client, node_list, call):
291 25348212 Iustin Pop
    """Helper for computing node addresses.
292 25348212 Iustin Pop

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

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

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

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

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

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

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

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

388 12bce260 Michael Hanselmann
    Small amounts of data are not compressed.
389 12bce260 Michael Hanselmann

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

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

411 72737a7f Iustin Pop
    This is a multi-node call.
412 a8083063 Iustin Pop

413 72737a7f Iustin Pop
    """
414 9a525d83 Michael Hanselmann
    return self._MultiNodeCall(node_list, "volume_list", [vg_name])
415 a8083063 Iustin Pop
416 72737a7f Iustin Pop
  def call_vg_list(self, node_list):
417 72737a7f Iustin Pop
    """Gets the volume group list.
418 a8083063 Iustin Pop

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

421 72737a7f Iustin Pop
    """
422 9a525d83 Michael Hanselmann
    return self._MultiNodeCall(node_list, "vg_list", [])
423 a8083063 Iustin Pop
424 72737a7f Iustin Pop
  def call_bridges_exist(self, node, bridges_list):
425 72737a7f Iustin Pop
    """Checks if a node has all the bridges given.
426 a8083063 Iustin Pop

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

431 72737a7f Iustin Pop
    This is a single-node call.
432 a8083063 Iustin Pop

433 72737a7f Iustin Pop
    """
434 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "bridges_exist", [bridges_list])
435 a8083063 Iustin Pop
436 0eca8e0c Iustin Pop
  def call_instance_start(self, node, instance, hvp, bep):
437 72737a7f Iustin Pop
    """Starts an instance.
438 a8083063 Iustin Pop

439 72737a7f Iustin Pop
    This is a single-node call.
440 a8083063 Iustin Pop

441 72737a7f Iustin Pop
    """
442 0eca8e0c Iustin Pop
    idict = self._InstDict(instance, hvp=hvp, bep=bep)
443 0eca8e0c Iustin Pop
    return self._SingleNodeCall(node, "instance_start", [idict])
444 a8083063 Iustin Pop
445 72737a7f Iustin Pop
  def call_instance_shutdown(self, node, instance):
446 72737a7f Iustin Pop
    """Stops an instance.
447 a8083063 Iustin Pop

448 72737a7f Iustin Pop
    This is a single-node call.
449 2a10865c Iustin Pop

450 72737a7f Iustin Pop
    """
451 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "instance_shutdown",
452 9a525d83 Michael Hanselmann
                                [self._InstDict(instance)])
453 2a10865c Iustin Pop
454 6906a9d8 Guido Trotter
  def call_migration_info(self, node, instance):
455 6906a9d8 Guido Trotter
    """Gather the information necessary to prepare an instance migration.
456 6906a9d8 Guido Trotter

457 6906a9d8 Guido Trotter
    This is a single-node call.
458 6906a9d8 Guido Trotter

459 6906a9d8 Guido Trotter
    @type node: string
460 6906a9d8 Guido Trotter
    @param node: the node on which the instance is currently running
461 6906a9d8 Guido Trotter
    @type instance: C{objects.Instance}
462 6906a9d8 Guido Trotter
    @param instance: the instance definition
463 6906a9d8 Guido Trotter

464 6906a9d8 Guido Trotter
    """
465 6906a9d8 Guido Trotter
    return self._SingleNodeCall(node, "migration_info",
466 6906a9d8 Guido Trotter
                                [self._InstDict(instance)])
467 6906a9d8 Guido Trotter
468 6906a9d8 Guido Trotter
  def call_accept_instance(self, node, instance, info, target):
469 6906a9d8 Guido Trotter
    """Prepare a node to accept an instance.
470 6906a9d8 Guido Trotter

471 6906a9d8 Guido Trotter
    This is a single-node call.
472 6906a9d8 Guido Trotter

473 6906a9d8 Guido Trotter
    @type node: string
474 6906a9d8 Guido Trotter
    @param node: the target node for the migration
475 6906a9d8 Guido Trotter
    @type instance: C{objects.Instance}
476 6906a9d8 Guido Trotter
    @param instance: the instance definition
477 6906a9d8 Guido Trotter
    @type info: opaque/hypervisor specific (string/data)
478 6906a9d8 Guido Trotter
    @param info: result for the call_migration_info call
479 6906a9d8 Guido Trotter
    @type target: string
480 6906a9d8 Guido Trotter
    @param target: target hostname (usually ip address) (on the node itself)
481 6906a9d8 Guido Trotter

482 6906a9d8 Guido Trotter
    """
483 6906a9d8 Guido Trotter
    return self._SingleNodeCall(node, "accept_instance",
484 6906a9d8 Guido Trotter
                                [self._InstDict(instance), info, target])
485 6906a9d8 Guido Trotter
486 6906a9d8 Guido Trotter
  def call_finalize_migration(self, node, instance, info, success):
487 6906a9d8 Guido Trotter
    """Finalize any target-node migration specific operation.
488 6906a9d8 Guido Trotter

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

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

494 6906a9d8 Guido Trotter
    @type node: string
495 6906a9d8 Guido Trotter
    @param node: the target node for the migration
496 6906a9d8 Guido Trotter
    @type instance: C{objects.Instance}
497 6906a9d8 Guido Trotter
    @param instance: the instance definition
498 6906a9d8 Guido Trotter
    @type info: opaque/hypervisor specific (string/data)
499 6906a9d8 Guido Trotter
    @param info: result for the call_migration_info call
500 6906a9d8 Guido Trotter
    @type success: boolean
501 6906a9d8 Guido Trotter
    @param success: whether the migration was a success or a failure
502 6906a9d8 Guido Trotter

503 6906a9d8 Guido Trotter
    """
504 6906a9d8 Guido Trotter
    return self._SingleNodeCall(node, "finalize_migration",
505 6906a9d8 Guido Trotter
                                [self._InstDict(instance), info, success])
506 6906a9d8 Guido Trotter
507 72737a7f Iustin Pop
  def call_instance_migrate(self, node, instance, target, live):
508 72737a7f Iustin Pop
    """Migrate an instance.
509 2a10865c Iustin Pop

510 72737a7f Iustin Pop
    This is a single-node call.
511 2a10865c Iustin Pop

512 72737a7f Iustin Pop
    @type node: string
513 72737a7f Iustin Pop
    @param node: the node on which the instance is currently running
514 72737a7f Iustin Pop
    @type instance: C{objects.Instance}
515 72737a7f Iustin Pop
    @param instance: the instance definition
516 72737a7f Iustin Pop
    @type target: string
517 72737a7f Iustin Pop
    @param target: the target node name
518 72737a7f Iustin Pop
    @type live: boolean
519 72737a7f Iustin Pop
    @param live: whether the migration should be done live or not (the
520 72737a7f Iustin Pop
        interpretation of this parameter is left to the hypervisor)
521 007a2f3e Alexander Schreiber

522 72737a7f Iustin Pop
    """
523 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "instance_migrate",
524 9a525d83 Michael Hanselmann
                                [self._InstDict(instance), target, live])
525 007a2f3e Alexander Schreiber
526 07813a9e Iustin Pop
  def call_instance_reboot(self, node, instance, reboot_type):
527 72737a7f Iustin Pop
    """Reboots an instance.
528 007a2f3e Alexander Schreiber

529 72737a7f Iustin Pop
    This is a single-node call.
530 a8083063 Iustin Pop

531 72737a7f Iustin Pop
    """
532 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "instance_reboot",
533 07813a9e Iustin Pop
                                [self._InstDict(instance), reboot_type])
534 a8083063 Iustin Pop
535 e557bae9 Guido Trotter
  def call_instance_os_add(self, node, inst, reinstall):
536 72737a7f Iustin Pop
    """Installs an OS on the given instance.
537 a8083063 Iustin Pop

538 72737a7f Iustin Pop
    This is a single-node call.
539 decd5f45 Iustin Pop

540 72737a7f Iustin Pop
    """
541 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "instance_os_add",
542 e557bae9 Guido Trotter
                                [self._InstDict(inst), reinstall])
543 decd5f45 Iustin Pop
544 d15a9ad3 Guido Trotter
  def call_instance_run_rename(self, node, inst, old_name):
545 72737a7f Iustin Pop
    """Run the OS rename script for an instance.
546 decd5f45 Iustin Pop

547 72737a7f Iustin Pop
    This is a single-node call.
548 a8083063 Iustin Pop

549 72737a7f Iustin Pop
    """
550 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "instance_run_rename",
551 9a525d83 Michael Hanselmann
                                [self._InstDict(inst), old_name])
552 a8083063 Iustin Pop
553 72737a7f Iustin Pop
  def call_instance_info(self, node, instance, hname):
554 72737a7f Iustin Pop
    """Returns information about a single instance.
555 a8083063 Iustin Pop

556 72737a7f Iustin Pop
    This is a single-node call.
557 a8083063 Iustin Pop

558 9a525d83 Michael Hanselmann
    @type node: list
559 9a525d83 Michael Hanselmann
    @param node: the list of nodes to query
560 72737a7f Iustin Pop
    @type instance: string
561 72737a7f Iustin Pop
    @param instance: the instance name
562 72737a7f Iustin Pop
    @type hname: string
563 72737a7f Iustin Pop
    @param hname: the hypervisor type of the instance
564 a8083063 Iustin Pop

565 72737a7f Iustin Pop
    """
566 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "instance_info", [instance, hname])
567 e69d05fd Iustin Pop
568 56e7640c Iustin Pop
  def call_instance_migratable(self, node, instance):
569 56e7640c Iustin Pop
    """Checks whether the given instance can be migrated.
570 56e7640c Iustin Pop

571 56e7640c Iustin Pop
    This is a single-node call.
572 56e7640c Iustin Pop

573 56e7640c Iustin Pop
    @param node: the node to query
574 56e7640c Iustin Pop
    @type instance: L{objects.Instance}
575 56e7640c Iustin Pop
    @param instance: the instance to check
576 56e7640c Iustin Pop

577 56e7640c Iustin Pop

578 56e7640c Iustin Pop
    """
579 56e7640c Iustin Pop
    return self._SingleNodeCall(node, "instance_migratable",
580 56e7640c Iustin Pop
                                [self._InstDict(instance)])
581 56e7640c Iustin Pop
582 72737a7f Iustin Pop
  def call_all_instances_info(self, node_list, hypervisor_list):
583 72737a7f Iustin Pop
    """Returns information about all instances on the given nodes.
584 a8083063 Iustin Pop

585 72737a7f Iustin Pop
    This is a multi-node call.
586 a8083063 Iustin Pop

587 72737a7f Iustin Pop
    @type node_list: list
588 72737a7f Iustin Pop
    @param node_list: the list of nodes to query
589 72737a7f Iustin Pop
    @type hypervisor_list: list
590 72737a7f Iustin Pop
    @param hypervisor_list: the hypervisors to query for instances
591 a8083063 Iustin Pop

592 72737a7f Iustin Pop
    """
593 9a525d83 Michael Hanselmann
    return self._MultiNodeCall(node_list, "all_instances_info",
594 9a525d83 Michael Hanselmann
                               [hypervisor_list])
595 e69d05fd Iustin Pop
596 72737a7f Iustin Pop
  def call_instance_list(self, node_list, hypervisor_list):
597 72737a7f Iustin Pop
    """Returns the list of running instances on a given node.
598 a8083063 Iustin Pop

599 72737a7f Iustin Pop
    This is a multi-node call.
600 a8083063 Iustin Pop

601 72737a7f Iustin Pop
    @type node_list: list
602 72737a7f Iustin Pop
    @param node_list: the list of nodes to query
603 72737a7f Iustin Pop
    @type hypervisor_list: list
604 72737a7f Iustin Pop
    @param hypervisor_list: the hypervisors to query for instances
605 16abfbc2 Alexander Schreiber

606 72737a7f Iustin Pop
    """
607 9a525d83 Michael Hanselmann
    return self._MultiNodeCall(node_list, "instance_list", [hypervisor_list])
608 16abfbc2 Alexander Schreiber
609 72737a7f Iustin Pop
  def call_node_tcp_ping(self, node, source, target, port, timeout,
610 72737a7f Iustin Pop
                         live_port_needed):
611 72737a7f Iustin Pop
    """Do a TcpPing on the remote node
612 a8083063 Iustin Pop

613 72737a7f Iustin Pop
    This is a single-node call.
614 caad16e2 Iustin Pop

615 72737a7f Iustin Pop
    """
616 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "node_tcp_ping",
617 9a525d83 Michael Hanselmann
                                [source, target, port, timeout,
618 72737a7f Iustin Pop
                                 live_port_needed])
619 a8083063 Iustin Pop
620 caad16e2 Iustin Pop
  def call_node_has_ip_address(self, node, address):
621 caad16e2 Iustin Pop
    """Checks if a node has the given IP address.
622 caad16e2 Iustin Pop

623 caad16e2 Iustin Pop
    This is a single-node call.
624 caad16e2 Iustin Pop

625 caad16e2 Iustin Pop
    """
626 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "node_has_ip_address", [address])
627 a8083063 Iustin Pop
628 72737a7f Iustin Pop
  def call_node_info(self, node_list, vg_name, hypervisor_type):
629 72737a7f Iustin Pop
    """Return node information.
630 e69d05fd Iustin Pop

631 72737a7f Iustin Pop
    This will return memory information and volume group size and free
632 72737a7f Iustin Pop
    space.
633 a8083063 Iustin Pop

634 72737a7f Iustin Pop
    This is a multi-node call.
635 a8083063 Iustin Pop

636 72737a7f Iustin Pop
    @type node_list: list
637 72737a7f Iustin Pop
    @param node_list: the list of nodes to query
638 c41eea6e Iustin Pop
    @type vg_name: C{string}
639 c41eea6e Iustin Pop
    @param vg_name: the name of the volume group to ask for disk space
640 72737a7f Iustin Pop
        information
641 72737a7f Iustin Pop
    @type hypervisor_type: C{str}
642 72737a7f Iustin Pop
    @param hypervisor_type: the name of the hypervisor to ask for
643 72737a7f Iustin Pop
        memory information
644 a8083063 Iustin Pop

645 72737a7f Iustin Pop
    """
646 9a525d83 Michael Hanselmann
    retux = self._MultiNodeCall(node_list, "node_info",
647 9a525d83 Michael Hanselmann
                                [vg_name, hypervisor_type])
648 a8083063 Iustin Pop
649 781de953 Iustin Pop
    for result in retux.itervalues():
650 781de953 Iustin Pop
      if result.failed or not isinstance(result.data, dict):
651 781de953 Iustin Pop
        result.data = {}
652 186ec53c Iustin Pop
      if result.offline:
653 186ec53c Iustin Pop
        log_name = None
654 186ec53c Iustin Pop
      else:
655 186ec53c Iustin Pop
        log_name = "call_node_info"
656 781de953 Iustin Pop
657 781de953 Iustin Pop
      utils.CheckDict(result.data, {
658 781de953 Iustin Pop
        'memory_total' : '-',
659 781de953 Iustin Pop
        'memory_dom0' : '-',
660 781de953 Iustin Pop
        'memory_free' : '-',
661 781de953 Iustin Pop
        'vg_size' : 'node_unreachable',
662 781de953 Iustin Pop
        'vg_free' : '-',
663 186ec53c Iustin Pop
        }, log_name)
664 72737a7f Iustin Pop
    return retux
665 a8083063 Iustin Pop
666 72737a7f Iustin Pop
  def call_node_add(self, node, dsa, dsapub, rsa, rsapub, ssh, sshpub):
667 72737a7f Iustin Pop
    """Add a node to the cluster.
668 a8083063 Iustin Pop

669 72737a7f Iustin Pop
    This is a single-node call.
670 a8083063 Iustin Pop

671 72737a7f Iustin Pop
    """
672 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "node_add",
673 9a525d83 Michael Hanselmann
                                [dsa, dsapub, rsa, rsapub, ssh, sshpub])
674 a8083063 Iustin Pop
675 72737a7f Iustin Pop
  def call_node_verify(self, node_list, checkdict, cluster_name):
676 72737a7f Iustin Pop
    """Request verification of given parameters.
677 a8083063 Iustin Pop

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

680 72737a7f Iustin Pop
    """
681 9a525d83 Michael Hanselmann
    return self._MultiNodeCall(node_list, "node_verify",
682 9a525d83 Michael Hanselmann
                               [checkdict, cluster_name])
683 a8083063 Iustin Pop
684 9a525d83 Michael Hanselmann
  @classmethod
685 9a525d83 Michael Hanselmann
  def call_node_start_master(cls, node, start_daemons):
686 72737a7f Iustin Pop
    """Tells a node to activate itself as a master.
687 a8083063 Iustin Pop

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

690 72737a7f Iustin Pop
    """
691 9a525d83 Michael Hanselmann
    return cls._StaticSingleNodeCall(node, "node_start_master",
692 9a525d83 Michael Hanselmann
                                     [start_daemons])
693 a8083063 Iustin Pop
694 9a525d83 Michael Hanselmann
  @classmethod
695 9a525d83 Michael Hanselmann
  def call_node_stop_master(cls, node, stop_daemons):
696 72737a7f Iustin Pop
    """Tells a node to demote itself from master status.
697 a8083063 Iustin Pop

698 72737a7f Iustin Pop
    This is a single-node call.
699 4e071d3b Iustin Pop

700 72737a7f Iustin Pop
    """
701 9a525d83 Michael Hanselmann
    return cls._StaticSingleNodeCall(node, "node_stop_master", [stop_daemons])
702 4e071d3b Iustin Pop
703 9a525d83 Michael Hanselmann
  @classmethod
704 9a525d83 Michael Hanselmann
  def call_master_info(cls, node_list):
705 72737a7f Iustin Pop
    """Query master info.
706 4e071d3b Iustin Pop

707 72737a7f Iustin Pop
    This is a multi-node call.
708 a8083063 Iustin Pop

709 72737a7f Iustin Pop
    """
710 72737a7f Iustin Pop
    # TODO: should this method query down nodes?
711 9a525d83 Michael Hanselmann
    return cls._StaticMultiNodeCall(node_list, "master_info", [])
712 a8083063 Iustin Pop
713 72737a7f Iustin Pop
  def call_version(self, node_list):
714 72737a7f Iustin Pop
    """Query node version.
715 a8083063 Iustin Pop

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

718 72737a7f Iustin Pop
    """
719 9a525d83 Michael Hanselmann
    return self._MultiNodeCall(node_list, "version", [])
720 a8083063 Iustin Pop
721 72737a7f Iustin Pop
  def call_blockdev_create(self, node, bdev, size, owner, on_primary, info):
722 72737a7f Iustin Pop
    """Request creation of a given block device.
723 a8083063 Iustin Pop

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

726 72737a7f Iustin Pop
    """
727 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "blockdev_create",
728 9a525d83 Michael Hanselmann
                                [bdev.ToDict(), size, owner, on_primary, info])
729 a8083063 Iustin Pop
730 72737a7f Iustin Pop
  def call_blockdev_remove(self, node, bdev):
731 72737a7f Iustin Pop
    """Request removal of a given block device.
732 a8083063 Iustin Pop

733 72737a7f Iustin Pop
    This is a single-node call.
734 f3e513ad Iustin Pop

735 72737a7f Iustin Pop
    """
736 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "blockdev_remove", [bdev.ToDict()])
737 f3e513ad Iustin Pop
738 72737a7f Iustin Pop
  def call_blockdev_rename(self, node, devlist):
739 72737a7f Iustin Pop
    """Request rename of the given block devices.
740 f3e513ad Iustin Pop

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

743 72737a7f Iustin Pop
    """
744 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "blockdev_rename",
745 9a525d83 Michael Hanselmann
                                [(d.ToDict(), uid) for d, uid in devlist])
746 a8083063 Iustin Pop
747 72737a7f Iustin Pop
  def call_blockdev_assemble(self, node, disk, owner, on_primary):
748 72737a7f Iustin Pop
    """Request assembling of a given block device.
749 a8083063 Iustin Pop

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

752 72737a7f Iustin Pop
    """
753 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "blockdev_assemble",
754 9a525d83 Michael Hanselmann
                                [disk.ToDict(), owner, on_primary])
755 a8083063 Iustin Pop
756 72737a7f Iustin Pop
  def call_blockdev_shutdown(self, node, disk):
757 72737a7f Iustin Pop
    """Request shutdown of a given block device.
758 a8083063 Iustin Pop

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

761 72737a7f Iustin Pop
    """
762 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "blockdev_shutdown", [disk.ToDict()])
763 a8083063 Iustin Pop
764 72737a7f Iustin Pop
  def call_blockdev_addchildren(self, node, bdev, ndevs):
765 72737a7f Iustin Pop
    """Request adding a list of children to a (mirroring) device.
766 a8083063 Iustin Pop

767 72737a7f Iustin Pop
    This is a single-node call.
768 a8083063 Iustin Pop

769 72737a7f Iustin Pop
    """
770 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "blockdev_addchildren",
771 9a525d83 Michael Hanselmann
                                [bdev.ToDict(),
772 9a525d83 Michael Hanselmann
                                 [disk.ToDict() for disk in ndevs]])
773 a8083063 Iustin Pop
774 72737a7f Iustin Pop
  def call_blockdev_removechildren(self, node, bdev, ndevs):
775 72737a7f Iustin Pop
    """Request removing a list of children from a (mirroring) device.
776 a8083063 Iustin Pop

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

779 72737a7f Iustin Pop
    """
780 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "blockdev_removechildren",
781 9a525d83 Michael Hanselmann
                                [bdev.ToDict(),
782 9a525d83 Michael Hanselmann
                                 [disk.ToDict() for disk in ndevs]])
783 a8083063 Iustin Pop
784 72737a7f Iustin Pop
  def call_blockdev_getmirrorstatus(self, node, disks):
785 72737a7f Iustin Pop
    """Request status of 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_getmirrorstatus",
791 9a525d83 Michael Hanselmann
                                [dsk.ToDict() for dsk in disks])
792 a8083063 Iustin Pop
793 72737a7f Iustin Pop
  def call_blockdev_find(self, node, disk):
794 72737a7f Iustin Pop
    """Request identification of a given block device.
795 72737a7f Iustin Pop

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

798 72737a7f Iustin Pop
    """
799 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "blockdev_find", [disk.ToDict()])
800 d61cbe76 Iustin Pop
801 b2e7666a Iustin Pop
  def call_blockdev_close(self, node, instance_name, disks):
802 72737a7f Iustin Pop
    """Closes the given block devices.
803 d61cbe76 Iustin Pop

804 72737a7f Iustin Pop
    This is a single-node call.
805 d61cbe76 Iustin Pop

806 72737a7f Iustin Pop
    """
807 b2e7666a Iustin Pop
    params = [instance_name, [cf.ToDict() for cf in disks]]
808 b2e7666a Iustin Pop
    return self._SingleNodeCall(node, "blockdev_close", params)
809 a8083063 Iustin Pop
810 6b93ec9d Iustin Pop
  def call_drbd_disconnect_net(self, node_list, nodes_ip, disks):
811 6b93ec9d Iustin Pop
    """Disconnects the network of the given drbd devices.
812 6b93ec9d Iustin Pop

813 6b93ec9d Iustin Pop
    This is a multi-node call.
814 6b93ec9d Iustin Pop

815 6b93ec9d Iustin Pop
    """
816 6b93ec9d Iustin Pop
    return self._MultiNodeCall(node_list, "drbd_disconnect_net",
817 6b93ec9d Iustin Pop
                               [nodes_ip, [cf.ToDict() for cf in disks]])
818 6b93ec9d Iustin Pop
819 6b93ec9d Iustin Pop
  def call_drbd_attach_net(self, node_list, nodes_ip,
820 6b93ec9d Iustin Pop
                           disks, instance_name, multimaster):
821 6b93ec9d Iustin Pop
    """Disconnects the given drbd devices.
822 6b93ec9d Iustin Pop

823 6b93ec9d Iustin Pop
    This is a multi-node call.
824 6b93ec9d Iustin Pop

825 6b93ec9d Iustin Pop
    """
826 6b93ec9d Iustin Pop
    return self._MultiNodeCall(node_list, "drbd_attach_net",
827 6b93ec9d Iustin Pop
                               [nodes_ip, [cf.ToDict() for cf in disks],
828 6b93ec9d Iustin Pop
                                instance_name, multimaster])
829 6b93ec9d Iustin Pop
830 6b93ec9d Iustin Pop
  def call_drbd_wait_sync(self, node_list, nodes_ip, disks):
831 6b93ec9d Iustin Pop
    """Waits for the synchronization of drbd devices is complete.
832 6b93ec9d Iustin Pop

833 6b93ec9d Iustin Pop
    This is a multi-node call.
834 6b93ec9d Iustin Pop

835 6b93ec9d Iustin Pop
    """
836 6b93ec9d Iustin Pop
    return self._MultiNodeCall(node_list, "drbd_wait_sync",
837 6b93ec9d Iustin Pop
                               [nodes_ip, [cf.ToDict() for cf in disks]])
838 6b93ec9d Iustin Pop
839 9a525d83 Michael Hanselmann
  @classmethod
840 9a525d83 Michael Hanselmann
  def call_upload_file(cls, node_list, file_name, address_list=None):
841 72737a7f Iustin Pop
    """Upload a file.
842 72737a7f Iustin Pop

843 72737a7f Iustin Pop
    The node will refuse the operation in case the file is not on the
844 72737a7f Iustin Pop
    approved file list.
845 72737a7f Iustin Pop

846 72737a7f Iustin Pop
    This is a multi-node call.
847 a8083063 Iustin Pop

848 6b294c53 Iustin Pop
    @type node_list: list
849 6b294c53 Iustin Pop
    @param node_list: the list of node names to upload to
850 6b294c53 Iustin Pop
    @type file_name: str
851 6b294c53 Iustin Pop
    @param file_name: the filename to upload
852 6b294c53 Iustin Pop
    @type address_list: list or None
853 6b294c53 Iustin Pop
    @keyword address_list: an optional list of node addresses, in order
854 6b294c53 Iustin Pop
        to optimize the RPC speed
855 6b294c53 Iustin Pop

856 72737a7f Iustin Pop
    """
857 12bce260 Michael Hanselmann
    file_contents = utils.ReadFile(file_name)
858 12bce260 Michael Hanselmann
    data = cls._Compress(file_contents)
859 72737a7f Iustin Pop
    st = os.stat(file_name)
860 72737a7f Iustin Pop
    params = [file_name, data, st.st_mode, st.st_uid, st.st_gid,
861 72737a7f Iustin Pop
              st.st_atime, st.st_mtime]
862 9a525d83 Michael Hanselmann
    return cls._StaticMultiNodeCall(node_list, "upload_file", params,
863 9a525d83 Michael Hanselmann
                                    address_list=address_list)
864 72737a7f Iustin Pop
865 6ddc95ec Michael Hanselmann
  @classmethod
866 03d1dba2 Michael Hanselmann
  def call_write_ssconf_files(cls, node_list, values):
867 6ddc95ec Michael Hanselmann
    """Write ssconf files.
868 6ddc95ec Michael Hanselmann

869 6ddc95ec Michael Hanselmann
    This is a multi-node call.
870 6ddc95ec Michael Hanselmann

871 6ddc95ec Michael Hanselmann
    """
872 03d1dba2 Michael Hanselmann
    return cls._StaticMultiNodeCall(node_list, "write_ssconf_files", [values])
873 6ddc95ec Michael Hanselmann
874 72737a7f Iustin Pop
  def call_os_diagnose(self, node_list):
875 72737a7f Iustin Pop
    """Request a diagnose of OS definitions.
876 72737a7f Iustin Pop

877 72737a7f Iustin Pop
    This is a multi-node call.
878 a8083063 Iustin Pop

879 72737a7f Iustin Pop
    """
880 9a525d83 Michael Hanselmann
    result = self._MultiNodeCall(node_list, "os_diagnose", [])
881 9a525d83 Michael Hanselmann
882 fab1e3a4 Iustin Pop
    for node_result in result.values():
883 781de953 Iustin Pop
      if not node_result.failed and node_result.data:
884 781de953 Iustin Pop
        node_result.data = [objects.OS.FromDict(oss)
885 781de953 Iustin Pop
                            for oss in node_result.data]
886 781de953 Iustin Pop
    return result
887 a8083063 Iustin Pop
888 72737a7f Iustin Pop
  def call_os_get(self, node, name):
889 72737a7f Iustin Pop
    """Returns an OS definition.
890 a8083063 Iustin Pop

891 72737a7f Iustin Pop
    This is a single-node call.
892 a8083063 Iustin Pop

893 72737a7f Iustin Pop
    """
894 9a525d83 Michael Hanselmann
    result = self._SingleNodeCall(node, "os_get", [name])
895 781de953 Iustin Pop
    if not result.failed and isinstance(result.data, dict):
896 781de953 Iustin Pop
      result.data = objects.OS.FromDict(result.data)
897 781de953 Iustin Pop
    return result
898 a8083063 Iustin Pop
899 72737a7f Iustin Pop
  def call_hooks_runner(self, node_list, hpath, phase, env):
900 72737a7f Iustin Pop
    """Call the hooks runner.
901 a8083063 Iustin Pop

902 72737a7f Iustin Pop
    Args:
903 72737a7f Iustin Pop
      - op: the OpCode instance
904 72737a7f Iustin Pop
      - env: a dictionary with the environment
905 a8083063 Iustin Pop

906 72737a7f Iustin Pop
    This is a multi-node call.
907 a8083063 Iustin Pop

908 72737a7f Iustin Pop
    """
909 72737a7f Iustin Pop
    params = [hpath, phase, env]
910 9a525d83 Michael Hanselmann
    return self._MultiNodeCall(node_list, "hooks_runner", params)
911 a8083063 Iustin Pop
912 72737a7f Iustin Pop
  def call_iallocator_runner(self, node, name, idata):
913 72737a7f Iustin Pop
    """Call an iallocator on a remote node
914 8d528b7c Iustin Pop

915 72737a7f Iustin Pop
    Args:
916 72737a7f Iustin Pop
      - name: the iallocator name
917 72737a7f Iustin Pop
      - input: the json-encoded input string
918 8d528b7c Iustin Pop

919 72737a7f Iustin Pop
    This is a single-node call.
920 8d528b7c Iustin Pop

921 72737a7f Iustin Pop
    """
922 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "iallocator_runner", [name, idata])
923 8d528b7c Iustin Pop
924 72737a7f Iustin Pop
  def call_blockdev_grow(self, node, cf_bdev, amount):
925 72737a7f Iustin Pop
    """Request a snapshot of the given block device.
926 4c8ba8b3 Iustin Pop

927 72737a7f Iustin Pop
    This is a single-node call.
928 4c8ba8b3 Iustin Pop

929 72737a7f Iustin Pop
    """
930 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "blockdev_grow",
931 9a525d83 Michael Hanselmann
                                [cf_bdev.ToDict(), amount])
932 4c8ba8b3 Iustin Pop
933 72737a7f Iustin Pop
  def call_blockdev_snapshot(self, node, cf_bdev):
934 72737a7f Iustin Pop
    """Request a snapshot of the given block device.
935 a8083063 Iustin Pop

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

938 72737a7f Iustin Pop
    """
939 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "blockdev_snapshot", [cf_bdev.ToDict()])
940 a8083063 Iustin Pop
941 72737a7f Iustin Pop
  def call_snapshot_export(self, node, snap_bdev, dest_node, instance,
942 74c47259 Iustin Pop
                           cluster_name, idx):
943 72737a7f Iustin Pop
    """Request the export of a given snapshot.
944 a8083063 Iustin Pop

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

947 72737a7f Iustin Pop
    """
948 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "snapshot_export",
949 9a525d83 Michael Hanselmann
                                [snap_bdev.ToDict(), dest_node,
950 9a525d83 Michael Hanselmann
                                 self._InstDict(instance), cluster_name, idx])
951 a8083063 Iustin Pop
952 72737a7f Iustin Pop
  def call_finalize_export(self, node, instance, snap_disks):
953 72737a7f Iustin Pop
    """Request the completion of an export operation.
954 a8083063 Iustin Pop

955 72737a7f Iustin Pop
    This writes the export config file, etc.
956 a8083063 Iustin Pop

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

959 72737a7f Iustin Pop
    """
960 72737a7f Iustin Pop
    flat_disks = []
961 72737a7f Iustin Pop
    for disk in snap_disks:
962 72737a7f Iustin Pop
      flat_disks.append(disk.ToDict())
963 9a525d83 Michael Hanselmann
964 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "finalize_export",
965 9a525d83 Michael Hanselmann
                                [self._InstDict(instance), flat_disks])
966 a8083063 Iustin Pop
967 72737a7f Iustin Pop
  def call_export_info(self, node, path):
968 72737a7f Iustin Pop
    """Queries the export information in a given path.
969 a8083063 Iustin Pop

970 72737a7f Iustin Pop
    This is a single-node call.
971 a8083063 Iustin Pop

972 72737a7f Iustin Pop
    """
973 9a525d83 Michael Hanselmann
    result = self._SingleNodeCall(node, "export_info", [path])
974 781de953 Iustin Pop
    if not result.failed and result.data:
975 781de953 Iustin Pop
      result.data = objects.SerializableConfigParser.Loads(str(result.data))
976 781de953 Iustin Pop
    return result
977 a8083063 Iustin Pop
978 6c0af70e Guido Trotter
  def call_instance_os_import(self, node, inst, src_node, src_images,
979 6c0af70e Guido Trotter
                              cluster_name):
980 72737a7f Iustin Pop
    """Request the import of a backup into an instance.
981 a8083063 Iustin Pop

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

984 72737a7f Iustin Pop
    """
985 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "instance_os_import",
986 9a525d83 Michael Hanselmann
                                [self._InstDict(inst), src_node, src_images,
987 9a525d83 Michael Hanselmann
                                 cluster_name])
988 a8083063 Iustin Pop
989 72737a7f Iustin Pop
  def call_export_list(self, node_list):
990 72737a7f Iustin Pop
    """Gets the stored exports list.
991 a8083063 Iustin Pop

992 72737a7f Iustin Pop
    This is a multi-node call.
993 a8083063 Iustin Pop

994 72737a7f Iustin Pop
    """
995 9a525d83 Michael Hanselmann
    return self._MultiNodeCall(node_list, "export_list", [])
996 a8083063 Iustin Pop
997 72737a7f Iustin Pop
  def call_export_remove(self, node, export):
998 72737a7f Iustin Pop
    """Requests removal of a given export.
999 a8083063 Iustin Pop

1000 72737a7f Iustin Pop
    This is a single-node call.
1001 a8083063 Iustin Pop

1002 72737a7f Iustin Pop
    """
1003 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "export_remove", [export])
1004 a8083063 Iustin Pop
1005 9a525d83 Michael Hanselmann
  @classmethod
1006 9a525d83 Michael Hanselmann
  def call_node_leave_cluster(cls, node):
1007 72737a7f Iustin Pop
    """Requests a node to clean the cluster information it has.
1008 a8083063 Iustin Pop

1009 72737a7f Iustin Pop
    This will remove the configuration information from the ganeti data
1010 72737a7f Iustin Pop
    dir.
1011 a8083063 Iustin Pop

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

1014 72737a7f Iustin Pop
    """
1015 9a525d83 Michael Hanselmann
    return cls._StaticSingleNodeCall(node, "node_leave_cluster", [])
1016 dcb93971 Michael Hanselmann
1017 72737a7f Iustin Pop
  def call_node_volumes(self, node_list):
1018 72737a7f Iustin Pop
    """Gets all volumes on node(s).
1019 dcb93971 Michael Hanselmann

1020 72737a7f Iustin Pop
    This is a multi-node call.
1021 dcb93971 Michael Hanselmann

1022 72737a7f Iustin Pop
    """
1023 9a525d83 Michael Hanselmann
    return self._MultiNodeCall(node_list, "node_volumes", [])
1024 06009e27 Iustin Pop
1025 56aa9fd5 Iustin Pop
  def call_node_demote_from_mc(self, node):
1026 56aa9fd5 Iustin Pop
    """Demote a node from the master candidate role.
1027 56aa9fd5 Iustin Pop

1028 56aa9fd5 Iustin Pop
    This is a single-node call.
1029 56aa9fd5 Iustin Pop

1030 56aa9fd5 Iustin Pop
    """
1031 56aa9fd5 Iustin Pop
    return self._SingleNodeCall(node, "node_demote_from_mc", [])
1032 56aa9fd5 Iustin Pop
1033 72737a7f Iustin Pop
  def call_test_delay(self, node_list, duration):
1034 72737a7f Iustin Pop
    """Sleep for a fixed time on given node(s).
1035 06009e27 Iustin Pop

1036 72737a7f Iustin Pop
    This is a multi-node call.
1037 06009e27 Iustin Pop

1038 72737a7f Iustin Pop
    """
1039 9a525d83 Michael Hanselmann
    return self._MultiNodeCall(node_list, "test_delay", [duration])
1040 5e04ed8b Manuel Franceschini
1041 72737a7f Iustin Pop
  def call_file_storage_dir_create(self, node, file_storage_dir):
1042 72737a7f Iustin Pop
    """Create the given file storage directory.
1043 5e04ed8b Manuel Franceschini

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

1046 72737a7f Iustin Pop
    """
1047 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "file_storage_dir_create",
1048 9a525d83 Michael Hanselmann
                                [file_storage_dir])
1049 5e04ed8b Manuel Franceschini
1050 72737a7f Iustin Pop
  def call_file_storage_dir_remove(self, node, file_storage_dir):
1051 72737a7f Iustin Pop
    """Remove the given file storage directory.
1052 5e04ed8b Manuel Franceschini

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

1055 72737a7f Iustin Pop
    """
1056 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "file_storage_dir_remove",
1057 9a525d83 Michael Hanselmann
                                [file_storage_dir])
1058 5e04ed8b Manuel Franceschini
1059 72737a7f Iustin Pop
  def call_file_storage_dir_rename(self, node, old_file_storage_dir,
1060 72737a7f Iustin Pop
                                   new_file_storage_dir):
1061 72737a7f Iustin Pop
    """Rename file storage directory.
1062 5e04ed8b Manuel Franceschini

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

1065 72737a7f Iustin Pop
    """
1066 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "file_storage_dir_rename",
1067 9a525d83 Michael Hanselmann
                                [old_file_storage_dir, new_file_storage_dir])
1068 ca52cdeb Michael Hanselmann
1069 9a525d83 Michael Hanselmann
  @classmethod
1070 9a525d83 Michael Hanselmann
  def call_jobqueue_update(cls, node_list, address_list, file_name, content):
1071 72737a7f Iustin Pop
    """Update job queue.
1072 ca52cdeb Michael Hanselmann

1073 72737a7f Iustin Pop
    This is a multi-node call.
1074 ca52cdeb Michael Hanselmann

1075 72737a7f Iustin Pop
    """
1076 9a525d83 Michael Hanselmann
    return cls._StaticMultiNodeCall(node_list, "jobqueue_update",
1077 12bce260 Michael Hanselmann
                                    [file_name, cls._Compress(content)],
1078 9a525d83 Michael Hanselmann
                                    address_list=address_list)
1079 ca52cdeb Michael Hanselmann
1080 9a525d83 Michael Hanselmann
  @classmethod
1081 9a525d83 Michael Hanselmann
  def call_jobqueue_purge(cls, node):
1082 72737a7f Iustin Pop
    """Purge job queue.
1083 ca52cdeb Michael Hanselmann

1084 72737a7f Iustin Pop
    This is a single-node call.
1085 ca52cdeb Michael Hanselmann

1086 72737a7f Iustin Pop
    """
1087 9a525d83 Michael Hanselmann
    return cls._StaticSingleNodeCall(node, "jobqueue_purge", [])
1088 af5ebcb1 Michael Hanselmann
1089 9a525d83 Michael Hanselmann
  @classmethod
1090 dd875d32 Michael Hanselmann
  def call_jobqueue_rename(cls, node_list, address_list, rename):
1091 72737a7f Iustin Pop
    """Rename a job queue file.
1092 af5ebcb1 Michael Hanselmann

1093 72737a7f Iustin Pop
    This is a multi-node call.
1094 af5ebcb1 Michael Hanselmann

1095 72737a7f Iustin Pop
    """
1096 dd875d32 Michael Hanselmann
    return cls._StaticMultiNodeCall(node_list, "jobqueue_rename", rename,
1097 9a525d83 Michael Hanselmann
                                    address_list=address_list)
1098 6217e295 Iustin Pop
1099 9a525d83 Michael Hanselmann
  @classmethod
1100 9a525d83 Michael Hanselmann
  def call_jobqueue_set_drain(cls, node_list, drain_flag):
1101 5d672980 Iustin Pop
    """Set the drain flag on the queue.
1102 5d672980 Iustin Pop

1103 5d672980 Iustin Pop
    This is a multi-node call.
1104 5d672980 Iustin Pop

1105 5d672980 Iustin Pop
    @type node_list: list
1106 5d672980 Iustin Pop
    @param node_list: the list of nodes to query
1107 5d672980 Iustin Pop
    @type drain_flag: bool
1108 5d672980 Iustin Pop
    @param drain_flag: if True, will set the drain flag, otherwise reset it.
1109 5d672980 Iustin Pop

1110 5d672980 Iustin Pop
    """
1111 9a525d83 Michael Hanselmann
    return cls._StaticMultiNodeCall(node_list, "jobqueue_set_drain",
1112 9a525d83 Michael Hanselmann
                                    [drain_flag])
1113 5d672980 Iustin Pop
1114 6217e295 Iustin Pop
  def call_hypervisor_validate_params(self, node_list, hvname, hvparams):
1115 6217e295 Iustin Pop
    """Validate the hypervisor params.
1116 6217e295 Iustin Pop

1117 6217e295 Iustin Pop
    This is a multi-node call.
1118 6217e295 Iustin Pop

1119 6217e295 Iustin Pop
    @type node_list: list
1120 6217e295 Iustin Pop
    @param node_list: the list of nodes to query
1121 6217e295 Iustin Pop
    @type hvname: string
1122 6217e295 Iustin Pop
    @param hvname: the hypervisor name
1123 6217e295 Iustin Pop
    @type hvparams: dict
1124 6217e295 Iustin Pop
    @param hvparams: the hypervisor parameters to be validated
1125 6217e295 Iustin Pop

1126 6217e295 Iustin Pop
    """
1127 6217e295 Iustin Pop
    cluster = self._cfg.GetClusterInfo()
1128 6217e295 Iustin Pop
    hv_full = cluster.FillDict(cluster.hvparams.get(hvname, {}), hvparams)
1129 9a525d83 Michael Hanselmann
    return self._MultiNodeCall(node_list, "hypervisor_validate_params",
1130 9a525d83 Michael Hanselmann
                               [hvname, hv_full])