Statistics
| Branch: | Tag: | Revision:

root / lib / rpc.py @ 6b93ec9d

History | View | Annotate | Download (30.4 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 72737a7f Iustin Pop
  def call_instance_migrate(self, node, instance, target, live):
436 72737a7f Iustin Pop
    """Migrate an instance.
437 2a10865c Iustin Pop

438 72737a7f Iustin Pop
    This is a single-node call.
439 2a10865c Iustin Pop

440 72737a7f Iustin Pop
    @type node: string
441 72737a7f Iustin Pop
    @param node: the node on which the instance is currently running
442 72737a7f Iustin Pop
    @type instance: C{objects.Instance}
443 72737a7f Iustin Pop
    @param instance: the instance definition
444 72737a7f Iustin Pop
    @type target: string
445 72737a7f Iustin Pop
    @param target: the target node name
446 72737a7f Iustin Pop
    @type live: boolean
447 72737a7f Iustin Pop
    @param live: whether the migration should be done live or not (the
448 72737a7f Iustin Pop
        interpretation of this parameter is left to the hypervisor)
449 007a2f3e Alexander Schreiber

450 72737a7f Iustin Pop
    """
451 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "instance_migrate",
452 9a525d83 Michael Hanselmann
                                [self._InstDict(instance), target, live])
453 007a2f3e Alexander Schreiber
454 72737a7f Iustin Pop
  def call_instance_reboot(self, node, instance, reboot_type, extra_args):
455 72737a7f Iustin Pop
    """Reboots an instance.
456 007a2f3e Alexander Schreiber

457 72737a7f Iustin Pop
    This is a single-node call.
458 a8083063 Iustin Pop

459 72737a7f Iustin Pop
    """
460 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "instance_reboot",
461 9a525d83 Michael Hanselmann
                                [self._InstDict(instance), reboot_type,
462 9a525d83 Michael Hanselmann
                                 extra_args])
463 a8083063 Iustin Pop
464 d15a9ad3 Guido Trotter
  def call_instance_os_add(self, node, inst):
465 72737a7f Iustin Pop
    """Installs an OS on the given instance.
466 a8083063 Iustin Pop

467 72737a7f Iustin Pop
    This is a single-node call.
468 decd5f45 Iustin Pop

469 72737a7f Iustin Pop
    """
470 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "instance_os_add",
471 9a525d83 Michael Hanselmann
                                [self._InstDict(inst)])
472 decd5f45 Iustin Pop
473 d15a9ad3 Guido Trotter
  def call_instance_run_rename(self, node, inst, old_name):
474 72737a7f Iustin Pop
    """Run the OS rename script for an instance.
475 decd5f45 Iustin Pop

476 72737a7f Iustin Pop
    This is a single-node call.
477 a8083063 Iustin Pop

478 72737a7f Iustin Pop
    """
479 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "instance_run_rename",
480 9a525d83 Michael Hanselmann
                                [self._InstDict(inst), old_name])
481 a8083063 Iustin Pop
482 72737a7f Iustin Pop
  def call_instance_info(self, node, instance, hname):
483 72737a7f Iustin Pop
    """Returns information about a single instance.
484 a8083063 Iustin Pop

485 72737a7f Iustin Pop
    This is a single-node call.
486 a8083063 Iustin Pop

487 9a525d83 Michael Hanselmann
    @type node: list
488 9a525d83 Michael Hanselmann
    @param node: the list of nodes to query
489 72737a7f Iustin Pop
    @type instance: string
490 72737a7f Iustin Pop
    @param instance: the instance name
491 72737a7f Iustin Pop
    @type hname: string
492 72737a7f Iustin Pop
    @param hname: the hypervisor type of the instance
493 a8083063 Iustin Pop

494 72737a7f Iustin Pop
    """
495 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "instance_info", [instance, hname])
496 e69d05fd Iustin Pop
497 56e7640c Iustin Pop
  def call_instance_migratable(self, node, instance):
498 56e7640c Iustin Pop
    """Checks whether the given instance can be migrated.
499 56e7640c Iustin Pop

500 56e7640c Iustin Pop
    This is a single-node call.
501 56e7640c Iustin Pop

502 56e7640c Iustin Pop
    @param node: the node to query
503 56e7640c Iustin Pop
    @type instance: L{objects.Instance}
504 56e7640c Iustin Pop
    @param instance: the instance to check
505 56e7640c Iustin Pop

506 56e7640c Iustin Pop

507 56e7640c Iustin Pop
    """
508 56e7640c Iustin Pop
    return self._SingleNodeCall(node, "instance_migratable",
509 56e7640c Iustin Pop
                                [self._InstDict(instance)])
510 56e7640c Iustin Pop
511 72737a7f Iustin Pop
  def call_all_instances_info(self, node_list, hypervisor_list):
