Statistics
| Branch: | Tag: | Revision:

root / lib / rpc.py @ afee0879

History | View | Annotate | Download (29.4 kB)

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

24 a8083063 Iustin Pop
"""
25 a8083063 Iustin Pop
26 72737a7f Iustin Pop
# pylint: disable-msg=C0103,R0201,R0904
27 72737a7f Iustin Pop
# C0103: Invalid name, since call_ are not valid
28 72737a7f Iustin Pop
# R0201: Method could be a function, we keep all rpcs instance methods
29 72737a7f Iustin Pop
# as not to change them back and forth between static/instance methods
30 72737a7f Iustin Pop
# if they need to start using instance attributes
31 72737a7f Iustin Pop
# R0904: Too many public methods
32 a8083063 Iustin Pop
33 a8083063 Iustin Pop
import os
34 81010134 Iustin Pop
import socket
35 58b311ca Iustin Pop
import logging
36 12bce260 Michael Hanselmann
import zlib
37 12bce260 Michael Hanselmann
import base64
38 a8083063 Iustin Pop
39 a8083063 Iustin Pop
from ganeti import utils
40 a8083063 Iustin Pop
from ganeti import objects
41 ecfe9491 Michael Hanselmann
from ganeti import http
42 7c28c575 Michael Hanselmann
from ganeti import serializer
43 eafd8762 Michael Hanselmann
from ganeti import constants
44 781de953 Iustin Pop
from ganeti import errors
45 a8083063 Iustin Pop
46 ae88ef45 Michael Hanselmann
import ganeti.http.client
47 ae88ef45 Michael Hanselmann
48 a8083063 Iustin Pop
49 4331f6cd Michael Hanselmann
# Module level variable
50 4331f6cd Michael Hanselmann
_http_manager = None
51 4331f6cd Michael Hanselmann
52 4331f6cd Michael Hanselmann
53 4331f6cd Michael Hanselmann
def Init():
54 4331f6cd Michael Hanselmann
  """Initializes the module-global HTTP client manager.
55 4331f6cd Michael Hanselmann

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

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

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

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

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

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

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

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

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

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

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

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

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

160 a8083063 Iustin Pop
  One current bug is that generic failure is still signalled by
161 a8083063 Iustin Pop
  'False' result, which is not good. This overloading of values can
162 a8083063 Iustin Pop
  cause bugs.
163 a8083063 Iustin Pop

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

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

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

196 bdf7d8c0 Iustin Pop
    @type name: str
197 bdf7d8c0 Iustin Pop
    @param name: the node name
198 bdf7d8c0 Iustin Pop
    @type address: str
199 bdf7d8c0 Iustin Pop
    @keyword address: the node address, if known
200 bdf7d8c0 Iustin Pop

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

215 ecfe9491 Michael Hanselmann
    @rtype: list
216 ecfe9491 Michael Hanselmann
    @returns: List of RPC results
217 a8083063 Iustin Pop

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

431 72737a7f Iustin Pop
    """
432 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "instance_shutdown",
433 9a525d83 Michael Hanselmann
                                [self._InstDict(instance)])
434 2a10865c Iustin Pop
435 72737a7f Iustin Pop
  def call_instance_migrate(self, node, instance, target, live):
436 72737a7f Iustin Pop
    """Migrate an instance.
437 2a10865c Iustin Pop

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

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

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

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

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

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

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

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

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

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

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

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

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

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

506 56e7640c Iustin Pop

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

664 72737a7f Iustin Pop
    """
665 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "blockdev_remove", [bdev.ToDict()])
666 f3e513ad Iustin Pop
667 72737a7f Iustin Pop
  def call_blockdev_rename(self, node, devlist):
668 72737a7f Iustin Pop
    """Request rename of the given block devices.
669 f3e513ad Iustin Pop

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

