Statistics
| Branch: | Tag: | Revision:

root / lib / rpc.py @ 3213d3c8

History | View | Annotate | Download (32.8 kB)

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

24 a8083063 Iustin Pop
"""
25 a8083063 Iustin Pop
26 72737a7f Iustin Pop
# pylint: disable-msg=C0103,R0201,R0904
27 72737a7f Iustin Pop
# C0103: Invalid name, since call_ are not valid
28 72737a7f Iustin Pop
# R0201: Method could be a function, we keep all rpcs instance methods
29 72737a7f Iustin Pop
# as not to change them back and forth between static/instance methods
30 72737a7f Iustin Pop
# if they need to start using instance attributes
31 72737a7f Iustin Pop
# R0904: Too many public methods
32 a8083063 Iustin Pop
33 a8083063 Iustin Pop
import os
34 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 ecfe9491 Michael Hanselmann
    @returns: 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 72737a7f Iustin Pop
  def call_instance_start(self, node, instance, extra_args):
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 9a525d83 Michael Hanselmann
                                [self._InstDict(instance), extra_args])
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 72737a7f Iustin Pop
  def call_instance_reboot(self, node, instance, reboot_type, extra_args):
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 9a525d83 Michael Hanselmann
                                [self._InstDict(instance), reboot_type,
526 9a525d83 Michael Hanselmann
                                 extra_args])
527 a8083063 Iustin Pop
528 d15a9ad3 Guido Trotter
  def call_instance_os_add(self, node, inst):
529 72737a7f Iustin Pop
    """Installs an OS on the given instance.
530 a8083063 Iustin Pop

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

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

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

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

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

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

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

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

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

570 56e7640c Iustin Pop

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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