512 72737a7f Iustin Pop
    """Returns information about all instances on the given nodes.
513 a8083063 Iustin Pop

514 72737a7f Iustin Pop
    This is a multi-node call.
515 a8083063 Iustin Pop

516 72737a7f Iustin Pop
    @type node_list: list
517 72737a7f Iustin Pop
    @param node_list: the list of nodes to query
518 72737a7f Iustin Pop
    @type hypervisor_list: list
519 72737a7f Iustin Pop
    @param hypervisor_list: the hypervisors to query for instances
520 a8083063 Iustin Pop

521 72737a7f Iustin Pop
    """
522 9a525d83 Michael Hanselmann
    return self._MultiNodeCall(node_list, "all_instances_info",
523 9a525d83 Michael Hanselmann
                               [hypervisor_list])
524 e69d05fd Iustin Pop
525 72737a7f Iustin Pop
  def call_instance_list(self, node_list, hypervisor_list):
526 72737a7f Iustin Pop
    """Returns the list of running instances on a given node.
527 a8083063 Iustin Pop

528 72737a7f Iustin Pop
    This is a multi-node call.
529 a8083063 Iustin Pop

530 72737a7f Iustin Pop
    @type node_list: list
531 72737a7f Iustin Pop
    @param node_list: the list of nodes to query
532 72737a7f Iustin Pop
    @type hypervisor_list: list
533 72737a7f Iustin Pop
    @param hypervisor_list: the hypervisors to query for instances
534 16abfbc2 Alexander Schreiber

535 72737a7f Iustin Pop
    """
536 9a525d83 Michael Hanselmann
    return self._MultiNodeCall(node_list, "instance_list", [hypervisor_list])
537 16abfbc2 Alexander Schreiber
538 72737a7f Iustin Pop
  def call_node_tcp_ping(self, node, source, target, port, timeout,
539 72737a7f Iustin Pop
                         live_port_needed):
540 72737a7f Iustin Pop
    """Do a TcpPing on the remote node
541 a8083063 Iustin Pop

542 72737a7f Iustin Pop
    This is a single-node call.
543 caad16e2 Iustin Pop

544 72737a7f Iustin Pop
    """
545 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "node_tcp_ping",
546 9a525d83 Michael Hanselmann
                                [source, target, port, timeout,
547 72737a7f Iustin Pop
                                 live_port_needed])
548 a8083063 Iustin Pop
549 caad16e2 Iustin Pop
  def call_node_has_ip_address(self, node, address):
550 caad16e2 Iustin Pop
    """Checks if a node has the given IP address.
551 caad16e2 Iustin Pop

552 caad16e2 Iustin Pop
    This is a single-node call.
553 caad16e2 Iustin Pop

554 caad16e2 Iustin Pop
    """
555 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "node_has_ip_address", [address])
556 a8083063 Iustin Pop
557 72737a7f Iustin Pop
  def call_node_info(self, node_list, vg_name, hypervisor_type):
558 72737a7f Iustin Pop
    """Return node information.
559 e69d05fd Iustin Pop

560 72737a7f Iustin Pop
    This will return memory information and volume group size and free
561 72737a7f Iustin Pop
    space.
562 a8083063 Iustin Pop

563 72737a7f Iustin Pop
    This is a multi-node call.
564 a8083063 Iustin Pop

565 72737a7f Iustin Pop
    @type node_list: list
566 72737a7f Iustin Pop
    @param node_list: the list of nodes to query
567 c41eea6e Iustin Pop
    @type vg_name: C{string}
568 c41eea6e Iustin Pop
    @param vg_name: the name of the volume group to ask for disk space
569 72737a7f Iustin Pop
        information
570 72737a7f Iustin Pop
    @type hypervisor_type: C{str}
571 72737a7f Iustin Pop
    @param hypervisor_type: the name of the hypervisor to ask for
572 72737a7f Iustin Pop
        memory information
573 a8083063 Iustin Pop

574 72737a7f Iustin Pop
    """
575 9a525d83 Michael Hanselmann
    retux = self._MultiNodeCall(node_list, "node_info",
576 9a525d83 Michael Hanselmann
                                [vg_name, hypervisor_type])
577 a8083063 Iustin Pop
578 781de953 Iustin Pop
    for result in retux.itervalues():
579 781de953 Iustin Pop
      if result.failed or not isinstance(result.data, dict):
580 781de953 Iustin Pop
        result.data = {}
581 186ec53c Iustin Pop
      if result.offline:
582 186ec53c Iustin Pop
        log_name = None
583 186ec53c Iustin Pop
      else:
584 186ec53c Iustin Pop
        log_name = "call_node_info"