672 72737a7f Iustin Pop
    """
673 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "blockdev_rename",
674 9a525d83 Michael Hanselmann
                                [(d.ToDict(), uid) for d, uid in devlist])
675 a8083063 Iustin Pop
676 72737a7f Iustin Pop
  def call_blockdev_assemble(self, node, disk, owner, on_primary):
677 72737a7f Iustin Pop
    """Request assembling of a given block device.
678 a8083063 Iustin Pop

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

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

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

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

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

698 72737a7f Iustin Pop
    """
699 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "blockdev_addchildren",
700 9a525d83 Michael Hanselmann
                                [bdev.ToDict(),
701 9a525d83 Michael Hanselmann
                                 [disk.ToDict() for disk in ndevs]])
702 a8083063 Iustin Pop
703 72737a7f Iustin Pop
  def call_blockdev_removechildren(self, node, bdev, ndevs):
704 72737a7f Iustin Pop
    """Request removing a list of children from a (mirroring) device.
705 a8083063 Iustin Pop

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

708 72737a7f Iustin Pop
    """
709 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "blockdev_removechildren",
710 9a525d83 Michael Hanselmann
                                [bdev.ToDict(),
711 9a525d83 Michael Hanselmann
                                 [disk.ToDict() for disk in ndevs]])
712 a8083063 Iustin Pop
713 72737a7f Iustin Pop
  def call_blockdev_getmirrorstatus(self, node, disks):
714 72737a7f Iustin Pop
    """Request status of a (mirroring) device.
715 a8083063 Iustin Pop

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

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

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

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

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

735 72737a7f Iustin Pop
    """
736 b2e7666a Iustin Pop
    params = [instance_name, [cf.ToDict() for cf in disks]]
737 b2e7666a Iustin Pop
    return self._SingleNodeCall(node, "blockdev_close", params)
738 a8083063 Iustin Pop
739 9a525d83 Michael Hanselmann
  @classmethod
740 9a525d83 Michael Hanselmann
  def call_upload_file(cls, node_list, file_name, address_list=None):
741 72737a7f Iustin Pop
    """Upload a file.
742 72737a7f Iustin Pop

743 72737a7f Iustin Pop
    The node will refuse the operation in case the file is not on the
744 72737a7f Iustin Pop
    approved file list.
745 72737a7f Iustin Pop

746 72737a7f Iustin Pop
    This is a multi-node call.
747 a8083063 Iustin Pop

748 6b294c53 Iustin Pop
    @type node_list: list
749 6b294c53 Iustin Pop
    @param node_list: the list of node names to upload to
750 6b294c53 Iustin Pop
    @type file_name: str
751 6b294c53 Iustin Pop
    @param file_name: the filename to upload
752 6b294c53 Iustin Pop
    @type address_list: list or None
753 6b294c53 Iustin Pop
    @keyword address_list: an optional list of node addresses, in order
754 6b294c53 Iustin Pop
        to optimize the RPC speed
755 6b294c53 Iustin Pop

756 72737a7f Iustin Pop
    """
757 12bce260 Michael Hanselmann
    file_contents = utils.ReadFile(file_name)
758 12bce260 Michael Hanselmann
    data = cls._Compress(file_contents)
759 72737a7f Iustin Pop
    st = os.stat(file_name)
760 72737a7f Iustin Pop
    params = [file_name, data, st.st_mode, st.st_uid, st.st_gid,
761 72737a7f Iustin Pop
              st.st_atime, st.st_mtime]
762 9a525d83 Michael Hanselmann
    return cls._StaticMultiNodeCall(node_list, "upload_file", params,
763 9a525d83 Michael Hanselmann
                                    address_list=address_list)
764 72737a7f Iustin Pop
765 6ddc95ec Michael Hanselmann
  @classmethod
766 03d1dba2 Michael Hanselmann
  def call_write_ssconf_files(cls, node_list, values):
767 6ddc95ec Michael Hanselmann
    """Write ssconf files.
768 6ddc95ec Michael Hanselmann

769 6ddc95ec Michael Hanselmann
    This is a multi-node call.
770 6ddc95ec Michael Hanselmann

