Statistics
| Branch: | Tag: | Revision:

root / lib / rpc.py @ 6b405598

History | View | Annotate | Download (32.7 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 26ba2bd8 Iustin Pop
  def _InstDict(self, instance):
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 26ba2bd8 Iustin Pop
    @rtype: dict
272 26ba2bd8 Iustin Pop
    @return: the instance dict, with the hvparams filled with the
273 26ba2bd8 Iustin Pop
        cluster defaults
274 26ba2bd8 Iustin Pop

275 26ba2bd8 Iustin Pop
    """
276 26ba2bd8 Iustin Pop
    idict = instance.ToDict()
277 5b442704 Iustin Pop
    cluster = self._cfg.GetClusterInfo()
278 5b442704 Iustin Pop
    idict["hvparams"] = cluster.FillHV(instance)
279 5b442704 Iustin Pop
    idict["beparams"] = cluster.FillBE(instance)
280 26ba2bd8 Iustin Pop
    return idict
281 26ba2bd8 Iustin Pop
282 84b45587 Iustin Pop
  def _ConnectList(self, client, node_list, call):
283 25348212 Iustin Pop
    """Helper for computing node addresses.
284 25348212 Iustin Pop

285 25348212 Iustin Pop
    @type client: L{Client}
286 25348212 Iustin Pop
    @param client: a C{Client} instance
287 25348212 Iustin Pop
    @type node_list: list
288 25348212 Iustin Pop
    @param node_list: the node list we should connect
289 84b45587 Iustin Pop
    @type call: string
290 84b45587 Iustin Pop
    @param call: the name of the remote procedure call, for filling in
291 84b45587 Iustin Pop
        correctly any eventual offline nodes' results
292 25348212 Iustin Pop

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

315 25348212 Iustin Pop
    @type client: L{Client}
316 25348212 Iustin Pop
    @param client: a C{Client} instance
317 25348212 Iustin Pop
    @type node: str
318 25348212 Iustin Pop
    @param node: the node we should connect
319 84b45587 Iustin Pop
    @type call: string
320 84b45587 Iustin Pop
    @param call: the name of the remote procedure call, for filling in
321 84b45587 Iustin Pop
        correctly any eventual offline nodes' results
322 25348212 Iustin Pop

323 25348212 Iustin Pop
    """
324 25348212 Iustin Pop
    node_info = self._cfg.GetNodeInfo(node)
325 25348212 Iustin Pop
    if node_info is not None:
326 ed83f5cc Iustin Pop
      if node_info.offline:
327 84b45587 Iustin Pop
        return RpcResult(node=node, offline=True, call=call)
328 25348212 Iustin Pop
      addr = node_info.primary_ip
329 25348212 Iustin Pop
    else:
330 25348212 Iustin Pop
      addr = None
331 25348212 Iustin Pop
    client.ConnectNode(node, address=addr)
332 25348212 Iustin Pop
333 ed83f5cc Iustin Pop
  def _MultiNodeCall(self, node_list, procedure, args):
334 160e2921 Iustin Pop
    """Helper for making a multi-node call
335 160e2921 Iustin Pop

336 160e2921 Iustin Pop
    """
337 160e2921 Iustin Pop
    body = serializer.DumpJson(args, indent=False)
338 160e2921 Iustin Pop
    c = Client(procedure, body, self.port)
339 84b45587 Iustin Pop
    skip_dict = self._ConnectList(c, node_list, procedure)
340 ed83f5cc Iustin Pop
    skip_dict.update(c.GetResults())
341 ed83f5cc Iustin Pop
    return skip_dict
342 9a525d83 Michael Hanselmann
343 9a525d83 Michael Hanselmann
  @classmethod
344 9a525d83 Michael Hanselmann
  def _StaticMultiNodeCall(cls, node_list, procedure, args,
345 9a525d83 Michael Hanselmann
                           address_list=None):
346 160e2921 Iustin Pop
    """Helper for making a multi-node static call
347 160e2921 Iustin Pop

348 160e2921 Iustin Pop
    """
349 160e2921 Iustin Pop
    body = serializer.DumpJson(args, indent=False)
350 160e2921 Iustin Pop
    c = Client(procedure, body, utils.GetNodeDaemonPort())
351 9a525d83 Michael Hanselmann
    c.ConnectList(node_list, address_list=address_list)
352 9a525d83 Michael Hanselmann
    return c.GetResults()
353 9a525d83 Michael Hanselmann
354 9a525d83 Michael Hanselmann
  def _SingleNodeCall(self, node, procedure, args):
355 160e2921 Iustin Pop
    """Helper for making a single-node call
356 9a525d83 Michael Hanselmann

357 9a525d83 Michael Hanselmann
    """
358 160e2921 Iustin Pop
    body = serializer.DumpJson(args, indent=False)
359 160e2921 Iustin Pop
    c = Client(procedure, body, self.port)
360 84b45587 Iustin Pop
    result = self._ConnectNode(c, node, procedure)
361 ed83f5cc Iustin Pop
    if result is None:
362 ed83f5cc Iustin Pop
      # we did connect, node is not offline
363 ed83f5cc Iustin Pop
      result = c.GetResults()[node]
364 ed83f5cc Iustin Pop
    return result
365 9a525d83 Michael Hanselmann
366 9a525d83 Michael Hanselmann
  @classmethod
367 9a525d83 Michael Hanselmann
  def _StaticSingleNodeCall(cls, node, procedure, args):
368 160e2921 Iustin Pop
    """Helper for making a single-node static call
369 9a525d83 Michael Hanselmann

370 9a525d83 Michael Hanselmann
    """
371 160e2921 Iustin Pop
    body = serializer.DumpJson(args, indent=False)
372 160e2921 Iustin Pop
    c = Client(procedure, body, utils.GetNodeDaemonPort())
373 3097c858 Michael Hanselmann
    c.ConnectNode(node)
374 ed83f5cc Iustin Pop
    return c.GetResults()[node]
375 9a525d83 Michael Hanselmann
376 12bce260 Michael Hanselmann
  @staticmethod
377 12bce260 Michael Hanselmann
  def _Compress(data):
378 12bce260 Michael Hanselmann
    """Compresses a string for transport over RPC.
379 12bce260 Michael Hanselmann

380 12bce260 Michael Hanselmann
    Small amounts of data are not compressed.
381 12bce260 Michael Hanselmann

382 12bce260 Michael Hanselmann
    @type data: str
383 12bce260 Michael Hanselmann
    @param data: Data
384 12bce260 Michael Hanselmann
    @rtype: tuple
385 12bce260 Michael Hanselmann
    @return: Encoded data to send
386 12bce260 Michael Hanselmann

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

403 72737a7f Iustin Pop
    This is a multi-node call.
404 a8083063 Iustin Pop

405 72737a7f Iustin Pop
    """
406 9a525d83 Michael Hanselmann
    return self._MultiNodeCall(node_list, "volume_list", [vg_name])
407 a8083063 Iustin Pop
408 72737a7f Iustin Pop
  def call_vg_list(self, node_list):
409 72737a7f Iustin Pop
    """Gets the volume group list.
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, "vg_list", [])
415 a8083063 Iustin Pop
416 72737a7f Iustin Pop
  def call_bridges_exist(self, node, bridges_list):