585 781de953 Iustin Pop
586 781de953 Iustin Pop
      utils.CheckDict(result.data, {
587 781de953 Iustin Pop
        'memory_total' : '-',
588 781de953 Iustin Pop
        'memory_dom0' : '-',
589 781de953 Iustin Pop
        'memory_free' : '-',
590 781de953 Iustin Pop
        'vg_size' : 'node_unreachable',
591 781de953 Iustin Pop
        'vg_free' : '-',
592 186ec53c Iustin Pop
        }, log_name)
593 72737a7f Iustin Pop
    return retux
594 a8083063 Iustin Pop
595 72737a7f Iustin Pop
  def call_node_add(self, node, dsa, dsapub, rsa, rsapub, ssh, sshpub):
596 72737a7f Iustin Pop
    """Add a node to the cluster.
597 a8083063 Iustin Pop

598 72737a7f Iustin Pop
    This is a single-node call.
599 a8083063 Iustin Pop

600 72737a7f Iustin Pop
    """
601 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "node_add",
602 9a525d83 Michael Hanselmann
                                [dsa, dsapub, rsa, rsapub, ssh, sshpub])
603 a8083063 Iustin Pop
604 72737a7f Iustin Pop
  def call_node_verify(self, node_list, checkdict, cluster_name):
605 72737a7f Iustin Pop
    """Request verification of given parameters.
606 a8083063 Iustin Pop

607 72737a7f Iustin Pop
    This is a multi-node call.
608 a8083063 Iustin Pop

609 72737a7f Iustin Pop
    """
610 9a525d83 Michael Hanselmann
    return self._MultiNodeCall(node_list, "node_verify",
611 9a525d83 Michael Hanselmann
                               [checkdict, cluster_name])
612 a8083063 Iustin Pop
613 9a525d83 Michael Hanselmann
  @classmethod
614 9a525d83 Michael Hanselmann
  def call_node_start_master(cls, node, start_daemons):
615 72737a7f Iustin Pop
    """Tells a node to activate itself as a master.
616 a8083063 Iustin Pop

617 72737a7f Iustin Pop
    This is a single-node call.
618 a8083063 Iustin Pop

619 72737a7f Iustin Pop
    """
620 9a525d83 Michael Hanselmann
    return cls._StaticSingleNodeCall(node, "node_start_master",
621 9a525d83 Michael Hanselmann
                                     [start_daemons])
622 a8083063 Iustin Pop
623 9a525d83 Michael Hanselmann
  @classmethod
624 9a525d83 Michael Hanselmann
  def call_node_stop_master(cls, node, stop_daemons):
625 72737a7f Iustin Pop
    """Tells a node to demote itself from master status.
626 a8083063 Iustin Pop

627 72737a7f Iustin Pop
    This is a single-node call.
628 4e071d3b Iustin Pop

629 72737a7f Iustin Pop
    """
630 9a525d83 Michael Hanselmann
    return cls._StaticSingleNodeCall(node, "node_stop_master", [stop_daemons])
631 4e071d3b Iustin Pop
632 9a525d83 Michael Hanselmann
  @classmethod
633 9a525d83 Michael Hanselmann
  def call_master_info(cls, node_list):
634 72737a7f Iustin Pop
    """Query master info.
635 4e071d3b Iustin Pop

636 72737a7f Iustin Pop
    This is a multi-node call.
637 a8083063 Iustin Pop

638 72737a7f Iustin Pop
    """
639 72737a7f Iustin Pop
    # TODO: should this method query down nodes?
640 9a525d83 Michael Hanselmann
    return cls._StaticMultiNodeCall(node_list, "master_info", [])
641 a8083063 Iustin Pop
642 72737a7f Iustin Pop
  def call_version(self, node_list):
643 72737a7f Iustin Pop
    """Query node version.
644 a8083063 Iustin Pop

645 72737a7f Iustin Pop
    This is a multi-node call.
646 a8083063 Iustin Pop

647 72737a7f Iustin Pop
    """
648 9a525d83 Michael Hanselmann
    return self._MultiNodeCall(node_list, "version", [])
649 a8083063 Iustin Pop
650 72737a7f Iustin Pop
  def call_blockdev_create(self, node, bdev, size, owner, on_primary, info):
651 72737a7f Iustin Pop
    """Request creation of a given block device.
652 a8083063 Iustin Pop

653 72737a7f Iustin Pop
    This is a single-node call.
654 a8083063 Iustin Pop

655 72737a7f Iustin Pop
    """
656 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "blockdev_create",
657 9a525d83 Michael Hanselmann
                                [bdev.ToDict(), size, owner, on_primary, info])
658 a8083063 Iustin Pop
659 72737a7f Iustin Pop
  def call_blockdev_remove(self, node, bdev):
660 72737a7f Iustin Pop
    """Request removal of a given block device.
661 a8083063 Iustin Pop

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

664 72737a7f Iustin Pop
    """
