Statistics
| Branch: | Tag: | Revision:

root / lib / rpc.py @ cd42d0ad

History | View | Annotate | Download (32.3 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 ecfe9491 Michael Hanselmann
      logging.error("RPC error from node %s: %s", name, msg)
238 781de953 Iustin Pop
      results[name] = RpcResult(data=msg, failed=True, node=name,
239 781de953 Iustin Pop
                                call=self.procedure)
240 ecfe9491 Michael Hanselmann
241 ecfe9491 Michael Hanselmann
    return results
242 a8083063 Iustin Pop
243 a8083063 Iustin Pop
244 72737a7f Iustin Pop
class RpcRunner(object):
245 72737a7f Iustin Pop
  """RPC runner class"""
246 a8083063 Iustin Pop
247 72737a7f Iustin Pop
  def __init__(self, cfg):
248 72737a7f Iustin Pop
    """Initialized the rpc runner.
249 a8083063 Iustin Pop

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

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

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

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

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

280 25348212 Iustin Pop
    @type client: L{Client}
281 25348212 Iustin Pop
    @param client: a C{Client} instance
282 25348212 Iustin Pop
    @type node_list: list
283 25348212 Iustin Pop
    @param node_list: the node list we should connect
284 25348212 Iustin Pop

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

307 25348212 Iustin Pop
    @type client: L{Client}
308 25348212 Iustin Pop
    @param client: a C{Client} instance
309 25348212 Iustin Pop
    @type node: str
310 25348212 Iustin Pop
    @param node: the node we should connect
311 25348212 Iustin Pop

312 25348212 Iustin Pop
    """
313 25348212 Iustin Pop
    node_info = self._cfg.GetNodeInfo(node)
314 25348212 Iustin Pop
    if node_info is not None:
315 ed83f5cc Iustin Pop
      if node_info.offline:
316 ed83f5cc Iustin Pop
        return RpcResult(node=node, offline=True)
317 25348212 Iustin Pop
      addr = node_info.primary_ip
318 25348212 Iustin Pop
    else:
319 25348212 Iustin Pop
      addr = None
320 25348212 Iustin Pop
    client.ConnectNode(node, address=addr)
321 25348212 Iustin Pop
322 ed83f5cc Iustin Pop
  def _MultiNodeCall(self, node_list, procedure, args):
323 160e2921 Iustin Pop
    """Helper for making a multi-node call
324 160e2921 Iustin Pop

325 160e2921 Iustin Pop
    """
326 160e2921 Iustin Pop
    body = serializer.DumpJson(args, indent=False)
327 160e2921 Iustin Pop
    c = Client(procedure, body, self.port)
328 ed83f5cc Iustin Pop
    skip_dict = self._ConnectList(c, node_list)
329 ed83f5cc Iustin Pop
    skip_dict.update(c.GetResults())
330 ed83f5cc Iustin Pop
    return skip_dict
331 9a525d83 Michael Hanselmann
332 9a525d83 Michael Hanselmann
  @classmethod
333 9a525d83 Michael Hanselmann
  def _StaticMultiNodeCall(cls, node_list, procedure, args,
334 9a525d83 Michael Hanselmann
                           address_list=None):
335 160e2921 Iustin Pop
    """Helper for making a multi-node static call
336 160e2921 Iustin Pop

337 160e2921 Iustin Pop
    """
338 160e2921 Iustin Pop
    body = serializer.DumpJson(args, indent=False)
339 160e2921 Iustin Pop
    c = Client(procedure, body, utils.GetNodeDaemonPort())
340 9a525d83 Michael Hanselmann
    c.ConnectList(node_list, address_list=address_list)
341 9a525d83 Michael Hanselmann
    return c.GetResults()
342 9a525d83 Michael Hanselmann
343 9a525d83 Michael Hanselmann
  def _SingleNodeCall(self, node, procedure, args):
344 160e2921 Iustin Pop
    """Helper for making a single-node call
345 9a525d83 Michael Hanselmann

346 9a525d83 Michael Hanselmann
    """
347 160e2921 Iustin Pop
    body = serializer.DumpJson(args, indent=False)
348 160e2921 Iustin Pop
    c = Client(procedure, body, self.port)
349 ed83f5cc Iustin Pop
    result = self._ConnectNode(c, node)
350 ed83f5cc Iustin Pop
    if result is None:
351 ed83f5cc Iustin Pop
      # we did connect, node is not offline
352 ed83f5cc Iustin Pop
      result = c.GetResults()[node]
353 ed83f5cc Iustin Pop
    return result
354 9a525d83 Michael Hanselmann
355 9a525d83 Michael Hanselmann
  @classmethod
356 9a525d83 Michael Hanselmann
  def _StaticSingleNodeCall(cls, node, procedure, args):
357 160e2921 Iustin Pop
    """Helper for making a single-node static call
358 9a525d83 Michael Hanselmann

359 9a525d83 Michael Hanselmann
    """
360 160e2921 Iustin Pop
    body = serializer.DumpJson(args, indent=False)
361 160e2921 Iustin Pop
    c = Client(procedure, body, utils.GetNodeDaemonPort())
362 3097c858 Michael Hanselmann
    c.ConnectNode(node)
363 ed83f5cc Iustin Pop
    return c.GetResults()[node]
364 9a525d83 Michael Hanselmann
365 12bce260 Michael Hanselmann
  @staticmethod
366 12bce260 Michael Hanselmann
  def _Compress(data):
367 12bce260 Michael Hanselmann
    """Compresses a string for transport over RPC.
368 12bce260 Michael Hanselmann

369 12bce260 Michael Hanselmann
    Small amounts of data are not compressed.
370 12bce260 Michael Hanselmann

371 12bce260 Michael Hanselmann
    @type data: str
372 12bce260 Michael Hanselmann
    @param data: Data
373 12bce260 Michael Hanselmann
    @rtype: tuple
374 12bce260 Michael Hanselmann
    @return: Encoded data to send
375 12bce260 Michael Hanselmann

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

392 72737a7f Iustin Pop
    This is a multi-node call.
393 a8083063 Iustin Pop

394 72737a7f Iustin Pop
    """
395 9a525d83 Michael Hanselmann
    return self._MultiNodeCall(node_list, "volume_list", [vg_name])
396 a8083063 Iustin Pop
397 72737a7f Iustin Pop
  def call_vg_list(self, node_list):
398 72737a7f Iustin Pop
    """Gets the volume group list.
399 a8083063 Iustin Pop

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

402 72737a7f Iustin Pop
    """
403 9a525d83 Michael Hanselmann
    return self._MultiNodeCall(node_list, "vg_list", [])
404 a8083063 Iustin Pop
405 72737a7f Iustin Pop
  def call_bridges_exist(self, node, bridges_list):
406 72737a7f Iustin Pop
    """Checks if a node has all the bridges given.
407 a8083063 Iustin Pop

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

412 72737a7f Iustin Pop
    This is a single-node call.
413 a8083063 Iustin Pop

414 72737a7f Iustin Pop
    """
415 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "bridges_exist", [bridges_list])
416 a8083063 Iustin Pop
417 72737a7f Iustin Pop
  def call_instance_start(self, node, instance, extra_args):
