Statistics
| Branch: | Tag: | Revision:

root / lib / rpc.py @ 6af6270a

History | View | Annotate | Download (33.2 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 58b311ca Iustin Pop
import logging
35 12bce260 Michael Hanselmann
import zlib
36 12bce260 Michael Hanselmann
import base64
37 a8083063 Iustin Pop
38 a8083063 Iustin Pop
from ganeti import utils
39 a8083063 Iustin Pop
from ganeti import objects
40 ecfe9491 Michael Hanselmann
from ganeti import http
41 7c28c575 Michael Hanselmann
from ganeti import serializer
42 eafd8762 Michael Hanselmann
from ganeti import constants
43 781de953 Iustin Pop
from ganeti import errors
44 a8083063 Iustin Pop
45 ae88ef45 Michael Hanselmann
import ganeti.http.client
46 ae88ef45 Michael Hanselmann
47 a8083063 Iustin Pop
48 4331f6cd Michael Hanselmann
# Module level variable
49 4331f6cd Michael Hanselmann
_http_manager = None
50 4331f6cd Michael Hanselmann
51 4331f6cd Michael Hanselmann
52 4331f6cd Michael Hanselmann
def Init():
53 4331f6cd Michael Hanselmann
  """Initializes the module-global HTTP client manager.
54 4331f6cd Michael Hanselmann

55 4331f6cd Michael Hanselmann
  Must be called before using any RPC function.
56 4331f6cd Michael Hanselmann

57 4331f6cd Michael Hanselmann
  """
58 4331f6cd Michael Hanselmann
  global _http_manager
59 4331f6cd Michael Hanselmann
60 4331f6cd Michael Hanselmann
  assert not _http_manager, "RPC module initialized more than once"
61 4331f6cd Michael Hanselmann
62 ae88ef45 Michael Hanselmann
  _http_manager = http.client.HttpClientManager()
63 4331f6cd Michael Hanselmann
64 4331f6cd Michael Hanselmann
65 4331f6cd Michael Hanselmann
def Shutdown():
66 4331f6cd Michael Hanselmann
  """Stops the module-global HTTP client manager.
67 4331f6cd Michael Hanselmann

68 4331f6cd Michael Hanselmann
  Must be called before quitting the program.
69 4331f6cd Michael Hanselmann

70 4331f6cd Michael Hanselmann
  """
71 4331f6cd Michael Hanselmann
  global _http_manager
72 4331f6cd Michael Hanselmann
73 4331f6cd Michael Hanselmann
  if _http_manager:
74 4331f6cd Michael Hanselmann
    _http_manager.Shutdown()
75 4331f6cd Michael Hanselmann
    _http_manager = None
76 4331f6cd Michael Hanselmann
77 4331f6cd Michael Hanselmann
78 781de953 Iustin Pop
class RpcResult(object):
79 781de953 Iustin Pop
  """RPC Result class.
80 781de953 Iustin Pop

81 781de953 Iustin Pop
  This class holds an RPC result. It is needed since in multi-node
82 781de953 Iustin Pop
  calls we can't raise an exception just because one one out of many
83 781de953 Iustin Pop
  failed, and therefore we use this class to encapsulate the result.
84 781de953 Iustin Pop

85 5bbd3f7f Michael Hanselmann
  @ivar data: the data payload, for successful results, or None
86 ed83f5cc Iustin Pop
  @type failed: boolean
87 ed83f5cc Iustin Pop
  @ivar failed: whether the operation failed at RPC level (not
88 ed83f5cc Iustin Pop
      application level on the remote node)
89 ed83f5cc Iustin Pop
  @ivar call: the name of the RPC call
90 ed83f5cc Iustin Pop
  @ivar node: the name of the node to which we made the call
91 ed83f5cc Iustin Pop
  @ivar offline: whether the operation failed because the node was
92 ed83f5cc Iustin Pop
      offline, as opposed to actual failure; offline=True will always
93 ed83f5cc Iustin Pop
      imply failed=True, in order to allow simpler checking if
94 ed83f5cc Iustin Pop
      the user doesn't care about the exact failure mode
95 ed83f5cc Iustin Pop

96 781de953 Iustin Pop
  """
97 ed83f5cc Iustin Pop
  def __init__(self, data=None, failed=False, offline=False,
98 ed83f5cc Iustin Pop
               call=None, node=None):
99 781de953 Iustin Pop
    self.failed = failed
100 ed83f5cc Iustin Pop
    self.offline = offline
101 ed83f5cc Iustin Pop
    self.call = call
102 ed83f5cc Iustin Pop
    self.node = node
103 ed83f5cc Iustin Pop
    if offline:
104 ed83f5cc Iustin Pop
      self.failed = True
105 ed83f5cc Iustin Pop
      self.error = "Node is marked offline"
106 f2def43a Iustin Pop
      self.data = self.payload = None
107 ed83f5cc Iustin Pop
    elif failed:
108 781de953 Iustin Pop
      self.error = data
109 f2def43a Iustin Pop
      self.data = self.payload = None
110 781de953 Iustin Pop
    else:
111 781de953 Iustin Pop
      self.data = data
112 781de953 Iustin Pop
      self.error = None
113 f2def43a Iustin Pop
      if isinstance(data, (tuple, list)) and len(data) == 2:
114 f2def43a Iustin Pop
        self.payload = data[1]
115 f2def43a Iustin Pop
      else:
116 f2def43a Iustin Pop
        self.payload = None
117 781de953 Iustin Pop
118 781de953 Iustin Pop
  def Raise(self):
119 781de953 Iustin Pop
    """If the result has failed, raise an OpExecError.
120 781de953 Iustin Pop

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

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

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

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

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

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

163 5bbd3f7f Michael Hanselmann
  One current bug is that generic failure is still signaled by
164 a8083063 Iustin Pop
  'False' result, which is not good. This overloading of values can
165 a8083063 Iustin Pop
  cause bugs.
166 a8083063 Iustin Pop

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

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

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

199 bdf7d8c0 Iustin Pop
    @type name: str
200 bdf7d8c0 Iustin Pop
    @param name: the node name
201 bdf7d8c0 Iustin Pop
    @type address: str
202 bdf7d8c0 Iustin Pop
    @keyword address: the node address, if known
203 bdf7d8c0 Iustin Pop

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

218 ecfe9491 Michael Hanselmann
    @rtype: list
219 5fcc718f Iustin Pop
    @return: List of RPC results
220 a8083063 Iustin Pop

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

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

258 72737a7f Iustin Pop
    """
259 72737a7f Iustin Pop
    self._cfg = cfg
260 160e2921 Iustin Pop
    self.port = utils.GetNodeDaemonPort()
261 a8083063 Iustin Pop
262 0eca8e0c Iustin Pop
  def _InstDict(self, instance, hvp=None, bep=None):
263 26ba2bd8 Iustin Pop
    """Convert the given instance to a dict.
264 26ba2bd8 Iustin Pop

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

268 26ba2bd8 Iustin Pop
    @type instance: L{objects.Instance}
269 26ba2bd8 Iustin Pop
    @param instance: an Instance object
270 0eca8e0c Iustin Pop
    @type hvp: dict or None
271 5bbd3f7f Michael Hanselmann
    @param hvp: a dictionary with overridden hypervisor parameters
272 0eca8e0c Iustin Pop
    @type bep: dict or None
273 5bbd3f7f Michael Hanselmann
    @param bep: a dictionary with overridden backend parameters
274 26ba2bd8 Iustin Pop
    @rtype: dict
275 26ba2bd8 Iustin Pop
    @return: the instance dict, with the hvparams filled with the
276 26ba2bd8 Iustin Pop
        cluster defaults
277 26ba2bd8 Iustin Pop

278 26ba2bd8 Iustin Pop
    """
279 26ba2bd8 Iustin Pop
    idict = instance.ToDict()
280 5b442704 Iustin Pop
    cluster = self._cfg.GetClusterInfo()
281 5b442704 Iustin Pop
    idict["hvparams"] = cluster.FillHV(instance)
282 0eca8e0c Iustin Pop
    if hvp is not None:
283 0eca8e0c Iustin Pop
      idict["hvparams"].update(hvp)
284 5b442704 Iustin Pop
    idict["beparams"] = cluster.FillBE(instance)
285 0eca8e0c Iustin Pop
    if bep is not None:
286 0eca8e0c Iustin Pop
      idict["beparams"].update(bep)
287 26ba2bd8 Iustin Pop
    return idict
288 26ba2bd8 Iustin Pop
289 84b45587 Iustin Pop
  def _ConnectList(self, client, node_list, call):
290 25348212 Iustin Pop
    """Helper for computing node addresses.
291 25348212 Iustin Pop

292 6af6270a Iustin Pop
    @type client: L{ganeti.rpc.Client}
293 25348212 Iustin Pop
    @param client: a C{Client} instance
294 25348212 Iustin Pop
    @type node_list: list
295 25348212 Iustin Pop
    @param node_list: the node list we should connect
296 84b45587 Iustin Pop
    @type call: string
297 84b45587 Iustin Pop
    @param call: the name of the remote procedure call, for filling in
298 84b45587 Iustin Pop
        correctly any eventual offline nodes' results
299 25348212 Iustin Pop

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

322 6af6270a Iustin Pop
    @type client: L{ganeti.rpc.Client}
323 25348212 Iustin Pop
    @param client: a C{Client} instance
324 25348212 Iustin Pop
    @type node: str
325 25348212 Iustin Pop
    @param node: the node we should connect
326 84b45587 Iustin Pop
    @type call: string
327 84b45587 Iustin Pop
    @param call: the name of the remote procedure call, for filling in
328 84b45587 Iustin Pop
        correctly any eventual offline nodes' results
329 25348212 Iustin Pop

330 25348212 Iustin Pop
    """
331 25348212 Iustin Pop
    node_info = self._cfg.GetNodeInfo(node)
332 25348212 Iustin Pop
    if node_info is not None:
333 ed83f5cc Iustin Pop
      if node_info.offline:
334 84b45587 Iustin Pop
        return RpcResult(node=node, offline=True, call=call)
335 25348212 Iustin Pop
      addr = node_info.primary_ip
336 25348212 Iustin Pop
    else:
337 25348212 Iustin Pop
      addr = None
338 25348212 Iustin Pop
    client.ConnectNode(node, address=addr)
339 25348212 Iustin Pop
340 ed83f5cc Iustin Pop
  def _MultiNodeCall(self, node_list, procedure, args):
341 160e2921 Iustin Pop
    """Helper for making a multi-node call
342 160e2921 Iustin Pop

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

355 160e2921 Iustin Pop
    """
356 160e2921 Iustin Pop
    body = serializer.DumpJson(args, indent=False)
357 160e2921 Iustin Pop
    c = Client(procedure, body, utils.GetNodeDaemonPort())
358 9a525d83 Michael Hanselmann
    c.ConnectList(node_list, address_list=address_list)
359 9a525d83 Michael Hanselmann
    return c.GetResults()
360 9a525d83 Michael Hanselmann
361 9a525d83 Michael Hanselmann
  def _SingleNodeCall(self, node, procedure, args):
362 160e2921 Iustin Pop
    """Helper for making a single-node call
363 9a525d83 Michael Hanselmann

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

377 9a525d83 Michael Hanselmann
    """
378 160e2921 Iustin Pop
    body = serializer.DumpJson(args, indent=False)
379 160e2921 Iustin Pop
    c = Client(procedure, body, utils.GetNodeDaemonPort())
380 3097c858 Michael Hanselmann
    c.ConnectNode(node)
381 ed83f5cc Iustin Pop
    return c.GetResults()[node]
382 9a525d83 Michael Hanselmann
383 12bce260 Michael Hanselmann
  @staticmethod
384 12bce260 Michael Hanselmann
  def _Compress(data):
385 12bce260 Michael Hanselmann
    """Compresses a string for transport over RPC.
386 12bce260 Michael Hanselmann

387 12bce260 Michael Hanselmann
    Small amounts of data are not compressed.
388 12bce260 Michael Hanselmann

389 12bce260 Michael Hanselmann
    @type data: str
390 12bce260 Michael Hanselmann
    @param data: Data
391 12bce260 Michael Hanselmann
    @rtype: tuple
392 12bce260 Michael Hanselmann
    @return: Encoded data to send
393 12bce260 Michael Hanselmann

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

410 72737a7f Iustin Pop
    This is a multi-node call.
411 a8083063 Iustin Pop

412 72737a7f Iustin Pop
    """
413 9a525d83 Michael Hanselmann
    return self._MultiNodeCall(node_list, "volume_list", [vg_name])
414 a8083063 Iustin Pop
415 72737a7f Iustin Pop
  def call_vg_list(self, node_list):
416 72737a7f Iustin Pop
    """Gets the volume group list.
417 a8083063 Iustin Pop

418 72737a7f Iustin Pop
    This is a multi-node call.
419 a8083063 Iustin Pop

420 72737a7f Iustin Pop
    """
421 9a525d83 Michael Hanselmann
    return self._MultiNodeCall(node_list, "vg_list", [])
422 a8083063 Iustin Pop
423 72737a7f Iustin Pop
  def call_bridges_exist(self, node, bridges_list):
424 72737a7f Iustin Pop
    """Checks if a node has all the bridges given.
425 a8083063 Iustin Pop

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

430 72737a7f Iustin Pop
    This is a single-node call.
431 a8083063 Iustin Pop

432 72737a7f Iustin Pop
    """
433 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "bridges_exist", [bridges_list])
434 a8083063 Iustin Pop
435 0eca8e0c Iustin Pop
  def call_instance_start(self, node, instance, hvp, bep):