665 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "blockdev_remove", [bdev.ToDict()])
666 f3e513ad Iustin Pop
667 72737a7f Iustin Pop
  def call_blockdev_rename(self, node, devlist):
668 72737a7f Iustin Pop
    """Request rename of the given block devices.
669 f3e513ad 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 self._SingleNodeCall(node, "blockdev_rename",
674 9a525d83 Michael Hanselmann
                                [(d.ToDict(), uid) for d, uid in devlist])
675 a8083063 Iustin Pop
676 72737a7f Iustin Pop
  def call_blockdev_assemble(self, node, disk, owner, on_primary):
677 72737a7f Iustin Pop
    """Request assembling of a given block device.
678 a8083063 Iustin Pop

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

681 72737a7f Iustin Pop
    """
682 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "blockdev_assemble",
683 9a525d83 Michael Hanselmann
                                [disk.ToDict(), owner, on_primary])
684 a8083063 Iustin Pop
685 72737a7f Iustin Pop
  def call_blockdev_shutdown(self, node, disk):
686 72737a7f Iustin Pop
    """Request shutdown of a given block device.
687 a8083063 Iustin Pop

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

690 72737a7f Iustin Pop
    """
691 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "blockdev_shutdown", [disk.ToDict()])
692 a8083063 Iustin Pop
693 72737a7f Iustin Pop
  def call_blockdev_addchildren(self, node, bdev, ndevs):
694 72737a7f Iustin Pop
    """Request adding a list of children to a (mirroring) device.
695 a8083063 Iustin Pop

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

698 72737a7f Iustin Pop
    """
699 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "blockdev_addchildren",
700 9a525d83 Michael Hanselmann
                                [bdev.ToDict(),
701 9a525d83 Michael Hanselmann
                                 [disk.ToDict() for disk in ndevs]])
702 a8083063 Iustin Pop
703 72737a7f Iustin Pop
  def call_blockdev_removechildren(self, node, bdev, ndevs):
704 72737a7f Iustin Pop
    """Request removing a list of children from a (mirroring) 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_removechildren",
710 9a525d83 Michael Hanselmann
                                [bdev.ToDict(),
711 9a525d83 Michael Hanselmann
                                 [disk.ToDict() for disk in ndevs]])
712 a8083063 Iustin Pop
713 72737a7f Iustin Pop
  def call_blockdev_getmirrorstatus(self, node, disks):
714 72737a7f Iustin Pop
    """Request status of a (mirroring) device.
715 a8083063 Iustin Pop

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

718 72737a7f Iustin Pop
    """
719 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "blockdev_getmirrorstatus",
720 9a525d83 Michael Hanselmann
                                [dsk.ToDict() for dsk in disks])
721 a8083063 Iustin Pop
722 72737a7f Iustin Pop
  def call_blockdev_find(self, node, disk):
723 72737a7f Iustin Pop
    """Request identification of a given block device.
724 72737a7f Iustin Pop

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

727 72737a7f Iustin Pop
    """
728 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "blockdev_find", [disk.ToDict()])
729 d61cbe76 Iustin Pop
730 b2e7666a Iustin Pop
  def call_blockdev_close(self, node, instance_name, disks):
731 72737a7f Iustin Pop
    """Closes the given block devices.
732 d61cbe76 Iustin Pop

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

735 72737a7f Iustin Pop
    """
736 b2e7666a Iustin Pop
    params = [instance_name, [cf.ToDict() for cf in disks]]
737 b2e7666a Iustin Pop
    return self._SingleNodeCall(node, "blockdev_close", params)
738 a8083063 Iustin Pop
739 6b93ec9d Iustin Pop
  def call_drbd_disconnect_net(self, node_list, nodes_ip, disks):
740 6b93ec9d Iustin Pop
    """Disconnects the network of the given drbd devices.
741 6b93ec9d Iustin Pop

742 6b93ec9d Iustin Pop
    This is a multi-node call.
743 6b93ec9d Iustin Pop

744 6b93ec9d Iustin Pop
    """
745 6b93ec9d Iustin Pop
    return self._MultiNodeCall(node_list, "drbd_disconnect_net",
746 6b93ec9d Iustin Pop
                               [nodes_ip, [cf.ToDict() for cf in disks]])
747 6b93ec9d Iustin Pop
748 6b93ec9d Iustin Pop
  def call_drbd_attach_net(self, node_list, nodes_ip,
749 6b93ec9d Iustin Pop
                           disks, instance_name, multimaster):
750 6b93ec9d Iustin Pop
    """Disconnects the given drbd devices.
751 6b93ec9d Iustin Pop

752 6b93ec9d Iustin Pop
    This is a multi-node call.
753 6b93ec9d Iustin Pop

754 6b93ec9d Iustin Pop
    """