417 72737a7f Iustin Pop
    """Checks if a node has all the bridges given.
418 a8083063 Iustin Pop

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

423 72737a7f Iustin Pop
    This is a single-node call.
424 a8083063 Iustin Pop

425 72737a7f Iustin Pop
    """
426 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "bridges_exist", [bridges_list])
427 a8083063 Iustin Pop
428 07813a9e Iustin Pop
  def call_instance_start(self, node, instance):
429 72737a7f Iustin Pop
    """Starts an instance.
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, "instance_start",
435 07813a9e Iustin Pop
                                [self._InstDict(instance)])
436 a8083063 Iustin Pop
437 72737a7f Iustin Pop
  def call_instance_shutdown(self, node, instance):
438 72737a7f Iustin Pop
    """Stops an instance.
439 a8083063 Iustin Pop

440 72737a7f Iustin Pop
    This is a single-node call.
441 2a10865c Iustin Pop

442 72737a7f Iustin Pop
    """
443 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "instance_shutdown",
444 9a525d83 Michael Hanselmann
                                [self._InstDict(instance)])
445 2a10865c Iustin Pop
446 6906a9d8 Guido Trotter
  def call_migration_info(self, node, instance):
447 6906a9d8 Guido Trotter
    """Gather the information necessary to prepare an instance migration.
448 6906a9d8 Guido Trotter

449 6906a9d8 Guido Trotter
    This is a single-node call.
450 6906a9d8 Guido Trotter

451 6906a9d8 Guido Trotter
    @type node: string
452 6906a9d8 Guido Trotter
    @param node: the node on which the instance is currently running
453 6906a9d8 Guido Trotter
    @type instance: C{objects.Instance}
454 6906a9d8 Guido Trotter
    @param instance: the instance definition
455 6906a9d8 Guido Trotter

456 6906a9d8 Guido Trotter
    """
457 6906a9d8 Guido Trotter
    return self._SingleNodeCall(node, "migration_info",
458 6906a9d8 Guido Trotter
                                [self._InstDict(instance)])
459 6906a9d8 Guido Trotter
460 6906a9d8 Guido Trotter
  def call_accept_instance(self, node, instance, info, target):
461 6906a9d8 Guido Trotter
    """Prepare a node to accept an instance.
462 6906a9d8 Guido Trotter

463 6906a9d8 Guido Trotter
    This is a single-node call.
464 6906a9d8 Guido Trotter

465 6906a9d8 Guido Trotter
    @type node: string
466 6906a9d8 Guido Trotter
    @param node: the target node for the migration
467 6906a9d8 Guido Trotter
    @type instance: C{objects.Instance}
468 6906a9d8 Guido Trotter
    @param instance: the instance definition
469 6906a9d8 Guido Trotter
    @type info: opaque/hypervisor specific (string/data)
470 6906a9d8 Guido Trotter
    @param info: result for the call_migration_info call
471 6906a9d8 Guido Trotter
    @type target: string
472 6906a9d8 Guido Trotter
    @param target: target hostname (usually ip address) (on the node itself)
473 6906a9d8 Guido Trotter

474 6906a9d8 Guido Trotter
    """
475 6906a9d8 Guido Trotter
    return self._SingleNodeCall(node, "accept_instance",
476 6906a9d8 Guido Trotter
                                [self._InstDict(instance), info, target])
477 6906a9d8 Guido Trotter
478 6906a9d8 Guido Trotter
  def call_finalize_migration(self, node, instance, info, success):
479 6906a9d8 Guido Trotter
    """Finalize any target-node migration specific operation.
480 6906a9d8 Guido Trotter

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

484 6906a9d8 Guido Trotter
    This is a single-node call.
485 6906a9d8 Guido Trotter

486 6906a9d8 Guido Trotter
    @type node: string
487 6906a9d8 Guido Trotter
    @param node: the target node for the migration
488 6906a9d8 Guido Trotter
    @type instance: C{objects.Instance}
489 6906a9d8 Guido Trotter
    @param instance: the instance definition
490 6906a9d8 Guido Trotter
    @type info: opaque/hypervisor specific (string/data)
491 6906a9d8 Guido Trotter
    @param info: result for the call_migration_info call
492 6906a9d8 Guido Trotter
    @type success: boolean
493 6906a9d8 Guido Trotter
    @param success: whether the migration was a success or a failure
494 6906a9d8 Guido Trotter

495 6906a9d8 Guido Trotter
    """
496 6906a9d8 Guido Trotter
    return self._SingleNodeCall(node, "finalize_migration",
497 6906a9d8 Guido Trotter
                                [self._InstDict(instance), info, success])
498 6906a9d8 Guido Trotter
499 72737a7f Iustin Pop
  def call_instance_migrate(self, node, instance, target, live):
500 72737a7f Iustin Pop
    """Migrate an instance.