418 72737a7f Iustin Pop
    """Starts an instance.
419 a8083063 Iustin Pop

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

422 72737a7f Iustin Pop
    """
423 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "instance_start",
424 9a525d83 Michael Hanselmann
                                [self._InstDict(instance), extra_args])
425 a8083063 Iustin Pop
426 72737a7f Iustin Pop
  def call_instance_shutdown(self, node, instance):
427 72737a7f Iustin Pop
    """Stops an instance.
428 a8083063 Iustin Pop

429 72737a7f Iustin Pop
    This is a single-node call.
430 2a10865c Iustin Pop

431 72737a7f Iustin Pop
    """
432 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "instance_shutdown",
433 9a525d83 Michael Hanselmann
                                [self._InstDict(instance)])
434 2a10865c Iustin Pop
435 6906a9d8 Guido Trotter
  def call_migration_info(self, node, instance):
436 6906a9d8 Guido Trotter
    """Gather the information necessary to prepare an instance migration.
437 6906a9d8 Guido Trotter

438 6906a9d8 Guido Trotter
    This is a single-node call.
439 6906a9d8 Guido Trotter

440 6906a9d8 Guido Trotter
    @type node: string
441 6906a9d8 Guido Trotter
    @param node: the node on which the instance is currently running
442 6906a9d8 Guido Trotter
    @type instance: C{objects.Instance}
443 6906a9d8 Guido Trotter
    @param instance: the instance definition
444 6906a9d8 Guido Trotter

445 6906a9d8 Guido Trotter
    """
446 6906a9d8 Guido Trotter
    return self._SingleNodeCall(node, "migration_info",
447 6906a9d8 Guido Trotter
                                [self._InstDict(instance)])
448 6906a9d8 Guido Trotter
449 6906a9d8 Guido Trotter
  def call_accept_instance(self, node, instance, info, target):
450 6906a9d8 Guido Trotter
    """Prepare a node to accept an instance.
451 6906a9d8 Guido Trotter

452 6906a9d8 Guido Trotter
    This is a single-node call.
453 6906a9d8 Guido Trotter

454 6906a9d8 Guido Trotter
    @type node: string
455 6906a9d8 Guido Trotter
    @param node: the target node for the migration
456 6906a9d8 Guido Trotter
    @type instance: C{objects.Instance}
457 6906a9d8 Guido Trotter
    @param instance: the instance definition
458 6906a9d8 Guido Trotter
    @type info: opaque/hypervisor specific (string/data)
459 6906a9d8 Guido Trotter
    @param info: result for the call_migration_info call
460 6906a9d8 Guido Trotter
    @type target: string
461 6906a9d8 Guido Trotter
    @param target: target hostname (usually ip address) (on the node itself)
462 6906a9d8 Guido Trotter

463 6906a9d8 Guido Trotter
    """
464 6906a9d8 Guido Trotter
    return self._SingleNodeCall(node, "accept_instance",
465 6906a9d8 Guido Trotter
                                [self._InstDict(instance), info, target])
466 6906a9d8 Guido Trotter
467 6906a9d8 Guido Trotter
  def call_finalize_migration(self, node, instance, info, success):
468 6906a9d8 Guido Trotter
    """Finalize any target-node migration specific operation.
469 6906a9d8 Guido Trotter

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

473 6906a9d8 Guido Trotter
    This is a single-node call.
474 6906a9d8 Guido Trotter

475 6906a9d8 Guido Trotter
    @type node: string
476 6906a9d8 Guido Trotter
    @param node: the target node for the migration
477 6906a9d8 Guido Trotter
    @type instance: C{objects.Instance}
478 6906a9d8 Guido Trotter
    @param instance: the instance definition
479 6906a9d8 Guido Trotter
    @type info: opaque/hypervisor specific (string/data)
480 6906a9d8 Guido Trotter
    @param info: result for the call_migration_info call
481 6906a9d8 Guido Trotter
    @type success: boolean
482 6906a9d8 Guido Trotter
    @param success: whether the migration was a success or a failure
483 6906a9d8 Guido Trotter

484 6906a9d8 Guido Trotter
    """