771 6ddc95ec Michael Hanselmann
    """
772 03d1dba2 Michael Hanselmann
    return cls._StaticMultiNodeCall(node_list, "write_ssconf_files", [values])
773 6ddc95ec Michael Hanselmann
774 72737a7f Iustin Pop
  def call_os_diagnose(self, node_list):
775 72737a7f Iustin Pop
    """Request a diagnose of OS definitions.
776 72737a7f Iustin Pop

777 72737a7f Iustin Pop
    This is a multi-node call.
778 a8083063 Iustin Pop

779 72737a7f Iustin Pop
    """
780 9a525d83 Michael Hanselmann
    result = self._MultiNodeCall(node_list, "os_diagnose", [])
781 9a525d83 Michael Hanselmann
782 fab1e3a4 Iustin Pop
    for node_result in result.values():
783 781de953 Iustin Pop
      if not node_result.failed and node_result.data:
784 781de953 Iustin Pop
        node_result.data = [objects.OS.FromDict(oss)
785 781de953 Iustin Pop
                            for oss in node_result.data]
786 781de953 Iustin Pop
    return result
787 a8083063 Iustin Pop
788 72737a7f Iustin Pop
  def call_os_get(self, node, name):
789 72737a7f Iustin Pop
    """Returns an OS definition.
790 a8083063 Iustin Pop

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

793 72737a7f Iustin Pop
    """
794 9a525d83 Michael Hanselmann
    result = self._SingleNodeCall(node, "os_get", [name])
795 781de953 Iustin Pop
    if not result.failed and isinstance(result.data, dict):
796 781de953 Iustin Pop
      result.data = objects.OS.FromDict(result.data)
797 781de953 Iustin Pop
    return result
798 a8083063 Iustin Pop
799 72737a7f Iustin Pop
  def call_hooks_runner(self, node_list, hpath, phase, env):
800 72737a7f Iustin Pop
    """Call the hooks runner.
801 a8083063 Iustin Pop

802 72737a7f Iustin Pop
    Args:
803 72737a7f Iustin Pop
      - op: the OpCode instance
804 72737a7f Iustin Pop
      - env: a dictionary with the environment
805 a8083063 Iustin Pop

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

808 72737a7f Iustin Pop
    """
809 72737a7f Iustin Pop
    params = [hpath, phase, env]
810 9a525d83 Michael Hanselmann
    return self._MultiNodeCall(node_list, "hooks_runner", params)
811 a8083063 Iustin Pop
812 72737a7f Iustin Pop
  def call_iallocator_runner(self, node, name, idata):
813 72737a7f Iustin Pop
    """Call an iallocator on a remote node
814 8d528b7c Iustin Pop

815 72737a7f Iustin Pop
    Args:
816 72737a7f Iustin Pop
      - name: the iallocator name
817 72737a7f Iustin Pop
      - input: the json-encoded input string
818 8d528b7c Iustin Pop

819 72737a7f Iustin Pop
    This is a single-node call.
820 8d528b7c Iustin Pop

821 72737a7f Iustin Pop
    """
822 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "iallocator_runner", [name, idata])
823 8d528b7c Iustin Pop
824 72737a7f Iustin Pop
  def call_blockdev_grow(self, node, cf_bdev, amount):
825 72737a7f Iustin Pop
    """Request a snapshot of the given block device.
826 4c8ba8b3 Iustin Pop

827 72737a7f Iustin Pop
    This is a single-node call.
828 4c8ba8b3 Iustin Pop

829 72737a7f Iustin Pop
    """
830 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "blockdev_grow",
831 9a525d83 Michael Hanselmann
                                [cf_bdev.ToDict(), amount])
832 4c8ba8b3 Iustin Pop
833 72737a7f Iustin Pop
  def call_blockdev_snapshot(self, node, cf_bdev):
834 72737a7f Iustin Pop
    """Request a snapshot of the given block device.
835 a8083063 Iustin Pop

836 72737a7f Iustin Pop
    This is a single-node call.