755 6b93ec9d Iustin Pop
    return self._MultiNodeCall(node_list, "drbd_attach_net",
756 6b93ec9d Iustin Pop
                               [nodes_ip, [cf.ToDict() for cf in disks],
757 6b93ec9d Iustin Pop
                                instance_name, multimaster])
758 6b93ec9d Iustin Pop
759 6b93ec9d Iustin Pop
  def call_drbd_wait_sync(self, node_list, nodes_ip, disks):
760 6b93ec9d Iustin Pop
    """Waits for the synchronization of drbd devices is complete.
761 6b93ec9d Iustin Pop

762 6b93ec9d Iustin Pop
    This is a multi-node call.
763 6b93ec9d Iustin Pop

764 6b93ec9d Iustin Pop
    """
765 6b93ec9d Iustin Pop
    return self._MultiNodeCall(node_list, "drbd_wait_sync",
766 6b93ec9d Iustin Pop
                               [nodes_ip, [cf.ToDict() for cf in disks]])
767 6b93ec9d Iustin Pop
768 9a525d83 Michael Hanselmann
  @classmethod
769 9a525d83 Michael Hanselmann
  def call_upload_file(cls, node_list, file_name, address_list=None):
770 72737a7f Iustin Pop
    """Upload a file.
771 72737a7f Iustin Pop

772 72737a7f Iustin Pop
    The node will refuse the operation in case the file is not on the
773 72737a7f Iustin Pop
    approved file list.
774 72737a7f Iustin Pop

775 72737a7f Iustin Pop
    This is a multi-node call.
776 a8083063 Iustin Pop

777 6b294c53 Iustin Pop
    @type node_list: list
778 6b294c53 Iustin Pop
    @param node_list: the list of node names to upload to
779 6b294c53 Iustin Pop
    @type file_name: str
780 6b294c53 Iustin Pop
    @param file_name: the filename to upload
781 6b294c53 Iustin Pop
    @type address_list: list or None
782 6b294c53 Iustin Pop
    @keyword address_list: an optional list of node addresses, in order
783 6b294c53 Iustin Pop
        to optimize the RPC speed
784 6b294c53 Iustin Pop

785 72737a7f Iustin Pop
    """
786 12bce260 Michael Hanselmann
    file_contents = utils.ReadFile(file_name)
787 12bce260 Michael Hanselmann
    data = cls._Compress(file_contents)
788 72737a7f Iustin Pop
    st = os.stat(file_name)
789 72737a7f Iustin Pop
    params = [file_name, data, st.st_mode, st.st_uid, st.st_gid,
790 72737a7f Iustin Pop
              st.st_atime, st.st_mtime]
791 9a525d83 Michael Hanselmann
    return cls._StaticMultiNodeCall(node_list, "upload_file", params,
792 9a525d83 Michael Hanselmann
                                    address_list=address_list)
793 72737a7f Iustin Pop
794 6ddc95ec Michael Hanselmann
  @classmethod
795 03d1dba2 Michael Hanselmann
  def call_write_ssconf_files(cls, node_list, values):
796 6ddc95ec Michael Hanselmann
    """Write ssconf files.
797 6ddc95ec Michael Hanselmann

798 6ddc95ec Michael Hanselmann
    This is a multi-node call.
799 6ddc95ec Michael Hanselmann

800 6ddc95ec Michael Hanselmann
    """
801 03d1dba2 Michael Hanselmann
    return cls._StaticMultiNodeCall(node_list, "write_ssconf_files", [values])
802 6ddc95ec Michael Hanselmann
803 72737a7f Iustin Pop
  def call_os_diagnose(self, node_list):
804 72737a7f Iustin Pop
    """Request a diagnose of OS definitions.
805 72737a7f Iustin Pop

806 72737a7f Iustin Pop
    This is a multi-node call.
807 a8083063 Iustin Pop

808 72737a7f Iustin Pop
    """
809 9a525d83 Michael Hanselmann
    result = self._MultiNodeCall(node_list, "os_diagnose", [])
810 9a525d83 Michael Hanselmann
811 fab1e3a4 Iustin Pop
    for node_result in result.values():
812 781de953 Iustin Pop
      if not node_result.failed and node_result.data:
813 781de953 Iustin Pop
        node_result.data = [objects.OS.FromDict(oss)
814 781de953 Iustin Pop
                            for oss in node_result.data]
815 781de953 Iustin Pop
    return result
816 a8083063 Iustin Pop
817 72737a7f Iustin Pop
  def call_os_get(self, node, name):
818 72737a7f Iustin Pop
    """Returns an OS definition.
819 a8083063 Iustin Pop

820 72737a7f Iustin Pop
    This is a single-node call.
821 a8083063 Iustin Pop

822 72737a7f Iustin Pop
    """