485 6906a9d8 Guido Trotter
    return self._SingleNodeCall(node, "finalize_migration",
486 6906a9d8 Guido Trotter
                                [self._InstDict(instance), info, success])
487 6906a9d8 Guido Trotter
488 72737a7f Iustin Pop
  def call_instance_migrate(self, node, instance, target, live):
489 72737a7f Iustin Pop
    """Migrate an instance.
490 2a10865c Iustin Pop

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

493 72737a7f Iustin Pop
    @type node: string
494 72737a7f Iustin Pop
    @param node: the node on which the instance is currently running
495 72737a7f Iustin Pop
    @type instance: C{objects.Instance}
496 72737a7f Iustin Pop
    @param instance: the instance definition
497 72737a7f Iustin Pop
    @type target: string
498 72737a7f Iustin Pop
    @param target: the target node name
499 72737a7f Iustin Pop
    @type live: boolean
500 72737a7f Iustin Pop
    @param live: whether the migration should be done live or not (the
501 72737a7f Iustin Pop
        interpretation of this parameter is left to the hypervisor)
502 007a2f3e Alexander Schreiber

503 72737a7f Iustin Pop
    """
504 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "instance_migrate",
505 9a525d83 Michael Hanselmann
                                [self._InstDict(instance), target, live])
506 007a2f3e Alexander Schreiber
507 72737a7f Iustin Pop
  def call_instance_reboot(self, node, instance, reboot_type, extra_args):
508 72737a7f Iustin Pop
    """Reboots an instance.
509 007a2f3e Alexander Schreiber

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

512 72737a7f Iustin Pop
    """
513 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "instance_reboot",
514 9a525d83 Michael Hanselmann
                                [self._InstDict(instance), reboot_type,
515 9a525d83 Michael Hanselmann
                                 extra_args])
516 a8083063 Iustin Pop
517 d15a9ad3 Guido Trotter
  def call_instance_os_add(self, node, inst):
518 72737a7f Iustin Pop
    """Installs an OS on the given instance.
519 a8083063 Iustin Pop

520 72737a7f Iustin Pop
    This is a single-node call.
521 decd5f45 Iustin Pop

522 72737a7f Iustin Pop
    """
523 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "instance_os_add",
524 9a525d83 Michael Hanselmann
                                [self._InstDict(inst)])
525 decd5f45 Iustin Pop
526 d15a9ad3 Guido Trotter
  def call_instance_run_rename(self, node, inst, old_name):
527 72737a7f Iustin Pop
    """Run the OS rename script for an instance.
528 decd5f45 Iustin Pop

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

531 72737a7f Iustin Pop
    """
532 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "instance_run_rename",
533 9a525d83 Michael Hanselmann
                                [self._InstDict(inst), old_name])
534 a8083063 Iustin Pop
535 72737a7f Iustin Pop
  def call_instance_info(self, node, instance, hname):
536 72737a7f Iustin Pop
    """Returns information about a single instance.
537 a8083063 Iustin Pop

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

540 9a525d83 Michael Hanselmann
    @type node: list
541 9a525d83 Michael Hanselmann
    @param node: the list of nodes to query
542 72737a7f Iustin Pop
    @type instance: string
543 72737a7f Iustin Pop
    @param instance: the instance name
544 72737a7f Iustin Pop
    @type hname: string
545 72737a7f Iustin Pop
    @param hname: the hypervisor type of the instance
546 a8083063 Iustin Pop

547 72737a7f Iustin Pop
    """
548 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "instance_info", [instance, hname])
549 e69d05fd Iustin Pop
550 56e7640c Iustin Pop
  def call_instance_migratable(self, node, instance):
551 56e7640c Iustin Pop
    """Checks whether the given instance can be migrated.
552 56e7640c Iustin Pop

553 56e7640c Iustin Pop
    This is a single-node call.
554 56e7640c Iustin Pop

555 56e7640c Iustin Pop
    @param node: the node to query
556 56e7640c Iustin Pop
    @type instance: L{objects.Instance}
557 56e7640c Iustin Pop
    @param instance: the instance to check
558 56e7640c Iustin Pop

559 56e7640c Iustin Pop

560 56e7640c Iustin Pop
    """
561 56e7640c Iustin Pop
    return self._SingleNodeCall(node, "instance_migratable",
562 56e7640c Iustin Pop
                                [self._InstDict(instance)])
563 56e7640c Iustin Pop
564 72737a7f Iustin Pop
  def call_all_instances_info(self, node_list, hypervisor_list):
565 72737a7f Iustin Pop
    """Returns information about all instances on the given nodes.
566 a8083063 Iustin Pop

567 72737a7f Iustin Pop
    This is a multi-node call.
568 a8083063 Iustin Pop

569 72737a7f Iustin Pop
    @type node_list: list
570 72737a7f Iustin Pop
    @param node_list: the list of nodes to query
571 72737a7f Iustin Pop
    @type hypervisor_list: list
572 72737a7f Iustin Pop
    @param hypervisor_list: the hypervisors to query for instances
573 a8083063 Iustin Pop

574 72737a7f Iustin Pop
    """
575 9a525d83 Michael Hanselmann
    return self._MultiNodeCall(node_list, "all_instances_info",
576 9a525d83 Michael Hanselmann
                               [hypervisor_list])
577 e69d05fd Iustin Pop
578 72737a7f Iustin Pop
  def call_instance_list(self, node_list, hypervisor_list):
579 72737a7f Iustin Pop
    """Returns the list of running instances on a given node.
580 a8083063 Iustin Pop

581 72737a7f Iustin Pop
    This is a multi-node call.
582 a8083063 Iustin Pop

583 72737a7f Iustin Pop
    @type node_list: list
584 72737a7f Iustin Pop
    @param node_list: the list of nodes to query
585 72737a7f Iustin Pop
    @type hypervisor_list: list
586 72737a7f Iustin Pop
    @param hypervisor_list: the hypervisors to query for instances
587 16abfbc2 Alexander Schreiber

588 72737a7f Iustin Pop
    """