436 72737a7f Iustin Pop
    """Starts an instance.
437 a8083063 Iustin Pop

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

440 72737a7f Iustin Pop
    """
441 0eca8e0c Iustin Pop
    idict = self._InstDict(instance, hvp=hvp, bep=bep)
442 0eca8e0c Iustin Pop
    return self._SingleNodeCall(node, "instance_start", [idict])
443 a8083063 Iustin Pop
444 72737a7f Iustin Pop
  def call_instance_shutdown(self, node, instance):
445 72737a7f Iustin Pop
    """Stops an instance.
446 a8083063 Iustin Pop

447 72737a7f Iustin Pop
    This is a single-node call.
448 2a10865c Iustin Pop

449 72737a7f Iustin Pop
    """
450 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "instance_shutdown",
451 9a525d83 Michael Hanselmann
                                [self._InstDict(instance)])
452 2a10865c Iustin Pop
453 6906a9d8 Guido Trotter
  def call_migration_info(self, node, instance):
454 6906a9d8 Guido Trotter
    """Gather the information necessary to prepare an instance migration.
455 6906a9d8 Guido Trotter

456 6906a9d8 Guido Trotter
    This is a single-node call.
457 6906a9d8 Guido Trotter

458 6906a9d8 Guido Trotter
    @type node: string
459 6906a9d8 Guido Trotter
    @param node: the node on which the instance is currently running
460 6906a9d8 Guido Trotter
    @type instance: C{objects.Instance}
461 6906a9d8 Guido Trotter
    @param instance: the instance definition
462 6906a9d8 Guido Trotter

463 6906a9d8 Guido Trotter
    """