823 9a525d83 Michael Hanselmann
    result = self._SingleNodeCall(node, "os_get", [name])
824 781de953 Iustin Pop
    if not result.failed and isinstance(result.data, dict):
825 781de953 Iustin Pop
      result.data = objects.OS.FromDict(result.data)
826 781de953 Iustin Pop
    return result
827 a8083063 Iustin Pop
828 72737a7f Iustin Pop
  def call_hooks_runner(self, node_list, hpath, phase, env):
829 72737a7f Iustin Pop
    """Call the hooks runner.
830 a8083063 Iustin Pop

831 72737a7f Iustin Pop
    Args:
832 72737a7f Iustin Pop
      - op: the OpCode instance
833 72737a7f Iustin Pop
      - env: a dictionary with the environment
834 a8083063 Iustin Pop

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

837 72737a7f Iustin Pop
    """
838 72737a7f Iustin Pop
    params = [hpath, phase, env]
839 9a525d83 Michael Hanselmann
    return self._MultiNodeCall(node_list, "hooks_runner", params)
840 a8083063 Iustin Pop
841 72737a7f Iustin Pop
  def call_iallocator_runner(self, node, name, idata):
842 72737a7f Iustin Pop
    """Call an iallocator on a remote node
843 8d528b7c Iustin Pop

844 72737a7f Iustin Pop
    Args:
845 72737a7f Iustin Pop
      - name: the iallocator name
846 72737a7f Iustin Pop
      - input: the json-encoded input string
847 8d528b7c Iustin Pop

848 72737a7f Iustin Pop
    This is a single-node call.
849 8d528b7c Iustin Pop

850 72737a7f Iustin Pop
    """
851 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "iallocator_runner", [name, idata])
852 8d528b7c Iustin Pop
853 72737a7f Iustin Pop
  def call_blockdev_grow(self, node, cf_bdev, amount):
854 72737a7f Iustin Pop
    """Request a snapshot of the given block device.
855 4c8ba8b3 Iustin Pop

856 72737a7f Iustin Pop
    This is a single-node call.
857 4c8ba8b3 Iustin Pop

858 72737a7f Iustin Pop
    """
859 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "blockdev_grow",
860 9a525d83 Michael Hanselmann
                                [cf_bdev.ToDict(), amount])
861 4c8ba8b3 Iustin Pop
862 72737a7f Iustin Pop
  def call_blockdev_snapshot(self, node, cf_bdev):
863 72737a7f Iustin Pop
    """Request a snapshot of the given block device.
864 a8083063 Iustin Pop

865 72737a7f Iustin Pop
    This is a single-node call.
866 a8083063 Iustin Pop

867 72737a7f Iustin Pop
    """
868 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "blockdev_snapshot", [cf_bdev.ToDict()])
869 a8083063 Iustin Pop
870 72737a7f Iustin Pop
  def call_snapshot_export(self, node, snap_bdev, dest_node, instance,
871 74c47259 Iustin Pop
                           cluster_name, idx):
872 72737a7f Iustin Pop
    """Request the export of a given snapshot.
873 a8083063 Iustin Pop

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

876 72737a7f Iustin Pop
    """
877 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "snapshot_export",
878 9a525d83 Michael Hanselmann
                                [snap_bdev.ToDict(), dest_node,
879 9a525d83 Michael Hanselmann
                                 self._InstDict(instance), cluster_name, idx])
880 a8083063 Iustin Pop
881 72737a7f Iustin Pop
  def call_finalize_export(self, node, instance, snap_disks):
882 72737a7f Iustin Pop
    """Request the completion of an export operation.
883 a8083063 Iustin Pop

884 72737a7f Iustin Pop
    This writes the export config file, etc.
885 a8083063 Iustin Pop

886 72737a7f Iustin Pop
    This is a single-node call.
887 a8083063 Iustin Pop

888 72737a7f Iustin Pop
    """
889 72737a7f Iustin Pop
    flat_disks = []
890 72737a7f Iustin Pop
    for disk in snap_disks:
891 72737a7f Iustin Pop
      flat_disks.append(disk.ToDict())
892 9a525d83 Michael Hanselmann
893 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "finalize_export",
894 9a525d83 Michael Hanselmann
                                [self._InstDict(instance), flat_disks])
895 a8083063 Iustin Pop
896 72737a7f Iustin Pop
  def call_export_info(self, node, path):
897 72737a7f Iustin Pop
    """Queries the export information in a given path.
898 a8083063 Iustin Pop

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

901 72737a7f Iustin Pop
    """
902 9a525d83 Michael Hanselmann
    result = self._SingleNodeCall(node, "export_info", [path])
903 781de953 Iustin Pop
    if not result.failed and result.data:
904 781de953 Iustin Pop
      result.data = objects.SerializableConfigParser.Loads(str(result.data))