501 2a10865c Iustin Pop

502 72737a7f Iustin Pop
    This is a single-node call.
503 2a10865c Iustin Pop

504 72737a7f Iustin Pop
    @type node: string
505 72737a7f Iustin Pop
    @param node: the node on which the instance is currently running
506 72737a7f Iustin Pop
    @type instance: C{objects.Instance}
507 72737a7f Iustin Pop
    @param instance: the instance definition
508 72737a7f Iustin Pop
    @type target: string
509 72737a7f Iustin Pop
    @param target: the target node name
510 72737a7f Iustin Pop
    @type live: boolean
511 72737a7f Iustin Pop
    @param live: whether the migration should be done live or not (the
512 72737a7f Iustin Pop
        interpretation of this parameter is left to the hypervisor)
513 007a2f3e Alexander Schreiber

514 72737a7f Iustin Pop
    """
515 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "instance_migrate",
516 9a525d83 Michael Hanselmann
                                [self._InstDict(instance), target, live])
517 007a2f3e Alexander Schreiber
518 07813a9e Iustin Pop
  def call_instance_reboot(self, node, instance, reboot_type):
519 72737a7f Iustin Pop
    """Reboots an instance.
520 007a2f3e Alexander Schreiber

521 72737a7f Iustin Pop
    This is a single-node call.
522 a8083063 Iustin Pop

523 72737a7f Iustin Pop
    """
524 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "instance_reboot",
525 07813a9e Iustin Pop
                                [self._InstDict(instance), reboot_type])
526 a8083063 Iustin Pop
527 d15a9ad3 Guido Trotter
  def call_instance_os_add(self, node, inst):
528 72737a7f Iustin Pop
    """Installs an OS on the given instance.
529 a8083063 Iustin Pop

530 72737a7f Iustin Pop
    This is a single-node call.
531 decd5f45 Iustin Pop

532 72737a7f Iustin Pop
    """
533 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "instance_os_add",
534 9a525d83 Michael Hanselmann
                                [self._InstDict(inst)])
535 decd5f45 Iustin Pop
536 d15a9ad3 Guido Trotter
  def call_instance_run_rename(self, node, inst, old_name):
537 72737a7f Iustin Pop
    """Run the OS rename script for an instance.
538 decd5f45 Iustin Pop

539 72737a7f Iustin Pop
    This is a single-node call.
540 a8083063 Iustin Pop

541 72737a7f Iustin Pop
    """
542 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "instance_run_rename",
543 9a525d83 Michael Hanselmann
                                [self._InstDict(inst), old_name])
544 a8083063 Iustin Pop
545 72737a7f Iustin Pop
  def call_instance_info(self, node, instance, hname):
546 72737a7f Iustin Pop
    """Returns information about a single instance.
547 a8083063 Iustin Pop

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

550 9a525d83 Michael Hanselmann
    @type node: list
551 9a525d83 Michael Hanselmann
    @param node: the list of nodes to query
552 72737a7f Iustin Pop
    @type instance: string
553 72737a7f Iustin Pop
    @param instance: the instance name
554 72737a7f Iustin Pop
    @type hname: string
555 72737a7f Iustin Pop
    @param hname: the hypervisor type of the instance
556 a8083063 Iustin Pop

557 72737a7f Iustin Pop
    """
558 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "instance_info", [instance, hname])
559 e69d05fd Iustin Pop
560 56e7640c Iustin Pop
  def call_instance_migratable(self, node, instance):
561 56e7640c Iustin Pop
    """Checks whether the given instance can be migrated.
562 56e7640c Iustin Pop

563 56e7640c Iustin Pop
    This is a single-node call.
564 56e7640c Iustin Pop

565 56e7640c Iustin Pop
    @param node: the node to query
566 56e7640c Iustin Pop
    @type instance: L{objects.Instance}
567 56e7640c Iustin Pop
    @param instance: the instance to check
568 56e7640c Iustin Pop

569 56e7640c Iustin Pop

570 56e7640c Iustin Pop
    """
571 56e7640c Iustin Pop
    return self._SingleNodeCall(node, "instance_migratable",
572 56e7640c Iustin Pop
                                [self._InstDict(instance)])
573 56e7640c Iustin Pop
574 72737a7f Iustin Pop
  def call_all_instances_info(self, node_list, hypervisor_list):
575 72737a7f Iustin Pop
    """Returns information about all instances on the given nodes.
576 a8083063 Iustin Pop

577 72737a7f Iustin Pop
    This is a multi-node call.
578 a8083063 Iustin Pop

579 72737a7f Iustin Pop
    @type node_list: list
580 72737a7f Iustin Pop
    @param node_list: the list of nodes to query
581 72737a7f Iustin Pop
    @type hypervisor_list: list
582 72737a7f Iustin Pop
    @param hypervisor_list: the hypervisors to query for instances
583 a8083063 Iustin Pop

584 72737a7f Iustin Pop
    """
585 9a525d83 Michael Hanselmann
    return self._MultiNodeCall(node_list, "all_instances_info",
586 9a525d83 Michael Hanselmann
                               [hypervisor_list])
587 e69d05fd Iustin Pop
588 72737a7f Iustin Pop
  def call_instance_list(self, node_list, hypervisor_list):
589 72737a7f Iustin Pop
    """Returns the list of running instances on a given node.
590 a8083063 Iustin Pop

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

593 72737a7f Iustin Pop
    @type node_list: list
594 72737a7f Iustin Pop
    @param node_list: the list of nodes to query
595 72737a7f Iustin Pop
    @type hypervisor_list: list
596 72737a7f Iustin Pop
    @param hypervisor_list: the hypervisors to query for instances
597 16abfbc2 Alexander Schreiber