464 6906a9d8 Guido Trotter
    return self._SingleNodeCall(node, "migration_info",
465 6906a9d8 Guido Trotter
                                [self._InstDict(instance)])
466 6906a9d8 Guido Trotter
467 6906a9d8 Guido Trotter
  def call_accept_instance(self, node, instance, info, target):
468 6906a9d8 Guido Trotter
    """Prepare a node to accept an instance.
469 6906a9d8 Guido Trotter

470 6906a9d8 Guido Trotter
    This is a single-node call.
471 6906a9d8 Guido Trotter

472 6906a9d8 Guido Trotter
    @type node: string
473 6906a9d8 Guido Trotter
    @param node: the target node for the migration
474 6906a9d8 Guido Trotter
    @type instance: C{objects.Instance}
475 6906a9d8 Guido Trotter
    @param instance: the instance definition
476 6906a9d8 Guido Trotter
    @type info: opaque/hypervisor specific (string/data)
477 6906a9d8 Guido Trotter
    @param info: result for the call_migration_info call
478 6906a9d8 Guido Trotter
    @type target: string
479 6906a9d8 Guido Trotter
    @param target: target hostname (usually ip address) (on the node itself)
480 6906a9d8 Guido Trotter

481 6906a9d8 Guido Trotter
    """
482 6906a9d8 Guido Trotter
    return self._SingleNodeCall(node, "accept_instance",
483 6906a9d8 Guido Trotter
                                [self._InstDict(instance), info, target])
484 6906a9d8 Guido Trotter
485 6906a9d8 Guido Trotter
  def call_finalize_migration(self, node, instance, info, success):
486 6906a9d8 Guido Trotter
    """Finalize any target-node migration specific operation.
487 6906a9d8 Guido Trotter

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

491 6906a9d8 Guido Trotter
    This is a single-node call.
492 6906a9d8 Guido Trotter

493 6906a9d8 Guido Trotter
    @type node: string
494 6906a9d8 Guido Trotter
    @param node: the target node for the migration
495 6906a9d8 Guido Trotter
    @type instance: C{objects.Instance}
496 6906a9d8 Guido Trotter
    @param instance: the instance definition
497 6906a9d8 Guido Trotter
    @type info: opaque/hypervisor specific (string/data)
498 6906a9d8 Guido Trotter
    @param info: result for the call_migration_info call
499 6906a9d8 Guido Trotter
    @type success: boolean
500 6906a9d8 Guido Trotter
    @param success: whether the migration was a success or a failure
501 6906a9d8 Guido Trotter

502 6906a9d8 Guido Trotter
    """
503 6906a9d8 Guido Trotter
    return self._SingleNodeCall(node, "finalize_migration",
504 6906a9d8 Guido Trotter
                                [self._InstDict(instance), info, success])
505 6906a9d8 Guido Trotter
506 72737a7f Iustin Pop
  def call_instance_migrate(self, node, instance, target, live):
507 72737a7f Iustin Pop
    """Migrate an instance.
508 2a10865c Iustin Pop

509 72737a7f Iustin Pop
    This is a single-node call.
510 2a10865c Iustin Pop

511 72737a7f Iustin Pop
    @type node: string
512 72737a7f Iustin Pop
    @param node: the node on which the instance is currently running
513 72737a7f Iustin Pop
    @type instance: C{objects.Instance}
514 72737a7f Iustin Pop
    @param instance: the instance definition
515 72737a7f Iustin Pop
    @type target: string
516 72737a7f Iustin Pop
    @param target: the target node name
517 72737a7f Iustin Pop
    @type live: boolean
518 72737a7f Iustin Pop
    @param live: whether the migration should be done live or not (the
519 72737a7f Iustin Pop
        interpretation of this parameter is left to the hypervisor)
520 007a2f3e Alexander Schreiber

521 72737a7f Iustin Pop
    """