905 781de953 Iustin Pop
    return result
906 a8083063 Iustin Pop
907 6c0af70e Guido Trotter
  def call_instance_os_import(self, node, inst, src_node, src_images,
908 6c0af70e Guido Trotter
                              cluster_name):
909 72737a7f Iustin Pop
    """Request the import of a backup into an instance.
910 a8083063 Iustin Pop

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

913 72737a7f Iustin Pop
    """
914 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "instance_os_import",
915 9a525d83 Michael Hanselmann
                                [self._InstDict(inst), src_node, src_images,
916 9a525d83 Michael Hanselmann
                                 cluster_name])
917 a8083063 Iustin Pop
918 72737a7f Iustin Pop
  def call_export_list(self, node_list):
919 72737a7f Iustin Pop
    """Gets the stored exports list.
920 a8083063 Iustin Pop

921 72737a7f Iustin Pop
    This is a multi-node call.
922 a8083063 Iustin Pop

923 72737a7f Iustin Pop
    """
924 9a525d83 Michael Hanselmann
    return self._MultiNodeCall(node_list, "export_list", [])
925 a8083063 Iustin Pop
926 72737a7f Iustin Pop
  def call_export_remove(self, node, export):
927 72737a7f Iustin Pop
    """Requests removal of a given export.
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, "export_remove", [export])
933 a8083063 Iustin Pop
934 9a525d83 Michael Hanselmann
  @classmethod
935 9a525d83 Michael Hanselmann
  def call_node_leave_cluster(cls, node):
936 72737a7f Iustin Pop
    """Requests a node to clean the cluster information it has.
937 a8083063 Iustin Pop

938 72737a7f Iustin Pop
    This will remove the configuration information from the ganeti data
939 72737a7f Iustin Pop
    dir.
940 a8083063 Iustin Pop

941 72737a7f Iustin Pop
    This is a single-node call.
942 a8083063 Iustin Pop

943 72737a7f Iustin Pop
    """
944 9a525d83 Michael Hanselmann
    return cls._StaticSingleNodeCall(node, "node_leave_cluster", [])
945 dcb93971 Michael Hanselmann
946 72737a7f Iustin Pop
  def call_node_volumes(self, node_list):
947 72737a7f Iustin Pop
    """Gets all volumes on node(s).
948 dcb93971 Michael Hanselmann

949 72737a7f Iustin Pop
    This is a multi-node call.
950 dcb93971 Michael Hanselmann

951 72737a7f Iustin Pop
    """
952 9a525d83 Michael Hanselmann
    return self._MultiNodeCall(node_list, "node_volumes", [])
953 06009e27 Iustin Pop
954 56aa9fd5 Iustin Pop
  def call_node_demote_from_mc(self, node):
955 56aa9fd5 Iustin Pop
    """Demote a node from the master candidate role.
956 56aa9fd5 Iustin Pop

957 56aa9fd5 Iustin Pop
    This is a single-node call.
958 56aa9fd5 Iustin Pop

959 56aa9fd5 Iustin Pop
    """
960 56aa9fd5 Iustin Pop
    return self._SingleNodeCall(node, "node_demote_from_mc", [])
961 56aa9fd5 Iustin Pop
962 72737a7f Iustin Pop
  def call_test_delay(self, node_list, duration):
963 72737a7f Iustin Pop
    """Sleep for a fixed time on given node(s).
964 06009e27 Iustin Pop

965 72737a7f Iustin Pop
    This is a multi-node call.
966 06009e27 Iustin Pop

967 72737a7f Iustin Pop
    """
968 9a525d83 Michael Hanselmann
    return self._MultiNodeCall(node_list, "test_delay", [duration])
969 5e04ed8b Manuel Franceschini
970 72737a7f Iustin Pop
  def call_file_storage_dir_create(self, node, file_storage_dir):
971 72737a7f Iustin Pop
    """Create the given file storage directory.
972 5e04ed8b Manuel Franceschini

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

975 72737a7f Iustin Pop
    """
976 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "file_storage_dir_create",
977 9a525d83 Michael Hanselmann
                                [file_storage_dir])
978 5e04ed8b Manuel Franceschini
979 72737a7f Iustin Pop
  def call_file_storage_dir_remove(self, node, file_storage_dir):
980 72737a7f Iustin Pop
    """Remove the given file storage directory.
981 5e04ed8b Manuel Franceschini

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

984 72737a7f Iustin Pop
    """
985 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "file_storage_dir_remove",
986 9a525d83 Michael Hanselmann
                                [file_storage_dir])
987 5e04ed8b Manuel Franceschini
988 72737a7f Iustin Pop
  def call_file_storage_dir_rename(self, node, old_file_storage_dir,
989 72737a7f Iustin Pop
                                   new_file_storage_dir):
990 72737a7f Iustin Pop
    """Rename file storage directory.