589 9a525d83 Michael Hanselmann
    return self._MultiNodeCall(node_list, "instance_list", [hypervisor_list])
590 16abfbc2 Alexander Schreiber
591 72737a7f Iustin Pop
  def call_node_tcp_ping(self, node, source, target, port, timeout,
592 72737a7f Iustin Pop
                         live_port_needed):
593 72737a7f Iustin Pop
    """Do a TcpPing on the remote node
594 a8083063 Iustin Pop

595 72737a7f Iustin Pop
    This is a single-node call.
596 caad16e2 Iustin Pop

597 72737a7f Iustin Pop
    """
598 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "node_tcp_ping",
599 9a525d83 Michael Hanselmann
                                [source, target, port, timeout,
600 72737a7f Iustin Pop
                                 live_port_needed])
601 a8083063 Iustin Pop
602 caad16e2 Iustin Pop
  def call_node_has_ip_address(self, node, address):
603 caad16e2 Iustin Pop
    """Checks if a node has the given IP address.
604 caad16e2 Iustin Pop

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

607 caad16e2 Iustin Pop
    """
608 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "node_has_ip_address", [address])
609 a8083063 Iustin Pop
610 72737a7f Iustin Pop
  def call_node_info(self, node_list, vg_name, hypervisor_type):
611 72737a7f Iustin Pop
    """Return node information.
612 e69d05fd Iustin Pop

613 72737a7f Iustin Pop
    This will return memory information and volume group size and free
614 72737a7f Iustin Pop
    space.
615 a8083063 Iustin Pop

616 72737a7f Iustin Pop
    This is a multi-node call.
617 a8083063 Iustin Pop

618 72737a7f Iustin Pop
    @type node_list: list
619 72737a7f Iustin Pop
    @param node_list: the list of nodes to query
620 c41eea6e Iustin Pop
    @type vg_name: C{string}
621 c41eea6e Iustin Pop
    @param vg_name: the name of the volume group to ask for disk space
622 72737a7f Iustin Pop
        information
623 72737a7f Iustin Pop
    @type hypervisor_type: C{str}
624 72737a7f Iustin Pop
    @param hypervisor_type: the name of the hypervisor to ask for
625 72737a7f Iustin Pop
        memory information
626 a8083063 Iustin Pop

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

651 72737a7f Iustin Pop
    This is a single-node call.
652 a8083063 Iustin Pop

653 72737a7f Iustin Pop
    """
654 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "node_add",
655 9a525d83 Michael Hanselmann
                                [dsa, dsapub, rsa, rsapub, ssh, sshpub])
656 a8083063 Iustin Pop
657 72737a7f Iustin Pop
  def call_node_verify(self, node_list, checkdict, cluster_name):
658 72737a7f Iustin Pop
    """Request verification of given parameters.
659 a8083063 Iustin Pop

660 72737a7f Iustin Pop
    This is a multi-node call.
661 a8083063 Iustin Pop

662 72737a7f Iustin Pop
    """
663 9a525d83 Michael Hanselmann
    return self._MultiNodeCall(node_list, "node_verify",
664 9a525d83 Michael Hanselmann
                               [checkdict, cluster_name])
665 a8083063 Iustin Pop
666 9a525d83 Michael Hanselmann
  @classmethod
667 9a525d83 Michael Hanselmann
  def call_node_start_master(cls, node, start_daemons):
668 72737a7f Iustin Pop
    """Tells a node to activate itself as a master.
669 a8083063 Iustin Pop

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

672 72737a7f Iustin Pop
    """
673 9a525d83 Michael Hanselmann
    return cls._StaticSingleNodeCall(node, "node_start_master",
674 9a525d83 Michael Hanselmann
                                     [start_daemons])
675 a8083063 Iustin Pop
676 9a525d83 Michael Hanselmann
  @classmethod
677 9a525d83 Michael Hanselmann
  def call_node_stop_master(cls, node, stop_daemons):
678 72737a7f Iustin Pop
    """Tells a node to demote itself from master status.
679 a8083063 Iustin Pop

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

682 72737a7f Iustin Pop
    """
683 9a525d83 Michael Hanselmann
    return cls._StaticSingleNodeCall(node, "node_stop_master", [stop_daemons])
684 4e071d3b Iustin Pop
685 9a525d83 Michael Hanselmann
  @classmethod
686 9a525d83 Michael Hanselmann
  def call_master_info(cls, node_list):
687 72737a7f Iustin Pop
    """Query master info.
688 4e071d3b Iustin Pop

689 72737a7f Iustin Pop
    This is a multi-node call.
690 a8083063 Iustin Pop

691 72737a7f Iustin Pop
    """
692 72737a7f Iustin Pop
    # TODO: should this method query down nodes?
693 9a525d83 Michael Hanselmann
    return cls._StaticMultiNodeCall(node_list, "master_info", [])
694 a8083063 Iustin Pop
695 72737a7f Iustin Pop
  def call_version(self, node_list):
696 72737a7f Iustin Pop
    """Query node version.
697 a8083063 Iustin Pop

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

700 72737a7f Iustin Pop
    """
701 9a525d83 Michael Hanselmann
    return self._MultiNodeCall(node_list, "version", [])
702 a8083063 Iustin Pop
703 72737a7f Iustin Pop
  def call_blockdev_create(self, node, bdev, size, owner, on_primary, info):