522 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "instance_migrate",
523 9a525d83 Michael Hanselmann
                                [self._InstDict(instance), target, live])
524 007a2f3e Alexander Schreiber
525 07813a9e Iustin Pop
  def call_instance_reboot(self, node, instance, reboot_type):
526 72737a7f Iustin Pop
    """Reboots an instance.
527 007a2f3e Alexander Schreiber

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

530 72737a7f Iustin Pop
    """
531 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "instance_reboot",
532 07813a9e Iustin Pop
                                [self._InstDict(instance), reboot_type])
533 a8083063 Iustin Pop
534 d15a9ad3 Guido Trotter
  def call_instance_os_add(self, node, inst):
535 72737a7f Iustin Pop
    """Installs an OS on the given instance.
536 a8083063 Iustin Pop

537 72737a7f Iustin Pop
    This is a single-node call.
538 decd5f45 Iustin Pop

539 72737a7f Iustin Pop
    """
540 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "instance_os_add",
541 9a525d83 Michael Hanselmann
                                [self._InstDict(inst)])
542 decd5f45 Iustin Pop
543 d15a9ad3 Guido Trotter
  def call_instance_run_rename(self, node, inst, old_name):
544 72737a7f Iustin Pop
    """Run the OS rename script for an instance.
545 decd5f45 Iustin Pop

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

548 72737a7f Iustin Pop
    """
549 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "instance_run_rename",
550 9a525d83 Michael Hanselmann
                                [self._InstDict(inst), old_name])
551 a8083063 Iustin Pop
552 72737a7f Iustin Pop
  def call_instance_info(self, node, instance, hname):
553 72737a7f Iustin Pop
    """Returns information about a single instance.
554 a8083063 Iustin Pop

555 72737a7f Iustin Pop
    This is a single-node call.
556 a8083063 Iustin Pop

557 9a525d83 Michael Hanselmann
    @type node: list
558 9a525d83 Michael Hanselmann
    @param node: the list of nodes to query
559 72737a7f Iustin Pop
    @type instance: string
560 72737a7f Iustin Pop
    @param instance: the instance name
561 72737a7f Iustin Pop
    @type hname: string
562 72737a7f Iustin Pop
    @param hname: the hypervisor type of the instance
563 a8083063 Iustin Pop

564 72737a7f Iustin Pop
    """
565 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "instance_info", [instance, hname])
566 e69d05fd Iustin Pop
567 56e7640c Iustin Pop
  def call_instance_migratable(self, node, instance):
568 56e7640c Iustin Pop
    """Checks whether the given instance can be migrated.
569 56e7640c Iustin Pop

570 56e7640c Iustin Pop
    This is a single-node call.
571 56e7640c Iustin Pop

572 56e7640c Iustin Pop
    @param node: the node to query
573 56e7640c Iustin Pop
    @type instance: L{objects.Instance}
574 56e7640c Iustin Pop
    @param instance: the instance to check
575 56e7640c Iustin Pop

576 56e7640c Iustin Pop

577 56e7640c Iustin Pop
    """
578 56e7640c Iustin Pop
    return self._SingleNodeCall(node, "instance_migratable",
579 56e7640c Iustin Pop
                                [self._InstDict(instance)])
580 56e7640c Iustin Pop
581 72737a7f Iustin Pop
  def call_all_instances_info(self, node_list, hypervisor_list):
582 72737a7f Iustin Pop
    """Returns information about all instances on the given nodes.
583 a8083063 Iustin Pop

584 72737a7f Iustin Pop
    This is a multi-node call.
585 a8083063 Iustin Pop

586 72737a7f Iustin Pop
    @type node_list: list
587 72737a7f Iustin Pop
    @param node_list: the list of nodes to query
588 72737a7f Iustin Pop
    @type hypervisor_list: list
589 72737a7f Iustin Pop
    @param hypervisor_list: the hypervisors to query for instances
590 a8083063 Iustin Pop

591 72737a7f Iustin Pop
    """
592 9a525d83 Michael Hanselmann
    return self._MultiNodeCall(node_list, "all_instances_info",
593 9a525d83 Michael Hanselmann
                               [hypervisor_list])
594 e69d05fd Iustin Pop
595 72737a7f Iustin Pop
  def call_instance_list(self, node_list, hypervisor_list):
596 72737a7f Iustin Pop
    """Returns the list of running instances on a given node.
597 a8083063 Iustin Pop

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

600 72737a7f Iustin Pop
    @type node_list: list
601 72737a7f Iustin Pop
    @param node_list: the list of nodes to query
602 72737a7f Iustin Pop
    @type hypervisor_list: list
603 72737a7f Iustin Pop
    @param hypervisor_list: the hypervisors to query for instances
604 16abfbc2 Alexander Schreiber

605 72737a7f Iustin Pop
    """
606 9a525d83 Michael Hanselmann
    return self._MultiNodeCall(node_list, "instance_list", [hypervisor_list])
607 16abfbc2 Alexander Schreiber
608 72737a7f Iustin Pop
  def call_node_tcp_ping(self, node, source, target, port, timeout,
609 72737a7f Iustin Pop
                         live_port_needed):
610 72737a7f Iustin Pop
    """Do a TcpPing on the remote node
611 a8083063 Iustin Pop

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

614 72737a7f Iustin Pop
    """
615 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "node_tcp_ping",
616 9a525d83 Michael Hanselmann
                                [source, target, port, timeout,
617 72737a7f Iustin Pop
                                 live_port_needed])
618 a8083063 Iustin Pop
619 caad16e2 Iustin Pop
  def call_node_has_ip_address(self, node, address):
620 caad16e2 Iustin Pop
    """Checks if a node has the given IP address.
621 caad16e2 Iustin Pop

622 caad16e2 Iustin Pop
    This is a single-node call.
623 caad16e2 Iustin Pop

624 caad16e2 Iustin Pop
    """
625 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "node_has_ip_address", [address])
626 a8083063 Iustin Pop
627 72737a7f Iustin Pop
  def call_node_info(self, node_list, vg_name, hypervisor_type):