991 5e04ed8b Manuel Franceschini

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

994 72737a7f Iustin Pop
    """
995 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "file_storage_dir_rename",
996 9a525d83 Michael Hanselmann
                                [old_file_storage_dir, new_file_storage_dir])
997 ca52cdeb Michael Hanselmann
998 9a525d83 Michael Hanselmann
  @classmethod
999 9a525d83 Michael Hanselmann
  def call_jobqueue_update(cls, node_list, address_list, file_name, content):
1000 72737a7f Iustin Pop
    """Update job queue.
1001 ca52cdeb Michael Hanselmann

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

1004 72737a7f Iustin Pop
    """
1005 9a525d83 Michael Hanselmann
    return cls._StaticMultiNodeCall(node_list, "jobqueue_update",
1006 12bce260 Michael Hanselmann
                                    [file_name, cls._Compress(content)],
1007 9a525d83 Michael Hanselmann
                                    address_list=address_list)
1008 ca52cdeb Michael Hanselmann
1009 9a525d83 Michael Hanselmann
  @classmethod
1010 9a525d83 Michael Hanselmann
  def call_jobqueue_purge(cls, node):
1011 72737a7f Iustin Pop
    """Purge job queue.
1012 ca52cdeb Michael Hanselmann

1013 72737a7f Iustin Pop
    This is a single-node call.
1014 ca52cdeb Michael Hanselmann

1015 72737a7f Iustin Pop
    """
1016 9a525d83 Michael Hanselmann
    return cls._StaticSingleNodeCall(node, "jobqueue_purge", [])
1017 af5ebcb1 Michael Hanselmann
1018 9a525d83 Michael Hanselmann
  @classmethod
1019 dd875d32 Michael Hanselmann
  def call_jobqueue_rename(cls, node_list, address_list, rename):
1020 72737a7f Iustin Pop
    """Rename a job queue file.
1021 af5ebcb1 Michael Hanselmann

1022 72737a7f Iustin Pop
    This is a multi-node call.
1023 af5ebcb1 Michael Hanselmann

1024 72737a7f Iustin Pop
    """
1025 dd875d32 Michael Hanselmann
    return cls._StaticMultiNodeCall(node_list, "jobqueue_rename", rename,
1026 9a525d83 Michael Hanselmann
                                    address_list=address_list)
1027 6217e295 Iustin Pop
1028 9a525d83 Michael Hanselmann
  @classmethod
1029 9a525d83 Michael Hanselmann
  def call_jobqueue_set_drain(cls, node_list, drain_flag):
1030 5d672980 Iustin Pop
    """Set the drain flag on the queue.
1031 5d672980 Iustin Pop

1032 5d672980 Iustin Pop
    This is a multi-node call.
1033 5d672980 Iustin Pop

1034 5d672980 Iustin Pop
    @type node_list: list
1035 5d672980 Iustin Pop
    @param node_list: the list of nodes to query
1036 5d672980 Iustin Pop
    @type drain_flag: bool
1037 5d672980 Iustin Pop
    @param drain_flag: if True, will set the drain flag, otherwise reset it.
1038 5d672980 Iustin Pop

1039 5d672980 Iustin Pop
    """
1040 9a525d83 Michael Hanselmann
    return cls._StaticMultiNodeCall(node_list, "jobqueue_set_drain",
1041 9a525d83 Michael Hanselmann
                                    [drain_flag])
1042 5d672980 Iustin Pop
1043 6217e295 Iustin Pop
  def call_hypervisor_validate_params(self, node_list, hvname, hvparams):
1044 6217e295 Iustin Pop
    """Validate the hypervisor params.
1045 6217e295 Iustin Pop

1046 6217e295 Iustin Pop
    This is a multi-node call.
1047 6217e295 Iustin Pop

1048 6217e295 Iustin Pop
    @type node_list: list
1049 6217e295 Iustin Pop
    @param node_list: the list of nodes to query
1050 6217e295 Iustin Pop
    @type hvname: string
1051 6217e295 Iustin Pop
    @param hvname: the hypervisor name
1052 6217e295 Iustin Pop
    @type hvparams: dict
1053 6217e295 Iustin Pop
    @param hvparams: the hypervisor parameters to be validated
1054 6217e295 Iustin Pop

1055 6217e295 Iustin Pop
    """
1056 6217e295 Iustin Pop
    cluster = self._cfg.GetClusterInfo()
1057 6217e295 Iustin Pop
    hv_full = cluster.FillDict(cluster.hvparams.get(hvname, {}), hvparams)
1058 9a525d83 Michael Hanselmann
    return self._MultiNodeCall(node_list, "hypervisor_validate_params",
1059 9a525d83 Michael Hanselmann
                               [hvname, hv_full])