704 72737a7f Iustin Pop
    """Request creation of a given block device.
705 a8083063 Iustin Pop

706 72737a7f Iustin Pop
    This is a single-node call.
707 a8083063 Iustin Pop

708 72737a7f Iustin Pop
    """
709 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "blockdev_create",
710 9a525d83 Michael Hanselmann
                                [bdev.ToDict(), size, owner, on_primary, info])
711 a8083063 Iustin Pop
712 72737a7f Iustin Pop
  def call_blockdev_remove(self, node, bdev):
713 72737a7f Iustin Pop
    """Request removal of a given block device.
714 a8083063 Iustin Pop

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

717 72737a7f Iustin Pop
    """
718 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "blockdev_remove", [bdev.ToDict()])
719 f3e513ad Iustin Pop
720 72737a7f Iustin Pop
  def call_blockdev_rename(self, node, devlist):
721 72737a7f Iustin Pop
    """Request rename of the given block devices.
722 f3e513ad Iustin Pop

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

725 72737a7f Iustin Pop
    """
726 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "blockdev_rename",
727 9a525d83 Michael Hanselmann
                                [(d.ToDict(), uid) for d, uid in devlist])
728 a8083063 Iustin Pop
729 72737a7f Iustin Pop
  def call_blockdev_assemble(self, node, disk, owner, on_primary):
730 72737a7f Iustin Pop
    """Request assembling of a given block device.
731 a8083063 Iustin Pop

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

734 72737a7f Iustin Pop
    """
735 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "blockdev_assemble",
736 9a525d83 Michael Hanselmann
                                [disk.ToDict(), owner, on_primary])
737 a8083063 Iustin Pop
738 72737a7f Iustin Pop
  def call_blockdev_shutdown(self, node, disk):
739 72737a7f Iustin Pop
    """Request shutdown of a given block device.
740 a8083063 Iustin Pop

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

743 72737a7f Iustin Pop
    """
744 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "blockdev_shutdown", [disk.ToDict()])
745 a8083063 Iustin Pop
746 72737a7f Iustin Pop
  def call_blockdev_addchildren(self, node, bdev, ndevs):
747 72737a7f Iustin Pop
    """Request adding a list of children to a (mirroring) device.
748 a8083063 Iustin Pop

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

751 72737a7f Iustin Pop
    """
752 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "blockdev_addchildren",
753 9a525d83 Michael Hanselmann
                                [bdev.ToDict(),
754 9a525d83 Michael Hanselmann
                                 [disk.ToDict() for disk in ndevs]])
755 a8083063 Iustin Pop
756 72737a7f Iustin Pop
  def call_blockdev_removechildren(self, node, bdev, ndevs):
757 72737a7f Iustin Pop
    """Request removing a list of children from a (mirroring) device.
758 a8083063 Iustin Pop

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

761 72737a7f Iustin Pop
    """
762 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "blockdev_removechildren",
763 9a525d83 Michael Hanselmann
                                [bdev.ToDict(),
764 9a525d83 Michael Hanselmann
                                 [disk.ToDict() for disk in ndevs]])
765 a8083063 Iustin Pop
766 72737a7f Iustin Pop
  def call_blockdev_getmirrorstatus(self, node, disks):
767 72737a7f Iustin Pop
    """Request status of a (mirroring) device.
768 a8083063 Iustin Pop

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

771 72737a7f Iustin Pop
    """
772 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "blockdev_getmirrorstatus",
773 9a525d83 Michael Hanselmann
                                [dsk.ToDict() for dsk in disks])
774 a8083063 Iustin Pop
775 72737a7f Iustin Pop
  def call_blockdev_find(self, node, disk):
776 72737a7f Iustin Pop
    """Request identification of a given block device.
777 72737a7f Iustin Pop

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

780 72737a7f Iustin Pop
    """
781 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "blockdev_find", [disk.ToDict()])
782 d61cbe76 Iustin Pop
783 b2e7666a Iustin Pop
  def call_blockdev_close(self, node, instance_name, disks):
784 72737a7f Iustin Pop
    """Closes the given block devices.
785 d61cbe76 Iustin Pop

786 72737a7f Iustin Pop
    This is a single-node call.
787 d61cbe76 Iustin Pop

788 72737a7f Iustin Pop
    """
789 b2e7666a Iustin Pop
    params = [instance_name, [cf.ToDict() for cf in disks]]
790 b2e7666a Iustin Pop
    return self._SingleNodeCall(node, "blockdev_close", params)
791 a8083063 Iustin Pop
792 6b93ec9d Iustin Pop
  def call_drbd_disconnect_net(self, node_list, nodes_ip, disks):
793 6b93ec9d Iustin Pop
    """Disconnects the network of the given drbd devices.
794 6b93ec9d Iustin Pop

795 6b93ec9d Iustin Pop
    This is a multi-node call.
796 6b93ec9d Iustin Pop

797 6b93ec9d Iustin Pop
    """
798 6b93ec9d Iustin Pop
    return self._MultiNodeCall(node_list, "drbd_disconnect_net",
799 6b93ec9d Iustin Pop
                               [nodes_ip, [cf.ToDict() for cf in disks]])
800 6b93ec9d Iustin Pop
801 6b93ec9d Iustin Pop
  def call_drbd_attach_net(self, node_list, nodes_ip,
802 6b93ec9d Iustin Pop
                           disks, instance_name, multimaster):
803 6b93ec9d Iustin Pop
    """Disconnects the given drbd devices.
804 6b93ec9d Iustin Pop

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

807 6b93ec9d Iustin Pop
    """
808 6b93ec9d Iustin Pop
    return self._MultiNodeCall(node_list, "drbd_attach_net",
809 6b93ec9d Iustin Pop
                               [nodes_ip, [cf.ToDict() for cf in disks],
810 6b93ec9d Iustin Pop
                                instance_name, multimaster])