628 72737a7f Iustin Pop
    """Return node information.
629 e69d05fd Iustin Pop

630 72737a7f Iustin Pop
    This will return memory information and volume group size and free
631 72737a7f Iustin Pop
    space.
632 a8083063 Iustin Pop

633 72737a7f Iustin Pop
    This is a multi-node call.
634 a8083063 Iustin Pop

635 72737a7f Iustin Pop
    @type node_list: list
636 72737a7f Iustin Pop
    @param node_list: the list of nodes to query
637 c41eea6e Iustin Pop
    @type vg_name: C{string}
638 c41eea6e Iustin Pop
    @param vg_name: the name of the volume group to ask for disk space
639 72737a7f Iustin Pop
        information
640 72737a7f Iustin Pop
    @type hypervisor_type: C{str}
641 72737a7f Iustin Pop
    @param hypervisor_type: the name of the hypervisor to ask for
642 72737a7f Iustin Pop
        memory information
643 a8083063 Iustin Pop

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

668 72737a7f Iustin Pop
    This is a single-node call.
669 a8083063 Iustin Pop

670 72737a7f Iustin Pop
    """
671 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "node_add",
672 9a525d83 Michael Hanselmann
                                [dsa, dsapub, rsa, rsapub, ssh, sshpub])
673 a8083063 Iustin Pop
674 72737a7f Iustin Pop
  def call_node_verify(self, node_list, checkdict, cluster_name):
675 72737a7f Iustin Pop
    """Request verification of given parameters.
676 a8083063 Iustin Pop

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

679 72737a7f Iustin Pop
    """
680 9a525d83 Michael Hanselmann
    return self._MultiNodeCall(node_list, "node_verify",
681 9a525d83 Michael Hanselmann
                               [checkdict, cluster_name])
682 a8083063 Iustin Pop
683 9a525d83 Michael Hanselmann
  @classmethod
684 9a525d83 Michael Hanselmann
  def call_node_start_master(cls, node, start_daemons):
685 72737a7f Iustin Pop
    """Tells a node to activate itself as a master.
686 a8083063 Iustin Pop

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

689 72737a7f Iustin Pop
    """
690 9a525d83 Michael Hanselmann
    return cls._StaticSingleNodeCall(node, "node_start_master",
691 9a525d83 Michael Hanselmann
                                     [start_daemons])
692 a8083063 Iustin Pop
693 9a525d83 Michael Hanselmann
  @classmethod
694 9a525d83 Michael Hanselmann
  def call_node_stop_master(cls, node, stop_daemons):
695 72737a7f Iustin Pop
    """Tells a node to demote itself from master status.
696 a8083063 Iustin Pop

697 72737a7f Iustin Pop
    This is a single-node call.
698 4e071d3b Iustin Pop

699 72737a7f Iustin Pop
    """
700 9a525d83 Michael Hanselmann
    return cls._StaticSingleNodeCall(node, "node_stop_master", [stop_daemons])
701 4e071d3b Iustin Pop
702 9a525d83 Michael Hanselmann
  @classmethod
703 9a525d83 Michael Hanselmann
  def call_master_info(cls, node_list):
704 72737a7f Iustin Pop
    """Query master info.
705 4e071d3b Iustin Pop

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

708 72737a7f Iustin Pop
    """
709 72737a7f Iustin Pop
    # TODO: should this method query down nodes?
710 9a525d83 Michael Hanselmann
    return cls._StaticMultiNodeCall(node_list, "master_info", [])
711 a8083063 Iustin Pop
712 72737a7f Iustin Pop
  def call_version(self, node_list):
713 72737a7f Iustin Pop
    """Query node version.
714 a8083063 Iustin Pop

715 72737a7f Iustin Pop
    This is a multi-node call.
716 a8083063 Iustin Pop

717 72737a7f Iustin Pop
    """
718 9a525d83 Michael Hanselmann
    return self._MultiNodeCall(node_list, "version", [])
719 a8083063 Iustin Pop
720 72737a7f Iustin Pop
  def call_blockdev_create(self, node, bdev, size, owner, on_primary, info):
721 72737a7f Iustin Pop
    """Request creation of a given block device.
722 a8083063 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_create",
727 9a525d83 Michael Hanselmann
                                [bdev.ToDict(), size, owner, on_primary, info])
728 a8083063 Iustin Pop
729 72737a7f Iustin Pop
  def call_blockdev_remove(self, node, bdev):
730 72737a7f Iustin Pop
    """Request removal of a given block device.
731 a8083063 Iustin Pop

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

734 72737a7f Iustin Pop
    """
735 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "blockdev_remove", [bdev.ToDict()])
736 f3e513ad Iustin Pop
737 72737a7f Iustin Pop
  def call_blockdev_rename(self, node, devlist):
738 72737a7f Iustin Pop
    """Request rename of the given block devices.
739 f3e513ad Iustin Pop

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

742 72737a7f Iustin Pop
    """
743 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "blockdev_rename",
744 9a525d83 Michael Hanselmann
                                [(d.ToDict(), uid) for d, uid in devlist])
745 a8083063 Iustin Pop
746 72737a7f Iustin Pop
  def call_blockdev_assemble(self, node, disk, owner, on_primary):
747 72737a7f Iustin Pop
    """Request assembling of a given block 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_assemble",
753 9a525d83 Michael Hanselmann
                                [disk.ToDict(), owner, on_primary])
754 a8083063 Iustin Pop
755 72737a7f Iustin Pop
  def call_blockdev_shutdown(self, node, disk):
756 72737a7f Iustin Pop
    """Request shutdown of a given block device.
757 a8083063 Iustin Pop

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

760 72737a7f Iustin Pop
    """
761 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "blockdev_shutdown", [disk.ToDict()])
762 a8083063 Iustin Pop
763 72737a7f Iustin Pop
  def call_blockdev_addchildren(self, node, bdev, ndevs):
764 72737a7f Iustin Pop
    """Request adding a list of children to a (mirroring) device.
765 a8083063 Iustin Pop

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

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

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

778 72737a7f Iustin Pop
    """
779 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "blockdev_removechildren",
780 9a525d83 Michael Hanselmann
                                [bdev.ToDict(),
781 9a525d83 Michael Hanselmann
                                 [disk.ToDict() for disk in ndevs]])
782 a8083063 Iustin Pop
783 72737a7f Iustin Pop
  def call_blockdev_getmirrorstatus(self, node, disks):
784 72737a7f Iustin Pop
    """Request status of a (mirroring) device.
785 a8083063 Iustin Pop

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

788 72737a7f Iustin Pop
    """