598 72737a7f Iustin Pop
    """
599 9a525d83 Michael Hanselmann
    return self._MultiNodeCall(node_list, "instance_list", [hypervisor_list])
600 16abfbc2 Alexander Schreiber
601 72737a7f Iustin Pop
  def call_node_tcp_ping(self, node, source, target, port, timeout,
602 72737a7f Iustin Pop
                         live_port_needed):
603 72737a7f Iustin Pop
    """Do a TcpPing on the remote node
604 a8083063 Iustin Pop

605 72737a7f Iustin Pop
    This is a single-node call.
606 caad16e2 Iustin Pop

607 72737a7f Iustin Pop
    """
608 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "node_tcp_ping",
609 9a525d83 Michael Hanselmann
                                [source, target, port, timeout,
610 72737a7f Iustin Pop
                                 live_port_needed])
611 a8083063 Iustin Pop
612 caad16e2 Iustin Pop
  def call_node_has_ip_address(self, node, address):
613 caad16e2 Iustin Pop
    """Checks if a node has the given IP address.
614 caad16e2 Iustin Pop

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

617 caad16e2 Iustin Pop
    """
618 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "node_has_ip_address", [address])
619 a8083063 Iustin Pop
620 72737a7f Iustin Pop
  def call_node_info(self, node_list, vg_name, hypervisor_type):
621 72737a7f Iustin Pop
    """Return node information.
622 e69d05fd Iustin Pop

623 72737a7f Iustin Pop
    This will return memory information and volume group size and free
624 72737a7f Iustin Pop
    space.
625 a8083063 Iustin Pop

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

628 72737a7f Iustin Pop
    @type node_list: list
629 72737a7f Iustin Pop
    @param node_list: the list of nodes to query
630 c41eea6e Iustin Pop
    @type vg_name: C{string}
631 c41eea6e Iustin Pop
    @param vg_name: the name of the volume group to ask for disk space
632 72737a7f Iustin Pop
        information
633 72737a7f Iustin Pop
    @type hypervisor_type: C{str}
634 72737a7f Iustin Pop
    @param hypervisor_type: the name of the hypervisor to ask for
635 72737a7f Iustin Pop
        memory information
636 a8083063 Iustin Pop

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

661 72737a7f Iustin Pop
    This is a single-node call.
662 a8083063 Iustin Pop

663 72737a7f Iustin Pop
    """
664 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "node_add",
665 9a525d83 Michael Hanselmann
                                [dsa, dsapub, rsa, rsapub, ssh, sshpub])
666 a8083063 Iustin Pop
667 72737a7f Iustin Pop
  def call_node_verify(self, node_list, checkdict, cluster_name):
668 72737a7f Iustin Pop
    """Request verification of given parameters.
669 a8083063 Iustin Pop

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

672 72737a7f Iustin Pop
    """
673 9a525d83 Michael Hanselmann
    return self._MultiNodeCall(node_list, "node_verify",
674 9a525d83 Michael Hanselmann
                               [checkdict, cluster_name])
675 a8083063 Iustin Pop
676 9a525d83 Michael Hanselmann
  @classmethod
677 9a525d83 Michael Hanselmann
  def call_node_start_master(cls, node, start_daemons):
678 72737a7f Iustin Pop
    """Tells a node to activate itself as a master.
679 a8083063 Iustin Pop

680 72737a7f Iustin Pop
    This is a single-node call.
681 a8083063 Iustin Pop

682 72737a7f Iustin Pop
    """
683 9a525d83 Michael Hanselmann
    return cls._StaticSingleNodeCall(node, "node_start_master",
684 9a525d83 Michael Hanselmann
                                     [start_daemons])
685 a8083063 Iustin Pop
686 9a525d83 Michael Hanselmann
  @classmethod
687 9a525d83 Michael Hanselmann
  def call_node_stop_master(cls, node, stop_daemons):
688 72737a7f Iustin Pop
    """Tells a node to demote itself from master status.
689 a8083063 Iustin Pop

690 72737a7f Iustin Pop
    This is a single-node call.
691 4e071d3b Iustin Pop

692 72737a7f Iustin Pop
    """
693 9a525d83 Michael Hanselmann
    return cls._StaticSingleNodeCall(node, "node_stop_master", [stop_daemons])
694 4e071d3b Iustin Pop
695 9a525d83 Michael Hanselmann
  @classmethod
696 9a525d83 Michael Hanselmann
  def call_master_info(cls, node_list):
697 72737a7f Iustin Pop
    """Query master info.
698 4e071d3b Iustin Pop

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

701 72737a7f Iustin Pop
    """
702 72737a7f Iustin Pop
    # TODO: should this method query down nodes?
703 9a525d83 Michael Hanselmann
    return cls._StaticMultiNodeCall(node_list, "master_info", [])
704 a8083063 Iustin Pop
705 72737a7f Iustin Pop
  def call_version(self, node_list):
706 72737a7f Iustin Pop
    """Query node version.
707 a8083063 Iustin Pop

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

710 72737a7f Iustin Pop
    """
711 9a525d83 Michael Hanselmann
    return self._MultiNodeCall(node_list, "version", [])
712 a8083063 Iustin Pop
713 72737a7f Iustin Pop
  def call_blockdev_create(self, node, bdev, size, owner, on_primary, info):
714 72737a7f Iustin Pop
    """Request creation of a given block device.
715 a8083063 Iustin Pop

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

718 72737a7f Iustin Pop
    """
719 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "blockdev_create",
720 9a525d83 Michael Hanselmann
                                [bdev.ToDict(), size, owner, on_primary, info])
721 a8083063 Iustin Pop
722 72737a7f Iustin Pop
  def call_blockdev_remove(self, node, bdev):
723 72737a7f Iustin Pop
    """Request removal of a given block device.
724 a8083063 Iustin Pop

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

727 72737a7f Iustin Pop
    """
728 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "blockdev_remove", [bdev.ToDict()])
729 f3e513ad Iustin Pop
730 72737a7f Iustin Pop
  def call_blockdev_rename(self, node, devlist):
731 72737a7f Iustin Pop
    """Request rename of the given block devices.
