Statistics
| Branch: | Tag: | Revision:

root / lib / rpc.py @ ed83f5cc

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

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

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

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

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

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

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

95 781de953 Iustin Pop
  """
96 ed83f5cc Iustin Pop
  def __init__(self, data=None, failed=False, offline=False,
97 ed83f5cc Iustin Pop
               call=None, node=None):
98 781de953 Iustin Pop
    self.failed = failed
99 ed83f5cc Iustin Pop
    self.offline = offline
100 ed83f5cc Iustin Pop
    self.call = call
101 ed83f5cc Iustin Pop
    self.node = node
102 ed83f5cc Iustin Pop
    if offline:
103 ed83f5cc Iustin Pop
      self.failed = True
104 ed83f5cc Iustin Pop
      self.error = "Node is marked offline"
105 ed83f5cc Iustin Pop
      self.data = None
106 ed83f5cc Iustin Pop
    elif failed:
107 781de953 Iustin Pop
      self.error = data
108 781de953 Iustin Pop
      self.data = None
109 781de953 Iustin Pop
    else:
110 781de953 Iustin Pop
      self.data = data
111 781de953 Iustin Pop
      self.error = None
112 781de953 Iustin Pop
113 781de953 Iustin Pop
  def Raise(self):
114 781de953 Iustin Pop
    """If the result has failed, raise an OpExecError.
115 781de953 Iustin Pop

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

119 781de953 Iustin Pop
    """
120 781de953 Iustin Pop
    if self.failed:
121 781de953 Iustin Pop
      raise errors.OpExecError("Call '%s' to node '%s' has failed: %s" %
122 781de953 Iustin Pop
                               (self.call, self.node, self.error))
123 781de953 Iustin Pop
124 781de953 Iustin Pop
125 a8083063 Iustin Pop
class Client:
126 a8083063 Iustin Pop
  """RPC Client class.
127 a8083063 Iustin Pop

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

132 a8083063 Iustin Pop
  One current bug is that generic failure is still signalled by
133 a8083063 Iustin Pop
  'False' result, which is not good. This overloading of values can
134 a8083063 Iustin Pop
  cause bugs.
135 a8083063 Iustin Pop

136 a8083063 Iustin Pop
  """
137 160e2921 Iustin Pop
  def __init__(self, procedure, body, port):
138 a8083063 Iustin Pop
    self.procedure = procedure
139 160e2921 Iustin Pop
    self.body = body
140 160e2921 Iustin Pop
    self.port = port
141 ecfe9491 Michael Hanselmann
    self.nc = {}
142 a8083063 Iustin Pop
143 d57ae7f7 Michael Hanselmann
    self._ssl_params = \
144 d57ae7f7 Michael Hanselmann
      http.HttpSslParams(ssl_key_path=constants.SSL_CERT_FILE,
145 d57ae7f7 Michael Hanselmann
                         ssl_cert_path=constants.SSL_CERT_FILE)
146 d57ae7f7 Michael Hanselmann
147 bdf7d8c0 Iustin Pop
  def ConnectList(self, node_list, address_list=None):
148 a8083063 Iustin Pop
    """Add a list of nodes to the target nodes.
149 a8083063 Iustin Pop

150 3ef3c771 Iustin Pop
    @type node_list: list
151 3ef3c771 Iustin Pop
    @param node_list: the list of node names to connect
152 bdf7d8c0 Iustin Pop
    @type address_list: list or None
153 bdf7d8c0 Iustin Pop
    @keyword address_list: either None or a list with node addresses,
154 bdf7d8c0 Iustin Pop
        which must have the same length as the node list
155 3ef3c771 Iustin Pop

156 a8083063 Iustin Pop
    """
157 bdf7d8c0 Iustin Pop
    if address_list is None:
158 bdf7d8c0 Iustin Pop
      address_list = [None for _ in node_list]
159 bdf7d8c0 Iustin Pop
    else:
160 bdf7d8c0 Iustin Pop
      assert len(node_list) == len(address_list), \
161 bdf7d8c0 Iustin Pop
             "Name and address lists should have the same length"
162 bdf7d8c0 Iustin Pop
    for node, address in zip(node_list, address_list):
163 bdf7d8c0 Iustin Pop
      self.ConnectNode(node, address)
164 bdf7d8c0 Iustin Pop
165 bdf7d8c0 Iustin Pop
  def ConnectNode(self, name, address=None):
166 a8083063 Iustin Pop
    """Add a node to the target list.
167 a8083063 Iustin Pop

168 bdf7d8c0 Iustin Pop
    @type name: str
169 bdf7d8c0 Iustin Pop
    @param name: the node name
170 bdf7d8c0 Iustin Pop
    @type address: str
171 bdf7d8c0 Iustin Pop
    @keyword address: the node address, if known
172 bdf7d8c0 Iustin Pop

173 a8083063 Iustin Pop
    """
174 ecfe9491 Michael Hanselmann
    if address is None:
175 ecfe9491 Michael Hanselmann
      address = name
176 ecfe9491 Michael Hanselmann
177 ae88ef45 Michael Hanselmann
    self.nc[name] = \
178 ae88ef45 Michael Hanselmann
      http.client.HttpClientRequest(address, self.port, http.HTTP_PUT,
179 ae88ef45 Michael Hanselmann
                                    "/%s" % self.procedure,
180 ae88ef45 Michael Hanselmann
                                    post_data=self.body,
181 ae88ef45 Michael Hanselmann
                                    ssl_params=self._ssl_params,
182 ae88ef45 Michael Hanselmann
                                    ssl_verify_peer=True)
183 a8083063 Iustin Pop
184 3ef3c771 Iustin Pop
  def GetResults(self):
185 ecfe9491 Michael Hanselmann
    """Call nodes and return results.
186 ecfe9491 Michael Hanselmann

187 ecfe9491 Michael Hanselmann
    @rtype: list
188 ecfe9491 Michael Hanselmann
    @returns: List of RPC results
189 a8083063 Iustin Pop