811 6b93ec9d Iustin Pop
812 6b93ec9d Iustin Pop
  def call_drbd_wait_sync(self, node_list, nodes_ip, disks):
813 6b93ec9d Iustin Pop
    """Waits for the synchronization of drbd devices is complete.
814 6b93ec9d Iustin Pop

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

817 6b93ec9d Iustin Pop
    """
818 6b93ec9d Iustin Pop
    return self._MultiNodeCall(node_list, "drbd_wait_sync",
819 6b93ec9d Iustin Pop
                               [nodes_ip, [cf.ToDict() for cf in disks]])
820 6b93ec9d Iustin Pop
821 9a525d83 Michael Hanselmann
  @classmethod
822 9a525d83 Michael Hanselmann
  def call_upload_file(cls, node_list, file_name, address_list=None):
823 72737a7f Iustin Pop
    """Upload a file.
824 72737a7f Iustin Pop

825 72737a7f Iustin Pop
    The node will refuse the operation in case the file is not on the
826 72737a7f Iustin Pop
    approved file list.
827 72737a7f Iustin Pop

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

830 6b294c53 Iustin Pop
    @type node_list: list
831 6b294c53 Iustin Pop
    @param node_list: the list of node names to upload to
832 6b294c53 Iustin Pop
    @type file_name: str
833 6b294c53 Iustin Pop
    @param file_name: the filename to upload
834 6b294c53 Iustin Pop
    @type address_list: list or None
835 6b294c53 Iustin Pop
    @keyword address_list: an optional list of node addresses, in order
836 6b294c53 Iustin Pop
        to optimize the RPC speed
837 6b294c53 Iustin Pop

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

851 6ddc95ec Michael Hanselmann
    This is a multi-node call.
852 6ddc95ec Michael Hanselmann

853 6ddc95ec Michael Hanselmann
    """
854 03d1dba2 Michael Hanselmann
    return cls._StaticMultiNodeCall(node_list, "write_ssconf_files", [values])
855 6ddc95ec Michael Hanselmann
856 72737a7f Iustin Pop
  def call_os_diagnose(self, node_list):
857 72737a7f Iustin Pop
    """Request a diagnose of OS definitions.
858 72737a7f Iustin Pop

859 72737a7f Iustin Pop
    This is a multi-node call.
860 a8083063 Iustin Pop

861 72737a7f Iustin Pop
    """
862 9a525d83 Michael Hanselmann
    result = self._MultiNodeCall(node_list, "os_diagnose", [])
863 9a525d83 Michael Hanselmann
864 fab1e3a4 Iustin Pop
    for node_result in result.values():
865 781de953 Iustin Pop
      if not node_result.failed and node_result.data:
866 781de953 Iustin Pop
        node_result.data = [objects.OS.FromDict(oss)
867 781de953 Iustin Pop
                            for oss in node_result.data]
868 781de953 Iustin Pop
    return result
869 a8083063 Iustin Pop
870 72737a7f Iustin Pop
  def call_os_get(self, node, name):
871 72737a7f Iustin Pop
    """Returns an OS definition.
872 a8083063 Iustin Pop

873 72737a7f Iustin Pop
    This is a single-node call.
874 a8083063 Iustin Pop

875 72737a7f Iustin Pop
    """
876 9a525d83 Michael Hanselmann
    result = self._SingleNodeCall(node, "os_get", [name])
877 781de953 Iustin Pop
    if not result.failed and isinstance(result.data, dict):
878 781de953 Iustin Pop
      result.data = objects.OS.FromDict(result.data)
879 781de953 Iustin Pop
    return result
880 a8083063 Iustin Pop
881 72737a7f Iustin Pop
  def call_hooks_runner(self, node_list, hpath, phase, env):
882 72737a7f Iustin Pop
    """Call the hooks runner.
883 a8083063 Iustin Pop

884 72737a7f Iustin Pop
    Args:
885 72737a7f Iustin Pop
      - op: the OpCode instance
886 72737a7f Iustin Pop
      - env: a dictionary with the environment
887 a8083063 Iustin Pop

888 72737a7f Iustin Pop
    This is a multi-node call.
889 a8083063 Iustin Pop

890 72737a7f Iustin Pop
    """
891 72737a7f Iustin Pop
    params = [hpath, phase, env]
892 9a525d83 Michael Hanselmann
    return self._MultiNodeCall(node_list, "hooks_runner", params)
893 a8083063 Iustin Pop
894 72737a7f Iustin Pop
  def call_iallocator_runner(self, node, name, idata):
895 72737a7f Iustin Pop
    """Call an iallocator on a remote node
896 8d528b7c Iustin Pop

897 72737a7f Iustin Pop
    Args:
898 72737a7f Iustin Pop
      - name: the iallocator name
899 72737a7f Iustin Pop
      - input: the json-encoded input string
900 8d528b7c Iustin Pop

901 72737a7f Iustin Pop
    This is a single-node call.
902 8d528b7c Iustin Pop

903 72737a7f Iustin Pop
    """
904 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "iallocator_runner", [name, idata])
905 8d528b7c Iustin Pop
906 72737a7f Iustin Pop
  def call_blockdev_grow(self, node, cf_bdev, amount):
907 72737a7f Iustin Pop
    """Request a snapshot of the given block device.
908 4c8ba8b3 Iustin Pop

909 72737a7f Iustin Pop
    This is a single-node call.
910 4c8ba8b3 Iustin Pop

911 72737a7f Iustin Pop
    """
912 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "blockdev_grow",
913 9a525d83 Michael Hanselmann
                                [cf_bdev.ToDict(), amount])