732 f3e513ad Iustin Pop

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

735 72737a7f Iustin Pop
    """
736 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "blockdev_rename",
737 9a525d83 Michael Hanselmann
                                [(d.ToDict(), uid) for d, uid in devlist])
738 a8083063 Iustin Pop
739 72737a7f Iustin Pop
  def call_blockdev_assemble(self, node, disk, owner, on_primary):
740 72737a7f Iustin Pop
    """Request assembling of a given block device.
741 a8083063 Iustin Pop

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

744 72737a7f Iustin Pop
    """
745 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "blockdev_assemble",
746 9a525d83 Michael Hanselmann
                                [disk.ToDict(), owner, on_primary])
747 a8083063 Iustin Pop
748 72737a7f Iustin Pop
  def call_blockdev_shutdown(self, node, disk):
749 72737a7f Iustin Pop
    """Request shutdown of a given block device.
750 a8083063 Iustin Pop

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

753 72737a7f Iustin Pop
    """
754 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "blockdev_shutdown", [disk.ToDict()])
755 a8083063 Iustin Pop
756 72737a7f Iustin Pop
  def call_blockdev_addchildren(self, node, bdev, ndevs):
757 72737a7f Iustin Pop
    """Request adding a list of children to a (mirroring) 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_addchildren",
763 9a525d83 Michael Hanselmann
                                [bdev.ToDict(),
764 9a525d83 Michael Hanselmann
                                 [disk.ToDict() for disk in ndevs]])
765 a8083063 Iustin Pop
766 72737a7f Iustin Pop
  def call_blockdev_removechildren(self, node, bdev, ndevs):
767 72737a7f Iustin Pop
    """Request removing a list of children from a (mirroring) device.
768 a8083063 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_removechildren",
773 9a525d83 Michael Hanselmann
                                [bdev.ToDict(),
774 9a525d83 Michael Hanselmann
                                 [disk.ToDict() for disk in ndevs]])
775 a8083063 Iustin Pop
776 72737a7f Iustin Pop
  def call_blockdev_getmirrorstatus(self, node, disks):
777 72737a7f Iustin Pop
    """Request status of a (mirroring) device.
778 a8083063 Iustin Pop

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

781 72737a7f Iustin Pop
    """
782 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "blockdev_getmirrorstatus",
783 9a525d83 Michael Hanselmann
                                [dsk.ToDict() for dsk in disks])
784 a8083063 Iustin Pop
785 72737a7f Iustin Pop
  def call_blockdev_find(self, node, disk):
786 72737a7f Iustin Pop
    """Request identification of a given block device.
787 72737a7f Iustin Pop

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

790 72737a7f Iustin Pop
    """
791 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "blockdev_find", [disk.ToDict()])
792 d61cbe76 Iustin Pop
793 b2e7666a Iustin Pop
  def call_blockdev_close(self, node, instance_name, disks):
794 72737a7f Iustin Pop
    """Closes the given block devices.
795 d61cbe76 Iustin Pop

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

798 72737a7f Iustin Pop
    """
799 b2e7666a Iustin Pop
    params = [instance_name, [cf.ToDict() for cf in disks]]
800 b2e7666a Iustin Pop
    return self._SingleNodeCall(node, "blockdev_close", params)
801 a8083063 Iustin Pop
802 6b93ec9d Iustin Pop
  def call_drbd_disconnect_net(self, node_list, nodes_ip, disks):
803 6b93ec9d Iustin Pop
    """Disconnects the network of the given drbd devices.
804 6b93ec9d Iustin Pop

805 6b93ec9d Iustin Pop
    This is a multi-node call.
806 6b93ec9d Iustin Pop

807 6b93ec9d Iustin Pop
    """
808 6b93ec9d Iustin Pop
    return self._MultiNodeCall(node_list, "drbd_disconnect_net",
809 6b93ec9d Iustin Pop
                               [nodes_ip, [cf.ToDict() for cf in disks]])
810 6b93ec9d Iustin Pop
811 6b93ec9d Iustin Pop
  def call_drbd_attach_net(self, node_list, nodes_ip,
812 6b93ec9d Iustin Pop
                           disks, instance_name, multimaster):
813 6b93ec9d Iustin Pop
    """Disconnects the given drbd devices.
814 6b93ec9d Iustin Pop

815 6b93ec9d Iustin Pop
    This is a multi-node call.
816 6b93ec9d Iustin Pop

817 6b93ec9d Iustin Pop
    """
818 6b93ec9d Iustin Pop
    return self._MultiNodeCall(node_list, "drbd_attach_net",
819 6b93ec9d Iustin Pop
                               [nodes_ip, [cf.ToDict() for cf in disks],
820 6b93ec9d Iustin Pop
                                instance_name, multimaster])
821 6b93ec9d Iustin Pop
822 6b93ec9d Iustin Pop
  def call_drbd_wait_sync(self, node_list, nodes_ip, disks):
823 6b93ec9d Iustin Pop
    """Waits for the synchronization of drbd devices is complete.
824 6b93ec9d Iustin Pop

825 6b93ec9d Iustin Pop
    This is a multi-node call.
826 6b93ec9d Iustin Pop

827 6b93ec9d Iustin Pop
    """
828 6b93ec9d Iustin Pop
    return self._MultiNodeCall(node_list, "drbd_wait_sync",
829 6b93ec9d Iustin Pop
                               [nodes_ip, [cf.ToDict() for cf in disks]])
830 6b93ec9d Iustin Pop
831 9a525d83 Michael Hanselmann
  @classmethod
832 9a525d83 Michael Hanselmann
  def call_upload_file(cls, node_list, file_name, address_list=None):
833 72737a7f Iustin Pop
    """Upload a file.
834 72737a7f Iustin Pop

835 72737a7f Iustin Pop
    The node will refuse the operation in case the file is not on the
836 72737a7f Iustin Pop
    approved file list.
837 72737a7f Iustin Pop