789 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "blockdev_getmirrorstatus",
790 9a525d83 Michael Hanselmann
                                [dsk.ToDict() for dsk in disks])
791 a8083063 Iustin Pop
792 72737a7f Iustin Pop
  def call_blockdev_find(self, node, disk):
793 72737a7f Iustin Pop
    """Request identification of a given block device.
794 72737a7f Iustin Pop

795 72737a7f Iustin Pop
    This is a single-node call.
796 a8083063 Iustin Pop

797 72737a7f Iustin Pop
    """
798 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "blockdev_find", [disk.ToDict()])
799 d61cbe76 Iustin Pop
800 b2e7666a Iustin Pop
  def call_blockdev_close(self, node, instance_name, disks):
801 72737a7f Iustin Pop
    """Closes the given block devices.
802 d61cbe76 Iustin Pop

803 72737a7f Iustin Pop
    This is a single-node call.
804 d61cbe76 Iustin Pop

805 72737a7f Iustin Pop
    """
806 b2e7666a Iustin Pop
    params = [instance_name, [cf.ToDict() for cf in disks]]
807 b2e7666a Iustin Pop
    return self._SingleNodeCall(node, "blockdev_close", params)
808 a8083063 Iustin Pop
809 6b93ec9d Iustin Pop
  def call_drbd_disconnect_net(self, node_list, nodes_ip, disks):
810 6b93ec9d Iustin Pop
    """Disconnects the network of the given drbd devices.
811 6b93ec9d Iustin Pop

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

814 6b93ec9d Iustin Pop
    """
815 6b93ec9d Iustin Pop
    return self._MultiNodeCall(node_list, "drbd_disconnect_net",
816 6b93ec9d Iustin Pop
                               [nodes_ip, [cf.ToDict() for cf in disks]])
817 6b93ec9d Iustin Pop
818 6b93ec9d Iustin Pop
  def call_drbd_attach_net(self, node_list, nodes_ip,
819 6b93ec9d Iustin Pop
                           disks, instance_name, multimaster):
820 6b93ec9d Iustin Pop
    """Disconnects the given drbd devices.
821 6b93ec9d Iustin Pop

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

824 6b93ec9d Iustin Pop
    """
825 6b93ec9d Iustin Pop
    return self._MultiNodeCall(node_list, "drbd_attach_net",
826 6b93ec9d Iustin Pop
                               [nodes_ip, [cf.ToDict() for cf in disks],
827 6b93ec9d Iustin Pop
                                instance_name, multimaster])
828 6b93ec9d Iustin Pop
829 6b93ec9d Iustin Pop
  def call_drbd_wait_sync(self, node_list, nodes_ip, disks):
830 6b93ec9d Iustin Pop
    """Waits for the synchronization of drbd devices is complete.
831 6b93ec9d Iustin Pop

832 6b93ec9d Iustin Pop
    This is a multi-node call.
833 6b93ec9d Iustin Pop

834 6b93ec9d Iustin Pop
    """
835 6b93ec9d Iustin Pop
    return self._MultiNodeCall(node_list, "drbd_wait_sync",
836 6b93ec9d Iustin Pop
                               [nodes_ip, [cf.ToDict() for cf in disks]])
837 6b93ec9d Iustin Pop
838 9a525d83 Michael Hanselmann
  @classmethod
839 9a525d83 Michael Hanselmann
  def call_upload_file(cls, node_list, file_name, address_list=None):
840 72737a7f Iustin Pop
    """Upload a file.
841 72737a7f Iustin Pop

842 72737a7f Iustin Pop
    The node will refuse the operation in case the file is not on the
843 72737a7f Iustin Pop
    approved file list.
844 72737a7f Iustin Pop

845 72737a7f Iustin Pop
    This is a multi-node call.
846 a8083063 Iustin Pop

847 6b294c53 Iustin Pop
    @type node_list: list
848 6b294c53 Iustin Pop
    @param node_list: the list of node names to upload to
849 6b294c53 Iustin Pop
    @type file_name: str
850 6b294c53 Iustin Pop
    @param file_name: the filename to upload
851 6b294c53 Iustin Pop
    @type address_list: list or None
852 6b294c53 Iustin Pop
    @keyword address_list: an optional list of node addresses, in order
853 6b294c53 Iustin Pop
        to optimize the RPC speed
854 6b294c53 Iustin Pop

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

868 6ddc95ec Michael Hanselmann
    This is a multi-node call.
869 6ddc95ec Michael Hanselmann

870 6ddc95ec Michael Hanselmann
    """
871 03d1dba2 Michael Hanselmann
    return cls._StaticMultiNodeCall(node_list, "write_ssconf_files", [values])
872 6ddc95ec Michael Hanselmann
873 72737a7f Iustin Pop
  def call_os_diagnose(self, node_list):
874 72737a7f Iustin Pop
    """Request a diagnose of OS definitions.
875 72737a7f Iustin Pop

876 72737a7f Iustin Pop
    This is a multi-node call.
877 a8083063 Iustin Pop

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

890 72737a7f Iustin Pop
    This is a single-node call.
891 a8083063 Iustin Pop

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

901 72737a7f Iustin Pop
    Args:
902 72737a7f Iustin Pop
      - op: the OpCode instance
903 72737a7f Iustin Pop
      - env: a dictionary with the environment
904 a8083063 Iustin Pop

905 72737a7f Iustin Pop
    This is a multi-node call.
906 a8083063 Iustin Pop

907 72737a7f Iustin Pop
    """
908 72737a7f Iustin Pop
    params = [hpath, phase, env]
909 9a525d83 Michael Hanselmann
    return self._MultiNodeCall(node_list, "hooks_runner", params)
910 a8083063 Iustin Pop
911 72737a7f Iustin Pop
  def call_iallocator_runner(self, node, name, idata):
912 72737a7f Iustin Pop
    """Call an iallocator on a remote node
913 8d528b7c Iustin Pop

914 72737a7f Iustin Pop
    Args:
915 72737a7f Iustin Pop
      - name: the iallocator name
916 72737a7f Iustin Pop
      - input: the json-encoded input string
917 8d528b7c Iustin Pop

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

920 72737a7f Iustin Pop
    """
921 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "iallocator_runner", [name, idata])
922 8d528b7c Iustin Pop
923 72737a7f Iustin Pop
  def call_blockdev_grow(self, node, cf_bdev, amount):
