Statistics
| Branch: | Tag: | Revision:

root / lib / rpc.py @ 2a21bc88

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 ed83f5cc Iustin Pop
      self.data = None
108 ed83f5cc Iustin Pop
    elif failed:
109 781de953 Iustin Pop
      self.error = data
110 781de953 Iustin Pop
      self.data = None
111 781de953 Iustin Pop
    else:
112 781de953 Iustin Pop
      self.data = data
113 781de953 Iustin Pop
      self.error = None
114 781de953 Iustin Pop
115 781de953 Iustin Pop
  def Raise(self):
116 781de953 Iustin Pop
    """If the result has failed, raise an OpExecError.
117 781de953 Iustin Pop

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

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

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

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

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

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

160 a8083063 Iustin Pop
  One current bug is that generic failure is still signalled by
161 a8083063 Iustin Pop
  'False' result, which is not good. This overloading of values can
162 a8083063 Iustin Pop
  cause bugs.
163 a8083063 Iustin Pop

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

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

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

196 bdf7d8c0 Iustin Pop
    @type name: str
197 bdf7d8c0 Iustin Pop
    @param name: the node name
198 bdf7d8c0 Iustin Pop
    @type address: str
199 bdf7d8c0 Iustin Pop
    @keyword address: the node address, if known
200 bdf7d8c0 Iustin Pop

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

215 ecfe9491 Michael Hanselmann
    @rtype: list
216 ecfe9491 Michael Hanselmann
    @returns: List of RPC results
217 a8083063 Iustin Pop

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

251 72737a7f Iustin Pop
    @type cfg:  C{config.ConfigWriter}
252 72737a7f Iustin Pop
    @param cfg: the configuration object that will be used to get data
253 72737a7f Iustin Pop
                about the cluster
254 a8083063 Iustin Pop

255 72737a7f Iustin Pop
    """
256 72737a7f Iustin Pop
    self._cfg = cfg
257 160e2921 Iustin Pop
    self.port = utils.GetNodeDaemonPort()
258 a8083063 Iustin Pop
259 26ba2bd8 Iustin Pop
  def _InstDict(self, instance):
260 26ba2bd8 Iustin Pop
    """Convert the given instance to a dict.
261 26ba2bd8 Iustin Pop

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

265 26ba2bd8 Iustin Pop
    @type instance: L{objects.Instance}
266 26ba2bd8 Iustin Pop
    @param instance: an Instance object
267 26ba2bd8 Iustin Pop
    @rtype: dict
268 26ba2bd8 Iustin Pop
    @return: the instance dict, with the hvparams filled with the
269 26ba2bd8 Iustin Pop
        cluster defaults
270 26ba2bd8 Iustin Pop

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

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

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

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

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

332 160e2921 Iustin Pop
    """
333 160e2921 Iustin Pop
    body = serializer.DumpJson(args, indent=False)
334 160e2921 Iustin Pop
    c = Client(procedure, body, self.port)
335 84b45587 Iustin Pop
    skip_dict = self._ConnectList(c, node_list, procedure)
336 ed83f5cc Iustin Pop
    skip_dict.update(c.GetResults())
337 ed83f5cc Iustin Pop
    return skip_dict
338 9a525d83 Michael Hanselmann
339 9a525d83 Michael Hanselmann
  @classmethod
340 9a525d83 Michael Hanselmann
  def _StaticMultiNodeCall(cls, node_list, procedure, args,
341 9a525d83 Michael Hanselmann
                           address_list=None):
342 160e2921 Iustin Pop
    """Helper for making a multi-node static 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, utils.GetNodeDaemonPort())
347 9a525d83 Michael Hanselmann
    c.ConnectList(node_list, address_list=address_list)
348 9a525d83 Michael Hanselmann
    return c.GetResults()
349 9a525d83 Michael Hanselmann
350 9a525d83 Michael Hanselmann
  def _SingleNodeCall(self, node, procedure, args):
351 160e2921 Iustin Pop
    """Helper for making a single-node call
352 9a525d83 Michael Hanselmann

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

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

376 12bce260 Michael Hanselmann
    Small amounts of data are not compressed.
377 12bce260 Michael Hanselmann

378 12bce260 Michael Hanselmann
    @type data: str
379 12bce260 Michael Hanselmann
    @param data: Data
380 12bce260 Michael Hanselmann
    @rtype: tuple
381 12bce260 Michael Hanselmann
    @return: Encoded data to send
382 12bce260 Michael Hanselmann

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

399 72737a7f Iustin Pop
    This is a multi-node call.
400 a8083063 Iustin Pop

401 72737a7f Iustin Pop
    """
402 9a525d83 Michael Hanselmann
    return self._MultiNodeCall(node_list, "volume_list", [vg_name])
403 a8083063 Iustin Pop
404 72737a7f Iustin Pop
  def call_vg_list(self, node_list):
405 72737a7f Iustin Pop
    """Gets the volume group list.
406 a8083063 Iustin Pop