914 4c8ba8b3 Iustin Pop
915 72737a7f Iustin Pop
  def call_blockdev_snapshot(self, node, cf_bdev):
916 72737a7f Iustin Pop
    """Request a snapshot of the given block device.
917 a8083063 Iustin Pop

918 72737a7f Iustin Pop
    This is a single-node call.
919 a8083063 Iustin Pop

920 72737a7f Iustin Pop
    """
921 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "blockdev_snapshot", [cf_bdev.ToDict()])
922 a8083063 Iustin Pop
923 72737a7f Iustin Pop
  def call_snapshot_export(self, node, snap_bdev, dest_node, instance,
924 74c47259 Iustin Pop
                           cluster_name, idx):
925 72737a7f Iustin Pop
    """Request the export of a given snapshot.
926 a8083063 Iustin Pop

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

929 72737a7f Iustin Pop
    """
930 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "snapshot_export",
931 9a525d83 Michael Hanselmann
                                [snap_bdev.ToDict(), dest_node,
932 9a525d83 Michael Hanselmann
                                 self._InstDict(instance), cluster_name, idx])
933 a8083063 Iustin Pop
934 72737a7f Iustin Pop
  def call_finalize_export(self, node, instance, snap_disks):
935 72737a7f Iustin Pop
    """Request the completion of an export operation.
936 a8083063 Iustin Pop

937 72737a7f Iustin Pop
    This writes the export config file, etc.
938 a8083063 Iustin Pop

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

941 72737a7f Iustin Pop
    """
942 72737a7f Iustin Pop
    flat_disks = []
943 72737a7f Iustin Pop
    for disk in snap_disks:
944 72737a7f Iustin Pop
      flat_disks.append(disk.ToDict())
945 9a525d83 Michael Hanselmann
946 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "finalize_export",
947 9a525d83 Michael Hanselmann
                                [self._InstDict(instance), flat_disks])
948 a8083063 Iustin Pop
949 72737a7f Iustin Pop
  def call_export_info(self, node, path):
950 72737a7f Iustin Pop
    """Queries the export information in a given path.
951 a8083063 Iustin Pop

952 72737a7f Iustin Pop
    This is a single-node call.
953 a8083063 Iustin Pop

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

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

966 72737a7f Iustin Pop
    """
967 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "instance_os_import",
968 9a525d83 Michael Hanselmann
                                [self._InstDict(inst), src_node, src_images,
969 9a525d83 Michael Hanselmann
                                 cluster_name])
970 a8083063 Iustin Pop
971 72737a7f Iustin Pop
  def call_export_list(self, node_list):
972 72737a7f Iustin Pop
    """Gets the stored exports list.
973 a8083063 Iustin Pop

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

976 72737a7f Iustin Pop
    """
977 9a525d83 Michael Hanselmann
    return self._MultiNodeCall(node_list, "export_list", [])
978 a8083063 Iustin Pop
979 72737a7f Iustin Pop
  def call_export_remove(self, node, export):
980 72737a7f Iustin Pop
    """Requests removal of a given export.
981 a8083063 Iustin Pop

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

984 72737a7f Iustin Pop
    """
985 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "export_remove", [export])
986 a8083063 Iustin Pop
987 9a525d83 Michael Hanselmann
  @classmethod
988 9a525d83 Michael Hanselmann
  def call_node_leave_cluster(cls, node):
989 72737a7f Iustin Pop
    """Requests a node to clean the cluster information it has.
990 a8083063 Iustin Pop

991 72737a7f Iustin Pop
    This will remove the configuration information from the ganeti data
992 72737a7f Iustin Pop
    dir.
993 a8083063 Iustin Pop

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

996 72737a7f Iustin Pop
    """
997 9a525d83 Michael Hanselmann
    return cls._StaticSingleNodeCall(node, "node_leave_cluster", [])
998 dcb93971 Michael Hanselmann
999 72737a7f Iustin Pop
  def call_node_volumes(self, node_list):
1000 72737a7f Iustin Pop
    """Gets all volumes on node(s).
1001 dcb93971 Michael Hanselmann

1002 72737a7f Iustin Pop
    This is a multi-node call.
1003 dcb93971 Michael Hanselmann

1004 72737a7f Iustin Pop
    """
1005 9a525d83 Michael Hanselmann
    return self._MultiNodeCall(node_list, "node_volumes", [])
1006 06009e27 Iustin Pop
1007 56aa9fd5 Iustin Pop
  def call_node_demote_from_mc(self, node):
1008 56aa9fd5 Iustin Pop
    """Demote a node from the master candidate role.
1009 56aa9fd5 Iustin Pop

1010 56aa9fd5 Iustin Pop
    This is a single-node call.
1011 56aa9fd5 Iustin Pop

1012 56aa9fd5 Iustin Pop
    """
1013 56aa9fd5 Iustin Pop
    return self._SingleNodeCall(node, "node_demote_from_mc", [])
1014 56aa9fd5 Iustin Pop
1015 72737a7f Iustin Pop
  def call_test_delay(self, node_list, duration):
1016 72737a7f Iustin Pop
    """Sleep for a fixed time on given node(s).
1017 06009e27 Iustin Pop

1018 72737a7f Iustin Pop
    This is a multi-node call.
1019 06009e27 Iustin Pop

1020 72737a7f Iustin Pop
    """
1021 9a525d83 Michael Hanselmann
    return self._MultiNodeCall(node_list, "test_delay", [duration])
1022 5e04ed8b Manuel Franceschini
1023 72737a7f Iustin Pop
  def call_file_storage_dir_create(self, node, file_storage_dir):
1024 72737a7f Iustin Pop
    """Create the given file storage directory.
1025 5e04ed8b Manuel Franceschini

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

1028 72737a7f Iustin Pop
    """