190 a8083063 Iustin Pop
    """
191 4331f6cd Michael Hanselmann
    assert _http_manager, "RPC module not intialized"
192 4331f6cd Michael Hanselmann
193 4331f6cd Michael Hanselmann
    _http_manager.ExecRequests(self.nc.values())
194 a8083063 Iustin Pop
195 ecfe9491 Michael Hanselmann
    results = {}
196 a8083063 Iustin Pop
197 ecfe9491 Michael Hanselmann
    for name, req in self.nc.iteritems():
198 ae88ef45 Michael Hanselmann
      if req.success and req.resp_status_code == http.HTTP_OK:
199 781de953 Iustin Pop
        results[name] = RpcResult(data=serializer.LoadJson(req.resp_body),
200 781de953 Iustin Pop
                                  node=name, call=self.procedure)
201 ecfe9491 Michael Hanselmann
        continue
202 a8083063 Iustin Pop
203 d57ae7f7 Michael Hanselmann
      # TODO: Better error reporting
204 ecfe9491 Michael Hanselmann
      if req.error:
205 ecfe9491 Michael Hanselmann
        msg = req.error
206 ecfe9491 Michael Hanselmann
      else:
207 ecfe9491 Michael Hanselmann
        msg = req.resp_body
208 ecfe9491 Michael Hanselmann
209 ecfe9491 Michael Hanselmann
      logging.error("RPC error from node %s: %s", name, msg)
210 781de953 Iustin Pop
      results[name] = RpcResult(data=msg, failed=True, node=name,
211 781de953 Iustin Pop
                                call=self.procedure)
212 ecfe9491 Michael Hanselmann
213 ecfe9491 Michael Hanselmann
    return results
214 a8083063 Iustin Pop
215 a8083063 Iustin Pop
216 72737a7f Iustin Pop
class RpcRunner(object):
217 72737a7f Iustin Pop
  """RPC runner class"""
218 a8083063 Iustin Pop
219 72737a7f Iustin Pop
  def __init__(self, cfg):
220 72737a7f Iustin Pop
    """Initialized the rpc runner.
221 a8083063 Iustin Pop

222 72737a7f Iustin Pop
    @type cfg:  C{config.ConfigWriter}
223 72737a7f Iustin Pop
    @param cfg: the configuration object that will be used to get data
224 72737a7f Iustin Pop
                about the cluster
225 a8083063 Iustin Pop

226 72737a7f Iustin Pop
    """
227 72737a7f Iustin Pop
    self._cfg = cfg
228 160e2921 Iustin Pop
    self.port = utils.GetNodeDaemonPort()
229 a8083063 Iustin Pop
230 26ba2bd8 Iustin Pop
  def _InstDict(self, instance):
231 26ba2bd8 Iustin Pop
    """Convert the given instance to a dict.
232 26ba2bd8 Iustin Pop

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

236 26ba2bd8 Iustin Pop
    @type instance: L{objects.Instance}
237 26ba2bd8 Iustin Pop
    @param instance: an Instance object
238 26ba2bd8 Iustin Pop
    @rtype: dict
239 26ba2bd8 Iustin Pop
    @return: the instance dict, with the hvparams filled with the
240 26ba2bd8 Iustin Pop
        cluster defaults
241 26ba2bd8 Iustin Pop

242 26ba2bd8 Iustin Pop
    """
243 26ba2bd8 Iustin Pop
    idict = instance.ToDict()
244 5b442704 Iustin Pop
    cluster = self._cfg.GetClusterInfo()
245 5b442704 Iustin Pop
    idict["hvparams"] = cluster.FillHV(instance)
246 5b442704 Iustin Pop
    idict["beparams"] = cluster.FillBE(instance)
247 26ba2bd8 Iustin Pop
    return idict
248 26ba2bd8 Iustin Pop
249 25348212 Iustin Pop
  def _ConnectList(self, client, node_list):
250 25348212 Iustin Pop
    """Helper for computing node addresses.
251 25348212 Iustin Pop

252 25348212 Iustin Pop
    @type client: L{Client}
253 25348212 Iustin Pop
    @param client: a C{Client} instance
254 25348212 Iustin Pop
    @type node_list: list
255 25348212 Iustin Pop
    @param node_list: the node list we should connect
256 25348212 Iustin Pop

257 25348212 Iustin Pop
    """
258 25348212 Iustin Pop
    all_nodes = self._cfg.GetAllNodesInfo()
259 ed83f5cc Iustin Pop
    name_list = []
260 25348212 Iustin Pop
    addr_list = []
261 ed83f5cc Iustin Pop
    skip_dict = {}
262 25348212 Iustin Pop
    for node in node_list:
263 25348212 Iustin Pop
      if node in all_nodes:
264 ed83f5cc Iustin Pop
        if all_nodes[node].offline:
265 ed83f5cc Iustin Pop
          skip_dict[node] = RpcResult(node=node, offline=True)
266 ed83f5cc Iustin Pop
          continue
267 25348212 Iustin Pop
        val = all_nodes[node].primary_ip
268 25348212 Iustin Pop
      else:
269 25348212 Iustin Pop
        val = None
270 25348212 Iustin Pop
      addr_list.append(val)
271 ed83f5cc Iustin Pop
      name_list.append(node)
272 ed83f5cc Iustin Pop
    if name_list:
273 ed83f5cc Iustin Pop
      client.ConnectList(name_list, address_list=addr_list)
274 ed83f5cc Iustin Pop
    return skip_dict
275 25348212 Iustin Pop
276 25348212 Iustin Pop
  def _ConnectNode(self, client, node):
277 25348212 Iustin Pop
    """Helper for computing one node's address.
278 25348212 Iustin Pop

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

284 25348212 Iustin Pop
    """
285 25348212 Iustin Pop
    node_info = self._cfg.GetNodeInfo(node)
286 25348212 Iustin Pop
    if node_info is not None:
287 ed83f5cc Iustin Pop
      if node_info.offline:
288 ed83f5cc Iustin Pop
        return RpcResult(node=node, offline=True)
289 25348212 Iustin Pop
      addr = node_info.primary_ip
290 25348212 Iustin Pop
    else:
291 25348212 Iustin Pop
      addr = None
292 25348212 Iustin Pop
    client.ConnectNode(node, address=addr)
293 25348212 Iustin Pop
294 ed83f5cc Iustin Pop
  def _MultiNodeCall(self, node_list, procedure, args):
295 160e2921 Iustin Pop
    """Helper for making a multi-node call
296 160e2921 Iustin Pop

297 160e2921 Iustin Pop
    """
298 160e2921 Iustin Pop
    body = serializer.DumpJson(args, indent=False)
299 160e2921 Iustin Pop
    c = Client(procedure, body, self.port)
300 ed83f5cc Iustin Pop
    skip_dict = self._ConnectList(c, node_list)
301 ed83f5cc Iustin Pop
    skip_dict.update(c.GetResults())
302 ed83f5cc Iustin Pop
    return skip_dict
303 9a525d83 Michael Hanselmann
304 9a525d83 Michael Hanselmann
  @classmethod
305 9a525d83 Michael Hanselmann
  def _StaticMultiNodeCall(cls, node_list, procedure, args,
306 9a525d83 Michael Hanselmann
                           address_list=None):
307 160e2921 Iustin Pop
    """Helper for making a multi-node static call