837 a8083063 Iustin Pop

838 72737a7f Iustin Pop
    """
839 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "blockdev_snapshot", [cf_bdev.ToDict()])
840 a8083063 Iustin Pop
841 72737a7f Iustin Pop
  def call_snapshot_export(self, node, snap_bdev, dest_node, instance,
842 74c47259 Iustin Pop
                           cluster_name, idx):
843 72737a7f Iustin Pop
    """Request the export of a given snapshot.
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 self._SingleNodeCall(node, "snapshot_export",
849 9a525d83 Michael Hanselmann
                                [snap_bdev.ToDict(), dest_node,
850 9a525d83 Michael Hanselmann
                                 self._InstDict(instance), cluster_name, idx])
851 a8083063 Iustin Pop
852 72737a7f Iustin Pop
  def call_finalize_export(self, node, instance, snap_disks):
853 72737a7f Iustin Pop
    """Request the completion of an export operation.
854 a8083063 Iustin Pop

855 72737a7f Iustin Pop
    This writes the export config file, etc.
856 a8083063 Iustin Pop

857 72737a7f Iustin Pop
    This is a single-node call.
858 a8083063 Iustin Pop

859 72737a7f Iustin Pop
    """
860 72737a7f Iustin Pop
    flat_disks = []
861 72737a7f Iustin Pop
    for disk in snap_disks:
862 72737a7f Iustin Pop
      flat_disks.append(disk.ToDict())
863 9a525d83 Michael Hanselmann
864 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "finalize_export",
865 9a525d83 Michael Hanselmann
                                [self._InstDict(instance), flat_disks])
866 a8083063 Iustin Pop
867 72737a7f Iustin Pop
  def call_export_info(self, node, path):
868 72737a7f Iustin Pop
    """Queries the export information in a given path.
869 a8083063 Iustin Pop

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

872 72737a7f Iustin Pop
    """
873 9a525d83 Michael Hanselmann
    result = self._SingleNodeCall(node, "export_info", [path])
874 781de953 Iustin Pop
    if not result.failed and result.data:
875 781de953 Iustin Pop
      result.data = objects.SerializableConfigParser.Loads(str(result.data))
876 781de953 Iustin Pop
    return result
877 a8083063 Iustin Pop
878 6c0af70e Guido Trotter
  def call_instance_os_import(self, node, inst, src_node, src_images,
879 6c0af70e Guido Trotter
                              cluster_name):
880 72737a7f Iustin Pop
    """Request the import of a backup into an instance.
881 a8083063 Iustin Pop

882 72737a7f Iustin Pop
    This is a single-node call.
883 a8083063 Iustin Pop

884 72737a7f Iustin Pop
    """
885 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "instance_os_import",
886 9a525d83 Michael Hanselmann
                                [self._InstDict(inst), src_node, src_images,
887 9a525d83 Michael Hanselmann
                                 cluster_name])
888 a8083063 Iustin Pop
889 72737a7f Iustin Pop
  def call_export_list(self, node_list):
890 72737a7f Iustin Pop
    """Gets the stored exports list.
891 a8083063 Iustin Pop

892 72737a7f Iustin Pop
    This is a multi-node call.
893 a8083063 Iustin Pop

894 72737a7f Iustin Pop
    """
895 9a525d83 Michael Hanselmann
    return self._MultiNodeCall(node_list, "export_list", [])
896 a8083063 Iustin Pop
897 72737a7f Iustin Pop
  def call_export_remove(self, node, export):
898 72737a7f Iustin Pop
    """Requests removal of a given export.
899 a8083063 Iustin Pop

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

902 72737a7f Iustin Pop
    """
903 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "export_remove", [export])
904 a8083063 Iustin Pop
905 9a525d83 Michael Hanselmann
  @classmethod
906 9a525d83 Michael Hanselmann
  def call_node_leave_cluster(cls, node):