838 72737a7f Iustin Pop
    This is a multi-node call.
839 a8083063 Iustin Pop

840 6b294c53 Iustin Pop
    @type node_list: list
841 6b294c53 Iustin Pop
    @param node_list: the list of node names to upload to
842 6b294c53 Iustin Pop
    @type file_name: str
843 6b294c53 Iustin Pop
    @param file_name: the filename to upload
844 6b294c53 Iustin Pop
    @type address_list: list or None
845 6b294c53 Iustin Pop
    @keyword address_list: an optional list of node addresses, in order
846 6b294c53 Iustin Pop
        to optimize the RPC speed
847 6b294c53 Iustin Pop

848 72737a7f Iustin Pop
    """
849 12bce260 Michael Hanselmann
    file_contents = utils.ReadFile(file_name)
850 12bce260 Michael Hanselmann
    data = cls._Compress(file_contents)
851 72737a7f Iustin Pop
    st = os.stat(file_name)
852 72737a7f Iustin Pop
    params = [file_name, data, st.st_mode, st.st_uid, st.st_gid,
853 72737a7f Iustin Pop
              st.st_atime, st.st_mtime]
854 9a525d83 Michael Hanselmann
    return cls._StaticMultiNodeCall(node_list, "upload_file", params,
855 9a525d83 Michael Hanselmann
                                    address_list=address_list)
856 72737a7f Iustin Pop
857 6ddc95ec Michael Hanselmann
  @classmethod
858 03d1dba2 Michael Hanselmann
  def call_write_ssconf_files(cls, node_list, values):
859 6ddc95ec Michael Hanselmann
    """Write ssconf files.
860 6ddc95ec Michael Hanselmann

861 6ddc95ec Michael Hanselmann
    This is a multi-node call.
862 6ddc95ec Michael Hanselmann

863 6ddc95ec Michael Hanselmann
    """
864 03d1dba2 Michael Hanselmann
    return cls._StaticMultiNodeCall(node_list, "write_ssconf_files", [values])
865 6ddc95ec Michael Hanselmann
866 72737a7f Iustin Pop
  def call_os_diagnose(self, node_list):
867 72737a7f Iustin Pop
    """Request a diagnose of OS definitions.
868 72737a7f Iustin Pop

869 72737a7f Iustin Pop
    This is a multi-node call.
870 a8083063 Iustin Pop

871 72737a7f Iustin Pop
    """
872 9a525d83 Michael Hanselmann
    result = self._MultiNodeCall(node_list, "os_diagnose", [])
873 9a525d83 Michael Hanselmann
874 fab1e3a4 Iustin Pop
    for node_result in result.values():
875 781de953 Iustin Pop
      if not node_result.failed and node_result.data:
876 781de953 Iustin Pop
        node_result.data = [objects.OS.FromDict(oss)
877 781de953 Iustin Pop
                            for oss in node_result.data]
878 781de953 Iustin Pop
    return result
879 a8083063 Iustin Pop
880 72737a7f Iustin Pop
  def call_os_get(self, node, name):
881 72737a7f Iustin Pop
    """Returns an OS definition.
882 a8083063 Iustin Pop

883 72737a7f Iustin Pop
    This is a single-node call.
884 a8083063 Iustin Pop

885 72737a7f Iustin Pop
    """
886 9a525d83 Michael Hanselmann
    result = self._SingleNodeCall(node, "os_get", [name])
887 781de953 Iustin Pop
    if not result.failed and isinstance(result.data, dict):
888 781de953 Iustin Pop
      result.data = objects.OS.FromDict(result.data)
889 781de953 Iustin Pop
    return result
890 a8083063 Iustin Pop
891 72737a7f Iustin Pop
  def call_hooks_runner(self, node_list, hpath, phase, env):
892 72737a7f Iustin Pop
    """Call the hooks runner.
893 a8083063 Iustin Pop

894 72737a7f Iustin Pop
    Args:
895 72737a7f Iustin Pop
      - op: the OpCode instance
896 72737a7f Iustin Pop
      - env: a dictionary with the environment
897 a8083063 Iustin Pop

898 72737a7f Iustin Pop
    This is a multi-node call.
899 a8083063 Iustin Pop

900 72737a7f Iustin Pop
    """
901 72737a7f Iustin Pop
    params = [hpath, phase, env]
902 9a525d83 Michael Hanselmann
    return self._MultiNodeCall(node_list, "hooks_runner", params)
903 a8083063 Iustin Pop
904 72737a7f Iustin Pop
  def call_iallocator_runner(self, node, name, idata):
905 72737a7f Iustin Pop
    """Call an iallocator on a remote node
906 8d528b7c Iustin Pop

907 72737a7f Iustin Pop
    Args:
908 72737a7f Iustin Pop
      - name: the iallocator name
909 72737a7f Iustin Pop
      - input: the json-encoded input string
910 8d528b7c Iustin Pop

911 72737a7f Iustin Pop
    This is a single-node call.
912 8d528b7c Iustin Pop

913 72737a7f Iustin Pop
    """
914 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "iallocator_runner", [name, idata])
915 8d528b7c Iustin Pop
916 72737a7f Iustin Pop
  def call_blockdev_grow(self, node, cf_bdev, amount):
917 72737a7f Iustin Pop
    """Request a snapshot of the given block device.
918 4c8ba8b3 Iustin Pop

919 72737a7f Iustin Pop
    This is a single-node call.
920 4c8ba8b3 Iustin Pop

921 72737a7f Iustin Pop
    """
922 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "blockdev_grow",
923 9a525d83 Michael Hanselmann
                                [cf_bdev.ToDict(), amount])
924 4c8ba8b3 Iustin Pop
925 72737a7f Iustin Pop
  def call_blockdev_snapshot(self, node, cf_bdev):
926 72737a7f Iustin Pop
    """Request a snapshot of the given block device.
927 a8083063 Iustin Pop

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