308 160e2921 Iustin Pop

309 160e2921 Iustin Pop
    """
310 160e2921 Iustin Pop
    body = serializer.DumpJson(args, indent=False)
311 160e2921 Iustin Pop
    c = Client(procedure, body, utils.GetNodeDaemonPort())
312 9a525d83 Michael Hanselmann
    c.ConnectList(node_list, address_list=address_list)
313 9a525d83 Michael Hanselmann
    return c.GetResults()
314 9a525d83 Michael Hanselmann
315 9a525d83 Michael Hanselmann
  def _SingleNodeCall(self, node, procedure, args):
316 160e2921 Iustin Pop
    """Helper for making a single-node call
317 9a525d83 Michael Hanselmann

318 9a525d83 Michael Hanselmann
    """
319 160e2921 Iustin Pop
    body = serializer.DumpJson(args, indent=False)
320 160e2921 Iustin Pop
    c = Client(procedure, body, self.port)
321 ed83f5cc Iustin Pop
    result = self._ConnectNode(c, node)
322 ed83f5cc Iustin Pop
    if result is None:
323 ed83f5cc Iustin Pop
      # we did connect, node is not offline
324 ed83f5cc Iustin Pop
      result = c.GetResults()[node]
325 ed83f5cc Iustin Pop
    return result
326 9a525d83 Michael Hanselmann
327 9a525d83 Michael Hanselmann
  @classmethod
328 9a525d83 Michael Hanselmann
  def _StaticSingleNodeCall(cls, node, procedure, args):
329 160e2921 Iustin Pop
    """Helper for making a single-node static call
330 9a525d83 Michael Hanselmann

331 9a525d83 Michael Hanselmann
    """
332 160e2921 Iustin Pop
    body = serializer.DumpJson(args, indent=False)
333 160e2921 Iustin Pop
    c = Client(procedure, body, utils.GetNodeDaemonPort())
334 3097c858 Michael Hanselmann
    c.ConnectNode(node)
335 ed83f5cc Iustin Pop
    return c.GetResults()[node]
336 9a525d83 Michael Hanselmann
337 781de953 Iustin Pop
  #
338 781de953 Iustin Pop
  # Begin RPC calls
339 781de953 Iustin Pop
  #
340 781de953 Iustin Pop
341 72737a7f Iustin Pop
  def call_volume_list(self, node_list, vg_name):
342 72737a7f Iustin Pop
    """Gets the logical volumes present in a given volume group.
343 a8083063 Iustin Pop

344 72737a7f Iustin Pop
    This is a multi-node call.
345 a8083063 Iustin Pop

346 72737a7f Iustin Pop
    """
347 9a525d83 Michael Hanselmann
    return self._MultiNodeCall(node_list, "volume_list", [vg_name])
348 a8083063 Iustin Pop
349 72737a7f Iustin Pop
  def call_vg_list(self, node_list):
350 72737a7f Iustin Pop
    """Gets the volume group list.
351 a8083063 Iustin Pop

352 72737a7f Iustin Pop
    This is a multi-node call.
353 a8083063 Iustin Pop

354 72737a7f Iustin Pop
    """
355 9a525d83 Michael Hanselmann
    return self._MultiNodeCall(node_list, "vg_list", [])
356 a8083063 Iustin Pop
357 72737a7f Iustin Pop
  def call_bridges_exist(self, node, bridges_list):
358 72737a7f Iustin Pop
    """Checks if a node has all the bridges given.
359 a8083063 Iustin Pop

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

364 72737a7f Iustin Pop
    This is a single-node call.
365 a8083063 Iustin Pop

366 72737a7f Iustin Pop
    """
367 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "bridges_exist", [bridges_list])
368 a8083063 Iustin Pop
369 72737a7f Iustin Pop
  def call_instance_start(self, node, instance, extra_args):
370 72737a7f Iustin Pop
    """Starts an instance.
371 a8083063 Iustin Pop

372 72737a7f Iustin Pop
    This is a single-node call.
373 a8083063 Iustin Pop

374 72737a7f Iustin Pop
    """
375 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "instance_start",
376 9a525d83 Michael Hanselmann
                                [self._InstDict(instance), extra_args])
377 a8083063 Iustin Pop
378 72737a7f Iustin Pop
  def call_instance_shutdown(self, node, instance):
379 72737a7f Iustin Pop
    """Stops an instance.
380 a8083063 Iustin Pop

381 72737a7f Iustin Pop
    This is a single-node call.
382 2a10865c Iustin Pop

383 72737a7f Iustin Pop
    """
384 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "instance_shutdown",
385 9a525d83 Michael Hanselmann
                                [self._InstDict(instance)])
386 2a10865c Iustin Pop
387 72737a7f Iustin Pop
  def call_instance_migrate(self, node, instance, target, live):
388 72737a7f Iustin Pop
    """Migrate an instance.
389 2a10865c Iustin Pop

390 72737a7f Iustin Pop
    This is a single-node call.
391 2a10865c Iustin Pop

392 72737a7f Iustin Pop
    @type node: string
393 72737a7f Iustin Pop
    @param node: the node on which the instance is currently running
394 72737a7f Iustin Pop
    @type instance: C{objects.Instance}
395 72737a7f Iustin Pop
    @param instance: the instance definition
396 72737a7f Iustin Pop
    @type target: string
397 72737a7f Iustin Pop
    @param target: the target node name
398 72737a7f Iustin Pop
    @type live: boolean
399 72737a7f Iustin Pop
    @param live: whether the migration should be done live or not (the
400 72737a7f Iustin Pop
        interpretation of this parameter is left to the hypervisor)
401 007a2f3e Alexander Schreiber

402 72737a7f Iustin Pop
    """
403 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "instance_migrate",
404 9a525d83 Michael Hanselmann
                                [self._InstDict(instance), target, live])
405 007a2f3e Alexander Schreiber
406 72737a7f Iustin Pop
  def call_instance_reboot(self, node, instance, reboot_type, extra_args):
407 72737a7f Iustin Pop
    """Reboots an instance.
408 007a2f3e Alexander Schreiber

409 72737a7f Iustin Pop
    This is a single-node call.
410 a8083063 Iustin Pop