407 72737a7f Iustin Pop
    This is a multi-node call.
408 a8083063 Iustin Pop

409 72737a7f Iustin Pop
    """
410 9a525d83 Michael Hanselmann
    return self._MultiNodeCall(node_list, "vg_list", [])
411 a8083063 Iustin Pop
412 72737a7f Iustin Pop
  def call_bridges_exist(self, node, bridges_list):
413 72737a7f Iustin Pop
    """Checks if a node has all the bridges given.
414 a8083063 Iustin Pop

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

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

421 72737a7f Iustin Pop
    """
422 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "bridges_exist", [bridges_list])
423 a8083063 Iustin Pop
424 72737a7f Iustin Pop
  def call_instance_start(self, node, instance, extra_args):
425 72737a7f Iustin Pop
    """Starts an instance.
426 a8083063 Iustin Pop

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

429 72737a7f Iustin Pop
    """
430 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "instance_start",
431 9a525d83 Michael Hanselmann
                                [self._InstDict(instance), extra_args])
432 a8083063 Iustin Pop
433 72737a7f Iustin Pop
  def call_instance_shutdown(self, node, instance):
434 72737a7f Iustin Pop
    """Stops an instance.
435 a8083063 Iustin Pop

436 72737a7f Iustin Pop
    This is a single-node call.
437 2a10865c Iustin Pop

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

445 6906a9d8 Guido Trotter
    This is a single-node call.
446 6906a9d8 Guido Trotter

447 6906a9d8 Guido Trotter
    @type node: string
448 6906a9d8 Guido Trotter
    @param node: the node on which the instance is currently running
449 6906a9d8 Guido Trotter
    @type instance: C{objects.Instance}
450 6906a9d8 Guido Trotter
    @param instance: the instance definition
451 6906a9d8 Guido Trotter

452 6906a9d8 Guido Trotter
    """
453 6906a9d8 Guido Trotter
    return self._SingleNodeCall(node, "migration_info",
454 6906a9d8 Guido Trotter
                                [self._InstDict(instance)])
455 6906a9d8 Guido Trotter
456 6906a9d8 Guido Trotter
  def call_accept_instance(self, node, instance, info, target):
457 6906a9d8 Guido Trotter
    """Prepare a node to accept an instance.
458 6906a9d8 Guido Trotter

459 6906a9d8 Guido Trotter
    This is a single-node call.
460 6906a9d8 Guido Trotter

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

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

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

480 6906a9d8 Guido Trotter
    This is a single-node call.
481 6906a9d8 Guido Trotter

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

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

498 72737a7f Iustin Pop
    This is a single-node call.
499 2a10865c Iustin Pop

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

510 72737a7f Iustin Pop
    """
511 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "instance_migrate",
512 9a525d83 Michael Hanselmann
                                [self._InstDict(instance), target, live])
513 007a2f3e Alexander Schreiber
514 72737a7f Iustin Pop
  def call_instance_reboot(self, node, instance, reboot_type, extra_args):
515 72737a7f Iustin Pop
    """Reboots an instance.
516 007a2f3e Alexander Schreiber

517 72737a7f Iustin Pop
    This is a single-node call.
518 a8083063 Iustin Pop

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

527 72737a7f Iustin Pop
    This is a single-node call.
528 decd5f45 Iustin Pop

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

536 72737a7f Iustin Pop
    This is a single-node call.
537 a8083063 Iustin Pop

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

545 72737a7f Iustin Pop
    This is a single-node call.
546 a8083063 Iustin Pop

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

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

560 56e7640c Iustin Pop
    This is a single-node call.
561 56e7640c Iustin Pop

562 56e7640c Iustin Pop
    @param node: the node to query
563 56e7640c Iustin Pop
    @type instance: L{objects.Instance}
564 56e7640c Iustin Pop
    @param instance: the instance to check
565 56e7640c Iustin Pop

566 56e7640c Iustin Pop

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

574 72737a7f Iustin Pop
    This is a multi-node call.
575 a8083063 Iustin Pop

576 72737a7f Iustin Pop
    @type node_list: list
577 72737a7f Iustin Pop
    @param node_list: the list of nodes to query
578 72737a7f Iustin Pop
    @type hypervisor_list: list
579 72737a7f Iustin Pop
    @param hypervisor_list: the hypervisors to query for instances
580 a8083063 Iustin Pop

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

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

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

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

602 72737a7f Iustin Pop
    This is a single-node call.
603 caad16e2 Iustin Pop

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

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

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

620 72737a7f Iustin Pop
    This will return memory information and volume group size and free
621 72737a7f Iustin Pop
    space.
622 a8083063 Iustin Pop

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

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

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

658 72737a7f Iustin Pop
    This is a single-node call.
659 a8083063 Iustin Pop

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

667 72737a7f Iustin Pop
    This is a multi-node call.
668 a8083063 Iustin Pop

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

677 72737a7f Iustin Pop
    This is a single-node call.
678 a8083063 Iustin Pop

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

687 72737a7f Iustin Pop
    This is a single-node call.