930 72737a7f Iustin Pop
    """
931 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "blockdev_snapshot", [cf_bdev.ToDict()])
932 a8083063 Iustin Pop
933 72737a7f Iustin Pop
  def call_snapshot_export(self, node, snap_bdev, dest_node, instance,
934 74c47259 Iustin Pop
                           cluster_name, idx):
935 72737a7f Iustin Pop
    """Request the export of a given snapshot.
936 a8083063 Iustin Pop

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

939 72737a7f Iustin Pop
    """
940 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "snapshot_export",
941 9a525d83 Michael Hanselmann
                                [snap_bdev.ToDict(), dest_node,
942 9a525d83 Michael Hanselmann
                                 self._InstDict(instance), cluster_name, idx])
943 a8083063 Iustin Pop
944 72737a7f Iustin Pop
  def call_finalize_export(self, node, instance, snap_disks):
945 72737a7f Iustin Pop
    """Request the completion of an export operation.
946 a8083063 Iustin Pop

947 72737a7f Iustin Pop
    This writes the export config file, etc.
948 a8083063 Iustin Pop

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

951 72737a7f Iustin Pop
    """
952 72737a7f Iustin Pop
    flat_disks = []
953 72737a7f Iustin Pop
    for disk in snap_disks:
954 72737a7f Iustin Pop
      flat_disks.append(disk.ToDict())
955 9a525d83 Michael Hanselmann
956 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "finalize_export",
957 9a525d83 Michael Hanselmann
                                [self._InstDict(instance), flat_disks])
958 a8083063 Iustin Pop
959 72737a7f Iustin Pop
  def call_export_info(self, node, path):
960 72737a7f Iustin Pop
    """Queries the export information in a given path.
961 a8083063 Iustin Pop

962 72737a7f Iustin Pop
    This is a single-node call.
963 a8083063 Iustin Pop

964 72737a7f Iustin Pop
    """
965 9a525d83 Michael Hanselmann
    result = self._SingleNodeCall(node, "export_info", [path])
966 781de953 Iustin Pop
    if not result.failed and result.data:
967 781de953 Iustin Pop
      result.data = objects.SerializableConfigParser.Loads(str(result.data))
968 781de953 Iustin Pop
    return result
969 a8083063 Iustin Pop
970 6c0af70e Guido Trotter
  def call_instance_os_import(self, node, inst, src_node, src_images,
971 6c0af70e Guido Trotter
                              cluster_name):
972 72737a7f Iustin Pop
    """Request the import of a backup into an instance.
973 a8083063 Iustin Pop

974 72737a7f Iustin Pop
    This is a single-node call.
975 a8083063 Iustin Pop

976 72737a7f Iustin Pop
    """
977 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "instance_os_import",
978 9a525d83 Michael Hanselmann
                                [self._InstDict(inst), src_node, src_images,
979 9a525d83 Michael Hanselmann
                                 cluster_name])
980 a8083063 Iustin Pop
981 72737a7f Iustin Pop
  def call_export_list(self, node_list):
982 72737a7f Iustin Pop
    """Gets the stored exports list.
983 a8083063 Iustin Pop

984 72737a7f Iustin Pop
    This is a multi-node call.
985 a8083063 Iustin Pop

986 72737a7f Iustin Pop
    """
987 9a525d83 Michael Hanselmann
    return self._MultiNodeCall(node_list, "export_list", [])
988 a8083063 Iustin Pop
989 72737a7f Iustin Pop
  def call_export_remove(self, node, export):
990 72737a7f Iustin Pop
    """Requests removal of a given export.
991 a8083063 Iustin Pop

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

994 72737a7f Iustin Pop
    """
995 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "export_remove", [export])
996 a8083063 Iustin Pop
997 9a525d83 Michael Hanselmann
  @classmethod
998 9a525d83 Michael Hanselmann
  def call_node_leave_cluster(cls, node):
999 72737a7f Iustin Pop
    """Requests a node to clean the cluster information it has.
1000 a8083063 Iustin Pop

1001 72737a7f Iustin Pop
    This will remove the configuration information from the ganeti data
1002 72737a7f Iustin Pop
    dir.
1003 a8083063 Iustin Pop

1004 72737a7f Iustin Pop
    This is a single-node call.
1005 a8083063 Iustin Pop

1006 72737a7f Iustin Pop
    """
1007 9a525d83 Michael Hanselmann
    return cls._StaticSingleNodeCall(node, "node_leave_cluster", [])
1008 dcb93971 Michael Hanselmann
1009 72737a7f Iustin Pop
  def call_node_volumes(self, node_list):
1010 72737a7f Iustin Pop
    """Gets all volumes on node(s).
1011 dcb93971 Michael Hanselmann

1012 72737a7f Iustin Pop
    This is a multi-node call.
1013 dcb93971 Michael Hanselmann

1014 72737a7f Iustin Pop
    """
1015 9a525d83 Michael Hanselmann
    return self._MultiNodeCall(node_list, "node_volumes", [])
1016 06009e27 Iustin Pop
1017 56aa9fd5 Iustin Pop
  def call_node_demote_from_mc(self, node):
1018 56aa9fd5 Iustin Pop
    """Demote a node from the master candidate role.
1019 56aa9fd5 Iustin Pop

1020 56aa9fd5 Iustin Pop
    This is a single-node call.
1021 56aa9fd5 Iustin Pop

1022 56aa9fd5 Iustin Pop
    """
1023 56aa9fd5 Iustin Pop
    return self._SingleNodeCall(node, "node_demote_from_mc", [])
1024 56aa9fd5 Iustin Pop
1025 72737a7f Iustin Pop
  def call_test_delay(self, node_list, duration):
1026 72737a7f Iustin Pop
    """Sleep for a fixed time on given node(s).
1027 06009e27 Iustin Pop

1028 72737a7f Iustin Pop
    This is a multi-node call.
1029 06009e27 Iustin Pop