411 72737a7f Iustin Pop
    """
412 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "instance_reboot",
413 9a525d83 Michael Hanselmann
                                [self._InstDict(instance), reboot_type,
414 9a525d83 Michael Hanselmann
                                 extra_args])
415 a8083063 Iustin Pop
416 d15a9ad3 Guido Trotter
  def call_instance_os_add(self, node, inst):
417 72737a7f Iustin Pop
    """Installs an OS on the given instance.
418 a8083063 Iustin Pop

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

421 72737a7f Iustin Pop
    """
422 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "instance_os_add",
423 9a525d83 Michael Hanselmann
                                [self._InstDict(inst)])
424 decd5f45 Iustin Pop
425 d15a9ad3 Guido Trotter
  def call_instance_run_rename(self, node, inst, old_name):
426 72737a7f Iustin Pop
    """Run the OS rename script for an instance.
427 decd5f45 Iustin Pop

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

430 72737a7f Iustin Pop
    """
431 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "instance_run_rename",
432 9a525d83 Michael Hanselmann
                                [self._InstDict(inst), old_name])
433 a8083063 Iustin Pop
434 72737a7f Iustin Pop
  def call_instance_info(self, node, instance, hname):
435 72737a7f Iustin Pop
    """Returns information about a single instance.
436 a8083063 Iustin Pop

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

439 9a525d83 Michael Hanselmann
    @type node: list
440 9a525d83 Michael Hanselmann
    @param node: the list of nodes to query
441 72737a7f Iustin Pop
    @type instance: string
442 72737a7f Iustin Pop
    @param instance: the instance name
443 72737a7f Iustin Pop
    @type hname: string
444 72737a7f Iustin Pop
    @param hname: the hypervisor type of the instance
445 a8083063 Iustin Pop

446 72737a7f Iustin Pop
    """
447 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "instance_info", [instance, hname])
448 e69d05fd Iustin Pop
449 72737a7f Iustin Pop
  def call_all_instances_info(self, node_list, hypervisor_list):
450 72737a7f Iustin Pop
    """Returns information about all instances on the given nodes.
451 a8083063 Iustin Pop

452 72737a7f Iustin Pop
    This is a multi-node call.
453 a8083063 Iustin Pop

454 72737a7f Iustin Pop
    @type node_list: list
455 72737a7f Iustin Pop
    @param node_list: the list of nodes to query
456 72737a7f Iustin Pop
    @type hypervisor_list: list
457 72737a7f Iustin Pop
    @param hypervisor_list: the hypervisors to query for instances
458 a8083063 Iustin Pop

459 72737a7f Iustin Pop
    """
460 9a525d83 Michael Hanselmann
    return self._MultiNodeCall(node_list, "all_instances_info",
461 9a525d83 Michael Hanselmann
                               [hypervisor_list])
462 e69d05fd Iustin Pop
463 72737a7f Iustin Pop
  def call_instance_list(self, node_list, hypervisor_list):
464 72737a7f Iustin Pop
    """Returns the list of running instances on a given node.
465 a8083063 Iustin Pop

466 72737a7f Iustin Pop
    This is a multi-node call.
467 a8083063 Iustin Pop

468 72737a7f Iustin Pop
    @type node_list: list
469 72737a7f Iustin Pop
    @param node_list: the list of nodes to query
470 72737a7f Iustin Pop
    @type hypervisor_list: list
471 72737a7f Iustin Pop
    @param hypervisor_list: the hypervisors to query for instances
472 16abfbc2 Alexander Schreiber

473 72737a7f Iustin Pop
    """
474 9a525d83 Michael Hanselmann
    return self._MultiNodeCall(node_list, "instance_list", [hypervisor_list])
475 16abfbc2 Alexander Schreiber
476 72737a7f Iustin Pop
  def call_node_tcp_ping(self, node, source, target, port, timeout,
477 72737a7f Iustin Pop
                         live_port_needed):
478 72737a7f Iustin Pop
    """Do a TcpPing on the remote node
479 a8083063 Iustin Pop

480 72737a7f Iustin Pop
    This is a single-node call.
481 caad16e2 Iustin Pop

482 72737a7f Iustin Pop
    """
483 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "node_tcp_ping",
484 9a525d83 Michael Hanselmann
                                [source, target, port, timeout,
485 72737a7f Iustin Pop
                                 live_port_needed])
486 a8083063 Iustin Pop
487 caad16e2 Iustin Pop
  def call_node_has_ip_address(self, node, address):
488 caad16e2 Iustin Pop
    """Checks if a node has the given IP address.
489 caad16e2 Iustin Pop

490 caad16e2 Iustin Pop
    This is a single-node call.
491 caad16e2 Iustin Pop

492 caad16e2 Iustin Pop
    """
493 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "node_has_ip_address", [address])
494 a8083063 Iustin Pop
495 72737a7f Iustin Pop
  def call_node_info(self, node_list, vg_name, hypervisor_type):
496 72737a7f Iustin Pop
    """Return node information.
497 e69d05fd Iustin Pop

498 72737a7f Iustin Pop
    This will return memory information and volume group size and free
499 72737a7f Iustin Pop
    space.
500 a8083063 Iustin Pop

501 72737a7f Iustin Pop
    This is a multi-node call.
502 a8083063 Iustin Pop

503 72737a7f Iustin Pop
    @type node_list: list
504 72737a7f Iustin Pop
    @param node_list: the list of nodes to query
505 72737a7f Iustin Pop
    @type vgname: C{string}
506 72737a7f Iustin Pop
    @param vgname: the name of the volume group to ask for disk space
507 72737a7f Iustin Pop
        information
508 72737a7f Iustin Pop
    @type hypervisor_type: C{str}
509 72737a7f Iustin Pop
    @param hypervisor_type: the name of the hypervisor to ask for
510 72737a7f Iustin Pop
        memory information
511 a8083063 Iustin Pop

512 72737a7f Iustin Pop
    """
513 9a525d83 Michael Hanselmann
    retux = self._MultiNodeCall(node_list, "node_info",
514 9a525d83 Michael Hanselmann
                                [vg_name, hypervisor_type])
515 a8083063 Iustin Pop
516 781de953 Iustin Pop
    for result in retux.itervalues():
517 781de953 Iustin Pop
      if result.failed or not isinstance(result.data, dict):
518 781de953 Iustin Pop
        result.data = {}
519 781de953 Iustin Pop
520 781de953 Iustin Pop
      utils.CheckDict(result.data, {
521 781de953 Iustin Pop
        'memory_total' : '-',
522 781de953 Iustin Pop
        'memory_dom0' : '-',
523 781de953 Iustin Pop
        'memory_free' : '-',
524 781de953 Iustin Pop
        'vg_size' : 'node_unreachable',
525 781de953 Iustin Pop
        'vg_free' : '-',
526 781de953 Iustin Pop
        }, "call_node_info")
527 72737a7f Iustin Pop
    return retux
528 a8083063 Iustin Pop
529 72737a7f Iustin Pop
  def call_node_add(self, node, dsa, dsapub, rsa, rsapub, ssh, sshpub):
530 72737a7f Iustin Pop
    """Add a node to the cluster.