688 4e071d3b Iustin Pop

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

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

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

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

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

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

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

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

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

730 72737a7f Iustin Pop
    This is a single-node call.
731 a8083063 Iustin Pop

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

739 72737a7f Iustin Pop
    This is a single-node call.
740 a8083063 Iustin Pop

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

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

750 72737a7f Iustin Pop
    """
751 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "blockdev_shutdown", [disk.ToDict()])
752 a8083063 Iustin Pop
753 72737a7f Iustin Pop
  def call_blockdev_addchildren(self, node, bdev, ndevs):
754 72737a7f Iustin Pop
    """Request adding a list of children to a (mirroring) device.
755 a8083063 Iustin Pop

756 72737a7f Iustin Pop
    This is a single-node call.
757 a8083063 Iustin Pop

758 72737a7f Iustin Pop
    """
759 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "blockdev_addchildren",
760 9a525d83 Michael Hanselmann
                                [bdev.ToDict(),
761 9a525d83 Michael Hanselmann
                                 [disk.ToDict() for disk in ndevs]])
762 a8083063 Iustin Pop
763 72737a7f Iustin Pop
  def call_blockdev_removechildren(self, node, bdev, ndevs):
764 72737a7f Iustin Pop
    """Request removing a list of children from a (mirroring) device.
765 a8083063 Iustin Pop

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

768 72737a7f Iustin Pop
    """
769 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "blockdev_removechildren",
770 9a525d83 Michael Hanselmann
                                [bdev.ToDict(),
771 9a525d83 Michael Hanselmann
                                 [disk.ToDict() for disk in ndevs]])
772 a8083063 Iustin Pop
773 72737a7f Iustin Pop
  def call_blockdev_getmirrorstatus(self, node, disks):
774 72737a7f Iustin Pop
    """Request status of a (mirroring) device.
775 a8083063 Iustin Pop

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

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

785 72737a7f Iustin Pop
    This is a single-node call.
786 a8083063 Iustin Pop

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

793 72737a7f Iustin Pop
    This is a single-node call.
794 d61cbe76 Iustin Pop

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

802 6b93ec9d Iustin Pop
    This is a multi-node call.
803 6b93ec9d Iustin Pop

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

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

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

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

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

832 72737a7f Iustin Pop
    The node will refuse the operation in case the file is not on the
833 72737a7f Iustin Pop
    approved file list.
834 72737a7f Iustin Pop

835 72737a7f Iustin Pop
    This is a multi-node call.
836 a8083063 Iustin Pop

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

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

858 6ddc95ec Michael Hanselmann
    This is a multi-node call.
859 6ddc95ec Michael Hanselmann

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

866 72737a7f Iustin Pop
    This is a multi-node call.
867 a8083063 Iustin Pop

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

880 72737a7f Iustin Pop
    This is a single-node call.
881 a8083063 Iustin Pop

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

891 72737a7f Iustin Pop
    Args:
892 72737a7f Iustin Pop
      - op: the OpCode instance
893 72737a7f Iustin Pop
      - env: a dictionary with the environment
894 a8083063 Iustin Pop

895 72737a7f Iustin Pop
    This is a multi-node call.
896 a8083063 Iustin Pop

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

904 72737a7f Iustin Pop
    Args:
905 72737a7f Iustin Pop
      - name: the iallocator name
906 72737a7f Iustin Pop
      - input: the json-encoded input string
907 8d528b7c Iustin Pop

908 72737a7f Iustin Pop
    This is a single-node call.
909 8d528b7c Iustin Pop

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

916 72737a7f Iustin Pop
    This is a single-node call.
917 4c8ba8b3 Iustin Pop

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

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

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

934 72737a7f Iustin Pop
    This is a single-node call.
935 a8083063 Iustin Pop

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

944 72737a7f Iustin Pop
    This writes the export config file, etc.
945 a8083063 Iustin Pop

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

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

959 72737a7f Iustin Pop
    This is a single-node call.
960 a8083063 Iustin Pop

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

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

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

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

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

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

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

998 72737a7f Iustin Pop
    This will remove the configuration information from the ganeti data
999 72737a7f Iustin Pop
    dir.
1000 a8083063 Iustin Pop

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

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

1009 72737a7f Iustin Pop
    This is a multi-node call.
1010 dcb93971 Michael Hanselmann

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

1017 56aa9fd5 Iustin Pop
    This is a single-node call.
1018 56aa9fd5 Iustin Pop

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

1025 72737a7f Iustin Pop
    This is a multi-node call.
1026 06009e27 Iustin Pop

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

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

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

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

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

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

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

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

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

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

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

1082 72737a7f Iustin Pop
    This is a multi-node call.
1083 af5ebcb1 Michael Hanselmann

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

1092 5d672980 Iustin Pop
    This is a multi-node call.
1093 5d672980 Iustin Pop

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

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

1106 6217e295 Iustin Pop
    This is a multi-node call.
1107 6217e295 Iustin Pop

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

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