924 72737a7f Iustin Pop
    """Request a snapshot of the given block device.
925 4c8ba8b3 Iustin Pop

926 72737a7f Iustin Pop
    This is a single-node call.
927 4c8ba8b3 Iustin Pop

928 72737a7f Iustin Pop
    """
929 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "blockdev_grow",
930 9a525d83 Michael Hanselmann
                                [cf_bdev.ToDict(), amount])
931 4c8ba8b3 Iustin Pop
932 72737a7f Iustin Pop
  def call_blockdev_snapshot(self, node, cf_bdev):
933 72737a7f Iustin Pop
    """Request a snapshot of the given block device.
934 a8083063 Iustin Pop

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

937 72737a7f Iustin Pop
    """
938 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "blockdev_snapshot", [cf_bdev.ToDict()])
939 a8083063 Iustin Pop
940 72737a7f Iustin Pop
  def call_snapshot_export(self, node, snap_bdev, dest_node, instance,
941 74c47259 Iustin Pop
                           cluster_name, idx):
942 72737a7f Iustin Pop
    """Request the export of a given snapshot.
943 a8083063 Iustin Pop

944 72737a7f Iustin Pop
    This is a single-node call.
945 a8083063 Iustin Pop

946 72737a7f Iustin Pop
    """
947 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "snapshot_export",
948 9a525d83 Michael Hanselmann
                                [snap_bdev.ToDict(), dest_node,
949 9a525d83 Michael Hanselmann
                                 self._InstDict(instance), cluster_name, idx])
950 a8083063 Iustin Pop
951 72737a7f Iustin Pop
  def call_finalize_export(self, node, instance, snap_disks):
952 72737a7f Iustin Pop
    """Request the completion of an export operation.
953 a8083063 Iustin Pop

954 72737a7f Iustin Pop
    This writes the export config file, etc.
955 a8083063 Iustin Pop

956 72737a7f Iustin Pop
    This is a single-node call.
957 a8083063 Iustin Pop

958 72737a7f Iustin Pop
    """
959 72737a7f Iustin Pop
    flat_disks = []
960 72737a7f Iustin Pop
    for disk in snap_disks:
961 a97da6b7 Iustin Pop
      if isinstance(disk, bool):
962 a97da6b7 Iustin Pop
        flat_disks.append(disk)
963 a97da6b7 Iustin Pop
      else:
964 a97da6b7 Iustin Pop
        flat_disks.append(disk.ToDict())
965 9a525d83 Michael Hanselmann
966 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "finalize_export",
967 9a525d83 Michael Hanselmann
                                [self._InstDict(instance), flat_disks])
968 a8083063 Iustin Pop
969 72737a7f Iustin Pop
  def call_export_info(self, node, path):
970 72737a7f Iustin Pop
    """Queries the export information in a given path.
971 a8083063 Iustin Pop

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

974 72737a7f Iustin Pop
    """
975 9a525d83 Michael Hanselmann
    result = self._SingleNodeCall(node, "export_info", [path])
976 781de953 Iustin Pop
    if not result.failed and result.data:
977 781de953 Iustin Pop
      result.data = objects.SerializableConfigParser.Loads(str(result.data))
978 781de953 Iustin Pop
    return result
979 a8083063 Iustin Pop
980 6c0af70e Guido Trotter
  def call_instance_os_import(self, node, inst, src_node, src_images,
981 6c0af70e Guido Trotter
                              cluster_name):
982 72737a7f Iustin Pop
    """Request the import of a backup into an instance.
983 a8083063 Iustin Pop

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

986 72737a7f Iustin Pop
    """
987 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "instance_os_import",
988 9a525d83 Michael Hanselmann
                                [self._InstDict(inst), src_node, src_images,
989 9a525d83 Michael Hanselmann
                                 cluster_name])
990 a8083063 Iustin Pop
991 72737a7f Iustin Pop
  def call_export_list(self, node_list):
992 72737a7f Iustin Pop
    """Gets the stored exports list.
993 a8083063 Iustin Pop

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

996 72737a7f Iustin Pop
    """
997 9a525d83 Michael Hanselmann
    return self._MultiNodeCall(node_list, "export_list", [])
998 a8083063 Iustin Pop
999 72737a7f Iustin Pop
  def call_export_remove(self, node, export):
1000 72737a7f Iustin Pop
    """Requests removal of a given export.
1001 a8083063 Iustin Pop

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

1004 72737a7f Iustin Pop
    """
1005 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "export_remove", [export])
1006 a8083063 Iustin Pop
1007 9a525d83 Michael Hanselmann
  @classmethod
1008 9a525d83 Michael Hanselmann
  def call_node_leave_cluster(cls, node):
1009 72737a7f Iustin Pop
    """Requests a node to clean the cluster information it has.
1010 a8083063 Iustin Pop

1011 72737a7f Iustin Pop
    This will remove the configuration information from the ganeti data
1012 72737a7f Iustin Pop
    dir.
1013 a8083063 Iustin Pop

1014 72737a7f Iustin Pop
    This is a single-node call.
1015 a8083063 Iustin Pop

1016 72737a7f Iustin Pop
    """
1017 9a525d83 Michael Hanselmann
    return cls._StaticSingleNodeCall(node, "node_leave_cluster", [])
1018 dcb93971 Michael Hanselmann
1019 72737a7f Iustin Pop
  def call_node_volumes(self, node_list):
1020 72737a7f Iustin Pop
    """Gets all volumes on node(s).
1021 dcb93971 Michael Hanselmann

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

1024 72737a7f Iustin Pop
    """
1025 9a525d83 Michael Hanselmann
    return self._MultiNodeCall(node_list, "node_volumes", [])
1026 06009e27 Iustin Pop
1027 56aa9fd5 Iustin Pop
  def call_node_demote_from_mc(self, node):
1028 56aa9fd5 Iustin Pop
    """Demote a node from the master candidate role.
1029 56aa9fd5 Iustin Pop

1030 56aa9fd5 Iustin Pop
    This is a single-node call.
1031 56aa9fd5 Iustin Pop

1032 56aa9fd5 Iustin Pop
    """
1033 56aa9fd5 Iustin Pop
    return self._SingleNodeCall(node, "node_demote_from_mc", [])
1034 56aa9fd5 Iustin Pop
1035 72737a7f Iustin Pop
  def call_test_delay(self, node_list, duration):