531 a8083063 Iustin Pop

532 72737a7f Iustin Pop
    This is a single-node call.
533 a8083063 Iustin Pop

534 72737a7f Iustin Pop
    """
535 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "node_add",
536 9a525d83 Michael Hanselmann
                                [dsa, dsapub, rsa, rsapub, ssh, sshpub])
537 a8083063 Iustin Pop
538 72737a7f Iustin Pop
  def call_node_verify(self, node_list, checkdict, cluster_name):
539 72737a7f Iustin Pop
    """Request verification of given parameters.
540 a8083063 Iustin Pop

541 72737a7f Iustin Pop
    This is a multi-node call.
542 a8083063 Iustin Pop

543 72737a7f Iustin Pop
    """
544 9a525d83 Michael Hanselmann
    return self._MultiNodeCall(node_list, "node_verify",
545 9a525d83 Michael Hanselmann
                               [checkdict, cluster_name])
546 a8083063 Iustin Pop
547 9a525d83 Michael Hanselmann
  @classmethod
548 9a525d83 Michael Hanselmann
  def call_node_start_master(cls, node, start_daemons):
549 72737a7f Iustin Pop
    """Tells a node to activate itself as a master.
550 a8083063 Iustin Pop

551 72737a7f Iustin Pop
    This is a single-node call.
552 a8083063 Iustin Pop

553 72737a7f Iustin Pop
    """
554 9a525d83 Michael Hanselmann
    return cls._StaticSingleNodeCall(node, "node_start_master",
555 9a525d83 Michael Hanselmann
                                     [start_daemons])
556 a8083063 Iustin Pop
557 9a525d83 Michael Hanselmann
  @classmethod
558 9a525d83 Michael Hanselmann
  def call_node_stop_master(cls, node, stop_daemons):
559 72737a7f Iustin Pop
    """Tells a node to demote itself from master status.
560 a8083063 Iustin Pop

561 72737a7f Iustin Pop
    This is a single-node call.
562 4e071d3b Iustin Pop

563 72737a7f Iustin Pop
    """
564 9a525d83 Michael Hanselmann
    return cls._StaticSingleNodeCall(node, "node_stop_master", [stop_daemons])
565 4e071d3b Iustin Pop
566 9a525d83 Michael Hanselmann
  @classmethod
567 9a525d83 Michael Hanselmann
  def call_master_info(cls, node_list):
568 72737a7f Iustin Pop
    """Query master info.
569 4e071d3b Iustin Pop

570 72737a7f Iustin Pop
    This is a multi-node call.
571 a8083063 Iustin Pop

572 72737a7f Iustin Pop
    """
573 72737a7f Iustin Pop
    # TODO: should this method query down nodes?
574 9a525d83 Michael Hanselmann
    return cls._StaticMultiNodeCall(node_list, "master_info", [])
575 a8083063 Iustin Pop
576 72737a7f Iustin Pop
  def call_version(self, node_list):
577 72737a7f Iustin Pop
    """Query node version.
578 a8083063 Iustin Pop

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

581 72737a7f Iustin Pop
    """
582 9a525d83 Michael Hanselmann
    return self._MultiNodeCall(node_list, "version", [])
583 a8083063 Iustin Pop
584 72737a7f Iustin Pop
  def call_blockdev_create(self, node, bdev, size, owner, on_primary, info):
585 72737a7f Iustin Pop
    """Request creation of a given block device.
586 a8083063 Iustin Pop

587 72737a7f Iustin Pop
    This is a single-node call.
588 a8083063 Iustin Pop

589 72737a7f Iustin Pop
    """
590 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "blockdev_create",
591 9a525d83 Michael Hanselmann
                                [bdev.ToDict(), size, owner, on_primary, info])
592 a8083063 Iustin Pop
593 72737a7f Iustin Pop
  def call_blockdev_remove(self, node, bdev):
594 72737a7f Iustin Pop
    """Request removal of a given block device.
595 a8083063 Iustin Pop

596 72737a7f Iustin Pop
    This is a single-node call.
597 f3e513ad Iustin Pop

598 72737a7f Iustin Pop
    """
599 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "blockdev_remove", [bdev.ToDict()])
600 f3e513ad Iustin Pop
601 72737a7f Iustin Pop
  def call_blockdev_rename(self, node, devlist):
602 72737a7f Iustin Pop
    """Request rename of the given block devices.
603 f3e513ad Iustin Pop

604 72737a7f Iustin Pop
    This is a single-node call.
605 a8083063 Iustin Pop

606 72737a7f Iustin Pop
    """
607 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "blockdev_rename",
608 9a525d83 Michael Hanselmann
                                [(d.ToDict(), uid) for d, uid in devlist])
609 a8083063 Iustin Pop
610 72737a7f Iustin Pop
  def call_blockdev_assemble(self, node, disk, owner, on_primary):
611 72737a7f Iustin Pop
    """Request assembling of a given block device.
612 a8083063 Iustin Pop

613 72737a7f Iustin Pop
    This is a single-node call.
614 a8083063 Iustin Pop

615 72737a7f Iustin Pop
    """
616 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "blockdev_assemble",
617 9a525d83 Michael Hanselmann
                                [disk.ToDict(), owner, on_primary])
618 a8083063 Iustin Pop
619 72737a7f Iustin Pop
  def call_blockdev_shutdown(self, node, disk):
620 72737a7f Iustin Pop
    """Request shutdown of a given block device.
621 a8083063 Iustin Pop

622 72737a7f Iustin Pop
    This is a single-node call.
623 a8083063 Iustin Pop

624 72737a7f Iustin Pop
    """
625 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "blockdev_shutdown", [disk.ToDict()])
626 a8083063 Iustin Pop
627 72737a7f Iustin Pop
  def call_blockdev_addchildren(self, node, bdev, ndevs):
628 72737a7f Iustin Pop
    """Request adding a list of children to a (mirroring) device.
629 a8083063 Iustin Pop

630 72737a7f Iustin Pop
    This is a single-node call.
631 a8083063 Iustin Pop