907 72737a7f Iustin Pop
    """Requests a node to clean the cluster information it has.
908 a8083063 Iustin Pop

909 72737a7f Iustin Pop
    This will remove the configuration information from the ganeti data
910 72737a7f Iustin Pop
    dir.
911 a8083063 Iustin Pop

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

914 72737a7f Iustin Pop
    """
915 9a525d83 Michael Hanselmann
    return cls._StaticSingleNodeCall(node, "node_leave_cluster", [])
916 dcb93971 Michael Hanselmann
917 72737a7f Iustin Pop
  def call_node_volumes(self, node_list):
918 72737a7f Iustin Pop
    """Gets all volumes on node(s).
919 dcb93971 Michael Hanselmann

920 72737a7f Iustin Pop
    This is a multi-node call.
921 dcb93971 Michael Hanselmann

922 72737a7f Iustin Pop
    """
923 9a525d83 Michael Hanselmann
    return self._MultiNodeCall(node_list, "node_volumes", [])
924 06009e27 Iustin Pop
925 56aa9fd5 Iustin Pop
  def call_node_demote_from_mc(self, node):
926 56aa9fd5 Iustin Pop
    """Demote a node from the master candidate role.
927 56aa9fd5 Iustin Pop

928 56aa9fd5 Iustin Pop
    This is a single-node call.
929 56aa9fd5 Iustin Pop

930 56aa9fd5 Iustin Pop
    """
931 56aa9fd5 Iustin Pop
    return self._SingleNodeCall(node, "node_demote_from_mc", [])
932 56aa9fd5 Iustin Pop
933 72737a7f Iustin Pop
  def call_test_delay(self, node_list, duration):
934 72737a7f Iustin Pop
    """Sleep for a fixed time on given node(s).
935 06009e27 Iustin Pop

936 72737a7f Iustin Pop
    This is a multi-node call.
937 06009e27 Iustin Pop

938 72737a7f Iustin Pop
    """
939 9a525d83 Michael Hanselmann
    return self._MultiNodeCall(node_list, "test_delay", [duration])
940 5e04ed8b Manuel Franceschini
941 72737a7f Iustin Pop
  def call_file_storage_dir_create(self, node, file_storage_dir):
942 72737a7f Iustin Pop
    """Create the given file storage directory.
943 5e04ed8b Manuel Franceschini

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

946 72737a7f Iustin Pop
    """
947 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "file_storage_dir_create",
948 9a525d83 Michael Hanselmann
                                [file_storage_dir])
949 5e04ed8b Manuel Franceschini
950 72737a7f Iustin Pop
  def call_file_storage_dir_remove(self, node, file_storage_dir):
951 72737a7f Iustin Pop
    """Remove the given file storage directory.
952 5e04ed8b Manuel Franceschini

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

955 72737a7f Iustin Pop
    """
956 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "file_storage_dir_remove",
957 9a525d83 Michael Hanselmann
                                [file_storage_dir])
958 5e04ed8b Manuel Franceschini
959 72737a7f Iustin Pop
  def call_file_storage_dir_rename(self, node, old_file_storage_dir,
960 72737a7f Iustin Pop
                                   new_file_storage_dir):
961 72737a7f Iustin Pop
    """Rename file storage directory.
962 5e04ed8b Manuel Franceschini

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

965 72737a7f Iustin Pop
    """
966 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "file_storage_dir_rename",
967 9a525d83 Michael Hanselmann
                                [old_file_storage_dir, new_file_storage_dir])
968 ca52cdeb Michael Hanselmann
969 9a525d83 Michael Hanselmann
  @classmethod
970 9a525d83 Michael Hanselmann
  def call_jobqueue_update(cls, node_list, address_list, file_name, content):
971 72737a7f Iustin Pop
    """Update job queue.
972 ca52cdeb Michael Hanselmann

973 72737a7f Iustin Pop
    This is a multi-node call.
974 ca52cdeb Michael Hanselmann

975 72737a7f Iustin Pop
    """