1029 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "file_storage_dir_create",
1030 9a525d83 Michael Hanselmann
                                [file_storage_dir])
1031 5e04ed8b Manuel Franceschini
1032 72737a7f Iustin Pop
  def call_file_storage_dir_remove(self, node, file_storage_dir):
1033 72737a7f Iustin Pop
    """Remove the given file storage directory.
1034 5e04ed8b Manuel Franceschini

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

1037 72737a7f Iustin Pop
    """
1038 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "file_storage_dir_remove",
1039 9a525d83 Michael Hanselmann
                                [file_storage_dir])
1040 5e04ed8b Manuel Franceschini
1041 72737a7f Iustin Pop
  def call_file_storage_dir_rename(self, node, old_file_storage_dir,
1042 72737a7f Iustin Pop
                                   new_file_storage_dir):
1043 72737a7f Iustin Pop
    """Rename file storage directory.
1044 5e04ed8b Manuel Franceschini

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

1047 72737a7f Iustin Pop
    """
1048 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "file_storage_dir_rename",
1049 9a525d83 Michael Hanselmann
                                [old_file_storage_dir, new_file_storage_dir])
1050 ca52cdeb Michael Hanselmann
1051 9a525d83 Michael Hanselmann
  @classmethod
1052 9a525d83 Michael Hanselmann
  def call_jobqueue_update(cls, node_list, address_list, file_name, content):
1053 72737a7f Iustin Pop
    """Update job queue.
1054 ca52cdeb Michael Hanselmann

1055 72737a7f Iustin Pop
    This is a multi-node call.
1056 ca52cdeb Michael Hanselmann

1057 72737a7f Iustin Pop
    """
1058 9a525d83 Michael Hanselmann
    return cls._StaticMultiNodeCall(node_list, "jobqueue_update",
1059 12bce260 Michael Hanselmann
                                    [file_name, cls._Compress(content)],
1060 9a525d83 Michael Hanselmann
                                    address_list=address_list)
1061 ca52cdeb Michael Hanselmann
1062 9a525d83 Michael Hanselmann
  @classmethod
1063 9a525d83 Michael Hanselmann
  def call_jobqueue_purge(cls, node):
1064 72737a7f Iustin Pop
    """Purge job queue.
1065 ca52cdeb Michael Hanselmann

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

1068 72737a7f Iustin Pop
    """
1069 9a525d83 Michael Hanselmann
    return cls._StaticSingleNodeCall(node, "jobqueue_purge", [])
1070 af5ebcb1 Michael Hanselmann
1071 9a525d83 Michael Hanselmann
  @classmethod
1072 dd875d32 Michael Hanselmann
  def call_jobqueue_rename(cls, node_list, address_list, rename):
1073 72737a7f Iustin Pop
    """Rename a job queue file.
1074 af5ebcb1 Michael Hanselmann

1075 72737a7f Iustin Pop
    This is a multi-node call.
1076 af5ebcb1 Michael Hanselmann

1077 72737a7f Iustin Pop
    """
1078 dd875d32 Michael Hanselmann
    return cls._StaticMultiNodeCall(node_list, "jobqueue_rename", rename,
1079 9a525d83 Michael Hanselmann
                                    address_list=address_list)
1080 6217e295 Iustin Pop
1081 9a525d83 Michael Hanselmann
  @classmethod
1082 9a525d83 Michael Hanselmann
  def call_jobqueue_set_drain(cls, node_list, drain_flag):
1083 5d672980 Iustin Pop
    """Set the drain flag on the queue.
1084 5d672980 Iustin Pop

1085 5d672980 Iustin Pop
    This is a multi-node call.
1086 5d672980 Iustin Pop

1087 5d672980 Iustin Pop
    @type node_list: list
1088 5d672980 Iustin Pop
    @param node_list: the list of nodes to query
1089 5d672980 Iustin Pop
    @type drain_flag: bool
1090 5d672980 Iustin Pop
    @param drain_flag: if True, will set the drain flag, otherwise reset it.
1091 5d672980 Iustin Pop

1092 5d672980 Iustin Pop
    """
1093 9a525d83 Michael Hanselmann
    return cls._StaticMultiNodeCall(node_list, "jobqueue_set_drain",
1094 9a525d83 Michael Hanselmann
                                    [drain_flag])
1095 5d672980 Iustin Pop
1096 6217e295 Iustin Pop
  def call_hypervisor_validate_params(self, node_list, hvname, hvparams):
1097 6217e295 Iustin Pop
    """Validate the hypervisor params.
1098 6217e295 Iustin Pop

1099 6217e295 Iustin Pop
    This is a multi-node call.
1100 6217e295 Iustin Pop

1101 6217e295 Iustin Pop
    @type node_list: list
1102 6217e295 Iustin Pop
    @param node_list: the list of nodes to query
1103 6217e295 Iustin Pop
    @type hvname: string
1104 6217e295 Iustin Pop
    @param hvname: the hypervisor name
1105 6217e295 Iustin Pop
    @type hvparams: dict
1106 6217e295 Iustin Pop
    @param hvparams: the hypervisor parameters to be validated
1107 6217e295 Iustin Pop

1108 6217e295 Iustin Pop
    """
1109 6217e295 Iustin Pop
    cluster = self._cfg.GetClusterInfo()
1110 6217e295 Iustin Pop
    hv_full = cluster.FillDict(cluster.hvparams.get(hvname, {}), hvparams)
1111 9a525d83 Michael Hanselmann
    return self._MultiNodeCall(node_list, "hypervisor_validate_params",
1112 9a525d83 Michael Hanselmann
                               [hvname, hv_full])