632 72737a7f Iustin Pop
    """
633 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "blockdev_addchildren",
634 9a525d83 Michael Hanselmann
                                [bdev.ToDict(),
635 9a525d83 Michael Hanselmann
                                 [disk.ToDict() for disk in ndevs]])
636 a8083063 Iustin Pop
637 72737a7f Iustin Pop
  def call_blockdev_removechildren(self, node, bdev, ndevs):
638 72737a7f Iustin Pop
    """Request removing a list of children from a (mirroring) device.
639 a8083063 Iustin Pop

640 72737a7f Iustin Pop
    This is a single-node call.
641 a8083063 Iustin Pop

642 72737a7f Iustin Pop
    """
643 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "blockdev_removechildren",
644 9a525d83 Michael Hanselmann
                                [bdev.ToDict(),
645 9a525d83 Michael Hanselmann
                                 [disk.ToDict() for disk in ndevs]])
646 a8083063 Iustin Pop
647 72737a7f Iustin Pop
  def call_blockdev_getmirrorstatus(self, node, disks):
648 72737a7f Iustin Pop
    """Request status of a (mirroring) device.
649 a8083063 Iustin Pop

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

652 72737a7f Iustin Pop
    """
653 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "blockdev_getmirrorstatus",
654 9a525d83 Michael Hanselmann
                                [dsk.ToDict() for dsk in disks])
655 a8083063 Iustin Pop
656 72737a7f Iustin Pop
  def call_blockdev_find(self, node, disk):
657 72737a7f Iustin Pop
    """Request identification of a given block device.
658 72737a7f Iustin Pop

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

661 72737a7f Iustin Pop
    """
662 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "blockdev_find", [disk.ToDict()])
663 d61cbe76 Iustin Pop
664 72737a7f Iustin Pop
  def call_blockdev_close(self, node, disks):
665 72737a7f Iustin Pop
    """Closes the given block devices.
666 d61cbe76 Iustin Pop

667 72737a7f Iustin Pop
    This is a single-node call.
668 d61cbe76 Iustin Pop

669 72737a7f Iustin Pop
    """
670 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "blockdev_close",
671 9a525d83 Michael Hanselmann
                                [cf.ToDict() for cf in disks])
672 a8083063 Iustin Pop
673 9a525d83 Michael Hanselmann
  @classmethod
674 9a525d83 Michael Hanselmann
  def call_upload_file(cls, node_list, file_name, address_list=None):
675 72737a7f Iustin Pop
    """Upload a file.
676 72737a7f Iustin Pop

677 72737a7f Iustin Pop
    The node will refuse the operation in case the file is not on the
678 72737a7f Iustin Pop
    approved file list.
679 72737a7f Iustin Pop

680 72737a7f Iustin Pop
    This is a multi-node call.
681 a8083063 Iustin Pop

682 6b294c53 Iustin Pop
    @type node_list: list
683 6b294c53 Iustin Pop
    @param node_list: the list of node names to upload to
684 6b294c53 Iustin Pop
    @type file_name: str
685 6b294c53 Iustin Pop
    @param file_name: the filename to upload
686 6b294c53 Iustin Pop
    @type address_list: list or None
687 6b294c53 Iustin Pop
    @keyword address_list: an optional list of node addresses, in order
688 6b294c53 Iustin Pop
        to optimize the RPC speed
689 6b294c53 Iustin Pop

690 72737a7f Iustin Pop
    """
691 4c7c81d7 Michael Hanselmann
    data = utils.ReadFile(file_name)
692 72737a7f Iustin Pop
    st = os.stat(file_name)
693 72737a7f Iustin Pop
    params = [file_name, data, st.st_mode, st.st_uid, st.st_gid,
694 72737a7f Iustin Pop
              st.st_atime, st.st_mtime]
695 9a525d83 Michael Hanselmann
    return cls._StaticMultiNodeCall(node_list, "upload_file", params,
696 9a525d83 Michael Hanselmann
                                    address_list=address_list)
697 72737a7f Iustin Pop
698 6ddc95ec Michael Hanselmann
  @classmethod
699 03d1dba2 Michael Hanselmann
  def call_write_ssconf_files(cls, node_list, values):
700 6ddc95ec Michael Hanselmann
    """Write ssconf files.
701 6ddc95ec Michael Hanselmann

702 6ddc95ec Michael Hanselmann
    This is a multi-node call.
703 6ddc95ec Michael Hanselmann

704 6ddc95ec Michael Hanselmann
    """
705 03d1dba2 Michael Hanselmann
    return cls._StaticMultiNodeCall(node_list, "write_ssconf_files", [values])
706 6ddc95ec Michael Hanselmann
707 72737a7f Iustin Pop
  def call_os_diagnose(self, node_list):
708 72737a7f Iustin Pop
    """Request a diagnose of OS definitions.
709 72737a7f Iustin Pop

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

712 72737a7f Iustin Pop
    """
713 9a525d83 Michael Hanselmann
    result = self._MultiNodeCall(node_list, "os_diagnose", [])
714 9a525d83 Michael Hanselmann
715 781de953 Iustin Pop
    for node_name, node_result in result.iteritems():
716 781de953 Iustin Pop
      if not node_result.failed and node_result.data:
717 781de953 Iustin Pop
        node_result.data = [objects.OS.FromDict(oss)
718 781de953 Iustin Pop
                            for oss in node_result.data]
719 781de953 Iustin Pop
    return result
720 a8083063 Iustin Pop
721 72737a7f Iustin Pop
  def call_os_get(self, node, name):
722 72737a7f Iustin Pop
    """Returns an OS definition.
723 a8083063 Iustin Pop

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

726 72737a7f Iustin Pop
    """
727 9a525d83 Michael Hanselmann
    result = self._SingleNodeCall(node, "os_get", [name])
728 781de953 Iustin Pop
    if not result.failed and isinstance(result.data, dict):
729 781de953 Iustin Pop
      result.data = objects.OS.FromDict(result.data)
730 781de953 Iustin Pop
    return result
731 a8083063 Iustin Pop
732 72737a7f Iustin Pop
  def call_hooks_runner(self, node_list, hpath, phase, env):
733 72737a7f Iustin Pop
    """Call the hooks runner.
734 a8083063 Iustin Pop

735 72737a7f Iustin Pop
    Args:
736 72737a7f Iustin Pop
      - op: the OpCode instance
737 72737a7f Iustin Pop
      - env: a dictionary with the environment
738 a8083063 Iustin Pop

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