976 9a525d83 Michael Hanselmann
    return cls._StaticMultiNodeCall(node_list, "jobqueue_update",
977 12bce260 Michael Hanselmann
                                    [file_name, cls._Compress(content)],
978 9a525d83 Michael Hanselmann
                                    address_list=address_list)
979 ca52cdeb Michael Hanselmann
980 9a525d83 Michael Hanselmann
  @classmethod
981 9a525d83 Michael Hanselmann
  def call_jobqueue_purge(cls, node):
982 72737a7f Iustin Pop
    """Purge job queue.
983 ca52cdeb Michael Hanselmann

984 72737a7f Iustin Pop
    This is a single-node call.
985 ca52cdeb Michael Hanselmann

986 72737a7f Iustin Pop
    """
987 9a525d83 Michael Hanselmann
    return cls._StaticSingleNodeCall(node, "jobqueue_purge", [])
988 af5ebcb1 Michael Hanselmann
989 9a525d83 Michael Hanselmann
  @classmethod
990 dd875d32 Michael Hanselmann
  def call_jobqueue_rename(cls, node_list, address_list, rename):
991 72737a7f Iustin Pop
    """Rename a job queue file.
992 af5ebcb1 Michael Hanselmann

993 72737a7f Iustin Pop
    This is a multi-node call.
994 af5ebcb1 Michael Hanselmann

995 72737a7f Iustin Pop
    """
996 dd875d32 Michael Hanselmann
    return cls._StaticMultiNodeCall(node_list, "jobqueue_rename", rename,
997 9a525d83 Michael Hanselmann
                                    address_list=address_list)
998 6217e295 Iustin Pop
999 9a525d83 Michael Hanselmann
  @classmethod
1000 9a525d83 Michael Hanselmann
  def call_jobqueue_set_drain(cls, node_list, drain_flag):
1001 5d672980 Iustin Pop
    """Set the drain flag on the queue.
1002 5d672980 Iustin Pop

1003 5d672980 Iustin Pop
    This is a multi-node call.
1004 5d672980 Iustin Pop

1005 5d672980 Iustin Pop
    @type node_list: list
1006 5d672980 Iustin Pop
    @param node_list: the list of nodes to query
1007 5d672980 Iustin Pop
    @type drain_flag: bool
1008 5d672980 Iustin Pop
    @param drain_flag: if True, will set the drain flag, otherwise reset it.
1009 5d672980 Iustin Pop

1010 5d672980 Iustin Pop
    """
1011 9a525d83 Michael Hanselmann
    return cls._StaticMultiNodeCall(node_list, "jobqueue_set_drain",
1012 9a525d83 Michael Hanselmann
                                    [drain_flag])
1013 5d672980 Iustin Pop
1014 6217e295 Iustin Pop
  def call_hypervisor_validate_params(self, node_list, hvname, hvparams):
1015 6217e295 Iustin Pop
    """Validate the hypervisor params.
1016 6217e295 Iustin Pop

1017 6217e295 Iustin Pop
    This is a multi-node call.
1018 6217e295 Iustin Pop

1019 6217e295 Iustin Pop
    @type node_list: list
1020 6217e295 Iustin Pop
    @param node_list: the list of nodes to query
1021 6217e295 Iustin Pop
    @type hvname: string
1022 6217e295 Iustin Pop
    @param hvname: the hypervisor name
1023 6217e295 Iustin Pop
    @type hvparams: dict
1024 6217e295 Iustin Pop
    @param hvparams: the hypervisor parameters to be validated
1025 6217e295 Iustin Pop

1026 6217e295 Iustin Pop
    """
1027 6217e295 Iustin Pop
    cluster = self._cfg.GetClusterInfo()
1028 6217e295 Iustin Pop
    hv_full = cluster.FillDict(cluster.hvparams.get(hvname, {}), hvparams)
1029 9a525d83 Michael Hanselmann
    return self._MultiNodeCall(node_list, "hypervisor_validate_params",
1030 9a525d83 Michael Hanselmann
                               [hvname, hv_full])