1030 72737a7f Iustin Pop
    """
1031 9a525d83 Michael Hanselmann
    return self._MultiNodeCall(node_list, "test_delay", [duration])
1032 5e04ed8b Manuel Franceschini
1033 72737a7f Iustin Pop
  def call_file_storage_dir_create(self, node, file_storage_dir):
1034 72737a7f Iustin Pop
    """Create the given file storage directory.
1035 5e04ed8b Manuel Franceschini

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

1038 72737a7f Iustin Pop
    """
1039 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "file_storage_dir_create",
1040 9a525d83 Michael Hanselmann
                                [file_storage_dir])
1041 5e04ed8b Manuel Franceschini
1042 72737a7f Iustin Pop
  def call_file_storage_dir_remove(self, node, file_storage_dir):
1043 72737a7f Iustin Pop
    """Remove the given file storage directory.
1044 5e04ed8b Manuel Franceschini

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

1047 72737a7f Iustin Pop
    """
1048 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "file_storage_dir_remove",
1049 9a525d83 Michael Hanselmann
                                [file_storage_dir])
1050 5e04ed8b Manuel Franceschini
1051 72737a7f Iustin Pop
  def call_file_storage_dir_rename(self, node, old_file_storage_dir,
1052 72737a7f Iustin Pop
                                   new_file_storage_dir):
1053 72737a7f Iustin Pop
    """Rename file storage directory.
1054 5e04ed8b Manuel Franceschini

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

1057 72737a7f Iustin Pop
    """
1058 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "file_storage_dir_rename",
1059 9a525d83 Michael Hanselmann
                                [old_file_storage_dir, new_file_storage_dir])
1060 ca52cdeb Michael Hanselmann
1061 9a525d83 Michael Hanselmann
  @classmethod
1062 9a525d83 Michael Hanselmann
  def call_jobqueue_update(cls, node_list, address_list, file_name, content):
1063 72737a7f Iustin Pop
    """Update job queue.
1064 ca52cdeb Michael Hanselmann

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

1067 72737a7f Iustin Pop
    """
1068 9a525d83 Michael Hanselmann
    return cls._StaticMultiNodeCall(node_list, "jobqueue_update",
1069 12bce260 Michael Hanselmann
                                    [file_name, cls._Compress(content)],
1070 9a525d83 Michael Hanselmann
                                    address_list=address_list)
1071 ca52cdeb Michael Hanselmann
1072 9a525d83 Michael Hanselmann
  @classmethod
1073 9a525d83 Michael Hanselmann
  def call_jobqueue_purge(cls, node):
1074 72737a7f Iustin Pop
    """Purge job queue.
1075 ca52cdeb Michael Hanselmann

1076 72737a7f Iustin Pop
    This is a single-node call.
1077 ca52cdeb Michael Hanselmann

1078 72737a7f Iustin Pop
    """
1079 9a525d83 Michael Hanselmann
    return cls._StaticSingleNodeCall(node, "jobqueue_purge", [])
1080 af5ebcb1 Michael Hanselmann
1081 9a525d83 Michael Hanselmann
  @classmethod
1082 dd875d32 Michael Hanselmann
  def call_jobqueue_rename(cls, node_list, address_list, rename):
1083 72737a7f Iustin Pop
    """Rename a job queue file.
1084 af5ebcb1 Michael Hanselmann

1085 72737a7f Iustin Pop
    This is a multi-node call.
1086 af5ebcb1 Michael Hanselmann

1087 72737a7f Iustin Pop
    """
1088 dd875d32 Michael Hanselmann
    return cls._StaticMultiNodeCall(node_list, "jobqueue_rename", rename,
1089 9a525d83 Michael Hanselmann
                                    address_list=address_list)
1090 6217e295 Iustin Pop
1091 9a525d83 Michael Hanselmann
  @classmethod
1092 9a525d83 Michael Hanselmann
  def call_jobqueue_set_drain(cls, node_list, drain_flag):
1093 5d672980 Iustin Pop
    """Set the drain flag on the queue.
1094 5d672980 Iustin Pop

1095 5d672980 Iustin Pop
    This is a multi-node call.
1096 5d672980 Iustin Pop

1097 5d672980 Iustin Pop
    @type node_list: list
1098 5d672980 Iustin Pop
    @param node_list: the list of nodes to query
1099 5d672980 Iustin Pop
    @type drain_flag: bool
1100 5d672980 Iustin Pop
    @param drain_flag: if True, will set the drain flag, otherwise reset it.
1101 5d672980 Iustin Pop

1102 5d672980 Iustin Pop
    """
1103 9a525d83 Michael Hanselmann
    return cls._StaticMultiNodeCall(node_list, "jobqueue_set_drain",
1104 9a525d83 Michael Hanselmann
                                    [drain_flag])
1105 5d672980 Iustin Pop
1106 6217e295 Iustin Pop
  def call_hypervisor_validate_params(self, node_list, hvname, hvparams):
1107 6217e295 Iustin Pop
    """Validate the hypervisor params.
1108 6217e295 Iustin Pop

1109 6217e295 Iustin Pop
    This is a multi-node call.
1110 6217e295 Iustin Pop

1111 6217e295 Iustin Pop
    @type node_list: list
1112 6217e295 Iustin Pop
    @param node_list: the list of nodes to query
1113 6217e295 Iustin Pop
    @type hvname: string
1114 6217e295 Iustin Pop
    @param hvname: the hypervisor name
1115 6217e295 Iustin Pop
    @type hvparams: dict
1116 6217e295 Iustin Pop
    @param hvparams: the hypervisor parameters to be validated
1117 6217e295 Iustin Pop

1118 6217e295 Iustin Pop
    """
1119 6217e295 Iustin Pop
    cluster = self._cfg.GetClusterInfo()
1120 6217e295 Iustin Pop
    hv_full = cluster.FillDict(cluster.hvparams.get(hvname, {}), hvparams)
1121 9a525d83 Michael Hanselmann
    return self._MultiNodeCall(node_list, "hypervisor_validate_params",
1122 9a525d83 Michael Hanselmann
                               [hvname, hv_full])