741 72737a7f Iustin Pop
    """
742 72737a7f Iustin Pop
    params = [hpath, phase, env]
743 9a525d83 Michael Hanselmann
    return self._MultiNodeCall(node_list, "hooks_runner", params)
744 a8083063 Iustin Pop
745 72737a7f Iustin Pop
  def call_iallocator_runner(self, node, name, idata):
746 72737a7f Iustin Pop
    """Call an iallocator on a remote node
747 8d528b7c Iustin Pop

748 72737a7f Iustin Pop
    Args:
749 72737a7f Iustin Pop
      - name: the iallocator name
750 72737a7f Iustin Pop
      - input: the json-encoded input string
751 8d528b7c Iustin Pop

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

754 72737a7f Iustin Pop
    """
755 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "iallocator_runner", [name, idata])
756 8d528b7c Iustin Pop
757 72737a7f Iustin Pop
  def call_blockdev_grow(self, node, cf_bdev, amount):
758 72737a7f Iustin Pop
    """Request a snapshot of the given block device.
759 4c8ba8b3 Iustin Pop

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

762 72737a7f Iustin Pop
    """
763 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "blockdev_grow",
764 9a525d83 Michael Hanselmann
                                [cf_bdev.ToDict(), amount])
765 4c8ba8b3 Iustin Pop
766 72737a7f Iustin Pop
  def call_blockdev_snapshot(self, node, cf_bdev):
767 72737a7f Iustin Pop
    """Request a snapshot of the given block device.
768 a8083063 Iustin Pop

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

771 72737a7f Iustin Pop
    """
772 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "blockdev_snapshot", [cf_bdev.ToDict()])
773 a8083063 Iustin Pop
774 72737a7f Iustin Pop
  def call_snapshot_export(self, node, snap_bdev, dest_node, instance,
775 74c47259 Iustin Pop
                           cluster_name, idx):
776 72737a7f Iustin Pop
    """Request the export of a given snapshot.
777 a8083063 Iustin Pop

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

780 72737a7f Iustin Pop
    """
781 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "snapshot_export",
782 9a525d83 Michael Hanselmann
                                [snap_bdev.ToDict(), dest_node,
783 9a525d83 Michael Hanselmann
                                 self._InstDict(instance), cluster_name, idx])
784 a8083063 Iustin Pop
785 72737a7f Iustin Pop
  def call_finalize_export(self, node, instance, snap_disks):
786 72737a7f Iustin Pop
    """Request the completion of an export operation.
787 a8083063 Iustin Pop

788 72737a7f Iustin Pop
    This writes the export config file, etc.
789 a8083063 Iustin Pop

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

792 72737a7f Iustin Pop
    """
793 72737a7f Iustin Pop
    flat_disks = []
794 72737a7f Iustin Pop
    for disk in snap_disks:
795 72737a7f Iustin Pop
      flat_disks.append(disk.ToDict())
796 9a525d83 Michael Hanselmann
797 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "finalize_export",
798 9a525d83 Michael Hanselmann
                                [self._InstDict(instance), flat_disks])
799 a8083063 Iustin Pop
800 72737a7f Iustin Pop
  def call_export_info(self, node, path):
801 72737a7f Iustin Pop
    """Queries the export information in a given path.
802 a8083063 Iustin Pop

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

805 72737a7f Iustin Pop
    """
806 9a525d83 Michael Hanselmann
    result = self._SingleNodeCall(node, "export_info", [path])
807 781de953 Iustin Pop
    if not result.failed and result.data:
808 781de953 Iustin Pop
      result.data = objects.SerializableConfigParser.Loads(str(result.data))
809 781de953 Iustin Pop
    return result
810 a8083063 Iustin Pop
811 6c0af70e Guido Trotter
  def call_instance_os_import(self, node, inst, src_node, src_images,
812 6c0af70e Guido Trotter
                              cluster_name):
813 72737a7f Iustin Pop
    """Request the import of a backup into an instance.
814 a8083063 Iustin Pop

815 72737a7f Iustin Pop
    This is a single-node call.
816 a8083063 Iustin Pop

817 72737a7f Iustin Pop
    """
818 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "instance_os_import",
819 9a525d83 Michael Hanselmann
                                [self._InstDict(inst), src_node, src_images,
820 9a525d83 Michael Hanselmann
                                 cluster_name])
821 a8083063 Iustin Pop
822 72737a7f Iustin Pop
  def call_export_list(self, node_list):
823 72737a7f Iustin Pop
    """Gets the stored exports list.
824 a8083063 Iustin Pop

825 72737a7f Iustin Pop
    This is a multi-node call.
826 a8083063 Iustin Pop

827 72737a7f Iustin Pop
    """
828 9a525d83 Michael Hanselmann
    return self._MultiNodeCall(node_list, "export_list", [])
829 a8083063 Iustin Pop
830 72737a7f Iustin Pop
  def call_export_remove(self, node, export):
831 72737a7f Iustin Pop
    """Requests removal of a given export.
832 a8083063 Iustin Pop

833 72737a7f Iustin Pop
    This is a single-node call.
834 a8083063 Iustin Pop

835 72737a7f Iustin Pop
    """
836 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "export_remove", [export])
837 a8083063 Iustin Pop
838 9a525d83 Michael Hanselmann
  @classmethod
839 9a525d83 Michael Hanselmann
  def call_node_leave_cluster(cls, node):
840 72737a7f Iustin Pop
    """Requests a node to clean the cluster information it has.
841 a8083063 Iustin Pop

842 72737a7f Iustin Pop
    This will remove the configuration information from the ganeti data
843 72737a7f Iustin Pop
    dir.
844 a8083063 Iustin Pop

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

847 72737a7f Iustin Pop
    """
848 9a525d83 Michael Hanselmann
    return cls._StaticSingleNodeCall(node, "node_leave_cluster", [])
849 dcb93971 Michael Hanselmann
850 72737a7f Iustin Pop
  def call_node_volumes(self, node_list):
851 72737a7f Iustin Pop
    """Gets all volumes on node(s).
852 dcb93971 Michael Hanselmann

853 72737a7f Iustin Pop
    This is a multi-node call.
854 dcb93971 Michael Hanselmann

855 72737a7f Iustin Pop
    """
856 9a525d83 Michael Hanselmann
    return self._MultiNodeCall(node_list, "node_volumes", [])
857 06009e27 Iustin Pop
858 56aa9fd5 Iustin Pop
  def call_node_demote_from_mc(self, node):
859 56aa9fd5 Iustin Pop
    """Demote a node from the master candidate role.
860 56aa9fd5 Iustin Pop

861 56aa9fd5 Iustin Pop
    This is a single-node call.