1036 72737a7f Iustin Pop
    """Sleep for a fixed time on given node(s).
1037 06009e27 Iustin Pop

1038 72737a7f Iustin Pop
    This is a multi-node call.
1039 06009e27 Iustin Pop

1040 72737a7f Iustin Pop
    """
1041 9a525d83 Michael Hanselmann
    return self._MultiNodeCall(node_list, "test_delay", [duration])
1042 5e04ed8b Manuel Franceschini
1043 72737a7f Iustin Pop
  def call_file_storage_dir_create(self, node, file_storage_dir):
1044 72737a7f Iustin Pop
    """Create the given file storage directory.
1045 5e04ed8b Manuel Franceschini

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

1048 72737a7f Iustin Pop
    """
1049 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "file_storage_dir_create",
1050 9a525d83 Michael Hanselmann
                                [file_storage_dir])
1051 5e04ed8b Manuel Franceschini
1052 72737a7f Iustin Pop
  def call_file_storage_dir_remove(self, node, file_storage_dir):
1053 72737a7f Iustin Pop
    """Remove the given file storage directory.
1054 5e04ed8b Manuel Franceschini

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

1057 72737a7f Iustin Pop
    """
1058 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "file_storage_dir_remove",
1059 9a525d83 Michael Hanselmann
                                [file_storage_dir])
1060 5e04ed8b Manuel Franceschini
1061 72737a7f Iustin Pop
  def call_file_storage_dir_rename(self, node, old_file_storage_dir,
1062 72737a7f Iustin Pop
                                   new_file_storage_dir):
1063 72737a7f Iustin Pop
    """Rename file storage directory.
1064 5e04ed8b Manuel Franceschini

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

1067 72737a7f Iustin Pop
    """
1068 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "file_storage_dir_rename",
1069 9a525d83 Michael Hanselmann
                                [old_file_storage_dir, new_file_storage_dir])
1070 ca52cdeb Michael Hanselmann
1071 9a525d83 Michael Hanselmann
  @classmethod
1072 9a525d83 Michael Hanselmann
  def call_jobqueue_update(cls, node_list, address_list, file_name, content):
1073 72737a7f Iustin Pop
    """Update job queue.
1074 ca52cdeb Michael Hanselmann

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

1077 72737a7f Iustin Pop
    """
1078 9a525d83 Michael Hanselmann
    return cls._StaticMultiNodeCall(node_list, "jobqueue_update",
1079 12bce260 Michael Hanselmann
                                    [file_name, cls._Compress(content)],
1080 9a525d83 Michael Hanselmann
                                    address_list=address_list)
1081 ca52cdeb Michael Hanselmann
1082 9a525d83 Michael Hanselmann
  @classmethod
1083 9a525d83 Michael Hanselmann
  def call_jobqueue_purge(cls, node):
1084 72737a7f Iustin Pop
    """Purge job queue.
1085 ca52cdeb Michael Hanselmann

1086 72737a7f Iustin Pop
    This is a single-node call.
1087 ca52cdeb Michael Hanselmann

1088 72737a7f Iustin Pop
    """
1089 9a525d83 Michael Hanselmann
    return cls._StaticSingleNodeCall(node, "jobqueue_purge", [])
1090 af5ebcb1 Michael Hanselmann
1091 9a525d83 Michael Hanselmann
  @classmethod
1092 dd875d32 Michael Hanselmann
  def call_jobqueue_rename(cls, node_list, address_list, rename):
1093 72737a7f Iustin Pop
    """Rename a job queue file.
1094 af5ebcb1 Michael Hanselmann

1095 72737a7f Iustin Pop
    This is a multi-node call.
1096 af5ebcb1 Michael Hanselmann

1097 72737a7f Iustin Pop
    """
1098 dd875d32 Michael Hanselmann
    return cls._StaticMultiNodeCall(node_list, "jobqueue_rename", rename,
1099 9a525d83 Michael Hanselmann
                                    address_list=address_list)
1100 6217e295 Iustin Pop
1101 9a525d83 Michael Hanselmann
  @classmethod
1102 9a525d83 Michael Hanselmann
  def call_jobqueue_set_drain(cls, node_list, drain_flag):
1103 5d672980 Iustin Pop
    """Set the drain flag on the queue.
1104 5d672980 Iustin Pop

1105 5d672980 Iustin Pop
    This is a multi-node call.
1106 5d672980 Iustin Pop

1107 5d672980 Iustin Pop
    @type node_list: list
1108 5d672980 Iustin Pop
    @param node_list: the list of nodes to query
1109 5d672980 Iustin Pop
    @type drain_flag: bool
1110 5d672980 Iustin Pop
    @param drain_flag: if True, will set the drain flag, otherwise reset it.
1111 5d672980 Iustin Pop

1112 5d672980 Iustin Pop
    """
1113 9a525d83 Michael Hanselmann
    return cls._StaticMultiNodeCall(node_list, "jobqueue_set_drain",
1114 9a525d83 Michael Hanselmann
                                    [drain_flag])
1115 5d672980 Iustin Pop
1116 6217e295 Iustin Pop
  def call_hypervisor_validate_params(self, node_list, hvname, hvparams):
1117 6217e295 Iustin Pop
    """Validate the hypervisor params.
1118 6217e295 Iustin Pop

1119 6217e295 Iustin Pop
    This is a multi-node call.
1120 6217e295 Iustin Pop

1121 6217e295 Iustin Pop
    @type node_list: list
1122 6217e295 Iustin Pop
    @param node_list: the list of nodes to query
1123 6217e295 Iustin Pop
    @type hvname: string
1124 6217e295 Iustin Pop
    @param hvname: the hypervisor name
1125 6217e295 Iustin Pop
    @type hvparams: dict
1126 6217e295 Iustin Pop
    @param hvparams: the hypervisor parameters to be validated
1127 6217e295 Iustin Pop

1128 6217e295 Iustin Pop
    """
1129 6217e295 Iustin Pop
    cluster = self._cfg.GetClusterInfo()
1130 6217e295 Iustin Pop
    hv_full = cluster.FillDict(cluster.hvparams.get(hvname, {}), hvparams)
1131 9a525d83 Michael Hanselmann
    return self._MultiNodeCall(node_list, "hypervisor_validate_params",
1132 9a525d83 Michael Hanselmann
                               [hvname, hv_full])