862 56aa9fd5 Iustin Pop

863 56aa9fd5 Iustin Pop
    """
864 56aa9fd5 Iustin Pop
    return self._SingleNodeCall(node, "node_demote_from_mc", [])
865 56aa9fd5 Iustin Pop
866 72737a7f Iustin Pop
  def call_test_delay(self, node_list, duration):
867 72737a7f Iustin Pop
    """Sleep for a fixed time on given node(s).
868 06009e27 Iustin Pop

869 72737a7f Iustin Pop
    This is a multi-node call.
870 06009e27 Iustin Pop

871 72737a7f Iustin Pop
    """
872 9a525d83 Michael Hanselmann
    return self._MultiNodeCall(node_list, "test_delay", [duration])
873 5e04ed8b Manuel Franceschini
874 72737a7f Iustin Pop
  def call_file_storage_dir_create(self, node, file_storage_dir):
875 72737a7f Iustin Pop
    """Create the given file storage directory.
876 5e04ed8b Manuel Franceschini

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

879 72737a7f Iustin Pop
    """
880 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "file_storage_dir_create",
881 9a525d83 Michael Hanselmann
                                [file_storage_dir])
882 5e04ed8b Manuel Franceschini
883 72737a7f Iustin Pop
  def call_file_storage_dir_remove(self, node, file_storage_dir):
884 72737a7f Iustin Pop
    """Remove the given file storage directory.
885 5e04ed8b Manuel Franceschini

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

888 72737a7f Iustin Pop
    """
889 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "file_storage_dir_remove",
890 9a525d83 Michael Hanselmann
                                [file_storage_dir])
891 5e04ed8b Manuel Franceschini
892 72737a7f Iustin Pop
  def call_file_storage_dir_rename(self, node, old_file_storage_dir,
893 72737a7f Iustin Pop
                                   new_file_storage_dir):
894 72737a7f Iustin Pop
    """Rename file storage directory.
895 5e04ed8b Manuel Franceschini

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

898 72737a7f Iustin Pop
    """
899 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "file_storage_dir_rename",
900 9a525d83 Michael Hanselmann
                                [old_file_storage_dir, new_file_storage_dir])
901 ca52cdeb Michael Hanselmann
902 9a525d83 Michael Hanselmann
  @classmethod
903 9a525d83 Michael Hanselmann
  def call_jobqueue_update(cls, node_list, address_list, file_name, content):
904 72737a7f Iustin Pop
    """Update job queue.
905 ca52cdeb Michael Hanselmann

906 72737a7f Iustin Pop
    This is a multi-node call.
907 ca52cdeb Michael Hanselmann

908 72737a7f Iustin Pop
    """
909 9a525d83 Michael Hanselmann
    return cls._StaticMultiNodeCall(node_list, "jobqueue_update",
910 9a525d83 Michael Hanselmann
                                    [file_name, content],
911 9a525d83 Michael Hanselmann
                                    address_list=address_list)
912 ca52cdeb Michael Hanselmann
913 9a525d83 Michael Hanselmann
  @classmethod
914 9a525d83 Michael Hanselmann
  def call_jobqueue_purge(cls, node):
915 72737a7f Iustin Pop
    """Purge job queue.
916 ca52cdeb Michael Hanselmann

917 72737a7f Iustin Pop
    This is a single-node call.
918 ca52cdeb Michael Hanselmann

919 72737a7f Iustin Pop
    """
920 9a525d83 Michael Hanselmann
    return cls._StaticSingleNodeCall(node, "jobqueue_purge", [])
921 af5ebcb1 Michael Hanselmann
922 9a525d83 Michael Hanselmann
  @classmethod
923 9a525d83 Michael Hanselmann
  def call_jobqueue_rename(cls, node_list, address_list, old, new):
924 72737a7f Iustin Pop
    """Rename a job queue file.
925 af5ebcb1 Michael Hanselmann

926 72737a7f Iustin Pop
    This is a multi-node call.
927 af5ebcb1 Michael Hanselmann

928 72737a7f Iustin Pop
    """
929 9a525d83 Michael Hanselmann
    return cls._StaticMultiNodeCall(node_list, "jobqueue_rename", [old, new],
930 9a525d83 Michael Hanselmann
                                    address_list=address_list)
931 6217e295 Iustin Pop
932 9a525d83 Michael Hanselmann
  @classmethod
933 9a525d83 Michael Hanselmann
  def call_jobqueue_set_drain(cls, node_list, drain_flag):
934 5d672980 Iustin Pop
    """Set the drain flag on the queue.
935 5d672980 Iustin Pop

936 5d672980 Iustin Pop
    This is a multi-node call.
937 5d672980 Iustin Pop

938 5d672980 Iustin Pop
    @type node_list: list
939 5d672980 Iustin Pop
    @param node_list: the list of nodes to query
940 5d672980 Iustin Pop
    @type drain_flag: bool
941 5d672980 Iustin Pop
    @param drain_flag: if True, will set the drain flag, otherwise reset it.
942 5d672980 Iustin Pop

943 5d672980 Iustin Pop
    """
944 9a525d83 Michael Hanselmann
    return cls._StaticMultiNodeCall(node_list, "jobqueue_set_drain",
945 9a525d83 Michael Hanselmann
                                    [drain_flag])
946 5d672980 Iustin Pop
947 6217e295 Iustin Pop
  def call_hypervisor_validate_params(self, node_list, hvname, hvparams):
948 6217e295 Iustin Pop
    """Validate the hypervisor params.
949 6217e295 Iustin Pop

950 6217e295 Iustin Pop
    This is a multi-node call.
951 6217e295 Iustin Pop

952 6217e295 Iustin Pop
    @type node_list: list
953 6217e295 Iustin Pop
    @param node_list: the list of nodes to query
954 6217e295 Iustin Pop
    @type hvname: string
955 6217e295 Iustin Pop
    @param hvname: the hypervisor name
956 6217e295 Iustin Pop
    @type hvparams: dict
957 6217e295 Iustin Pop
    @param hvparams: the hypervisor parameters to be validated
958 6217e295 Iustin Pop

959 6217e295 Iustin Pop
    """
960 6217e295 Iustin Pop
    cluster = self._cfg.GetClusterInfo()
961 6217e295 Iustin Pop
    hv_full = cluster.FillDict(cluster.hvparams.get(hvname, {}), hvparams)
962 9a525d83 Michael Hanselmann
    return self._MultiNodeCall(node_list, "hypervisor_validate_params",
963 9a525d83 Michael Hanselmann
                               [hvname, hv_full])