Statistics
| Branch: | Tag: | Revision:

root / lib / rpc.py @ 0436da49

History | View | Annotate | Download (40.3 kB)

1 2f31098c Iustin Pop
#
2 a8083063 Iustin Pop
#
3 a8083063 Iustin Pop
4 d2cd6944 Iustin Pop
# Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011 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 b459a848 Andrea Spadaccini
# pylint: disable=C0103,R0201,R0904
27 72737a7f Iustin Pop
# C0103: Invalid name, since call_ are not valid
28 72737a7f Iustin Pop
# R0201: Method could be a function, we keep all rpcs instance methods
29 72737a7f Iustin Pop
# as not to change them back and forth between static/instance methods
30 72737a7f Iustin Pop
# if they need to start using instance attributes
31 72737a7f Iustin Pop
# R0904: Too many public methods
32 a8083063 Iustin Pop
33 a8083063 Iustin Pop
import os
34 58b311ca Iustin Pop
import logging
35 12bce260 Michael Hanselmann
import zlib
36 12bce260 Michael Hanselmann
import base64
37 33231500 Michael Hanselmann
import pycurl
38 33231500 Michael Hanselmann
import threading
39 a8083063 Iustin Pop
40 a8083063 Iustin Pop
from ganeti import utils
41 a8083063 Iustin Pop
from ganeti import objects
42 ecfe9491 Michael Hanselmann
from ganeti import http
43 7c28c575 Michael Hanselmann
from ganeti import serializer
44 eafd8762 Michael Hanselmann
from ganeti import constants
45 781de953 Iustin Pop
from ganeti import errors
46 a744b676 Manuel Franceschini
from ganeti import netutils
47 eb202c13 Manuel Franceschini
from ganeti import ssconf
48 9a914f7a René Nussbaumer
from ganeti import runtime
49 00267bfe Michael Hanselmann
from ganeti import compat
50 a8083063 Iustin Pop
51 200de241 Michael Hanselmann
# Special module generated at build time
52 200de241 Michael Hanselmann
from ganeti import _generated_rpc
53 200de241 Michael Hanselmann
54 fe267188 Iustin Pop
# pylint has a bug here, doesn't see this import
55 b459a848 Andrea Spadaccini
import ganeti.http.client  # pylint: disable=W0611
56 ae88ef45 Michael Hanselmann
57 a8083063 Iustin Pop
58 33231500 Michael Hanselmann
# Timeout for connecting to nodes (seconds)
59 33231500 Michael Hanselmann
_RPC_CONNECT_TIMEOUT = 5
60 33231500 Michael Hanselmann
61 33231500 Michael Hanselmann
_RPC_CLIENT_HEADERS = [
62 33231500 Michael Hanselmann
  "Content-type: %s" % http.HTTP_APP_JSON,
63 8e29563f Iustin Pop
  "Expect:",
64 33231500 Michael Hanselmann
  ]
65 4331f6cd Michael Hanselmann
66 92fd2250 Iustin Pop
# Various time constants for the timeout table
67 92fd2250 Iustin Pop
_TMO_URGENT = 60 # one minute
68 92fd2250 Iustin Pop
_TMO_FAST = 5 * 60 # five minutes
69 92fd2250 Iustin Pop
_TMO_NORMAL = 15 * 60 # 15 minutes
70 92fd2250 Iustin Pop
_TMO_SLOW = 3600 # one hour
71 92fd2250 Iustin Pop
_TMO_4HRS = 4 * 3600
72 92fd2250 Iustin Pop
_TMO_1DAY = 86400
73 92fd2250 Iustin Pop
74 92fd2250 Iustin Pop
# Timeout table that will be built later by decorators
75 92fd2250 Iustin Pop
# Guidelines for choosing timeouts:
76 92fd2250 Iustin Pop
# - call used during watcher: timeout -> 1min, _TMO_URGENT
77 92fd2250 Iustin Pop
# - trivial (but be sure it is trivial) (e.g. reading a file): 5min, _TMO_FAST
78 92fd2250 Iustin Pop
# - other calls: 15 min, _TMO_NORMAL
79 92fd2250 Iustin Pop
# - special calls (instance add, etc.): either _TMO_SLOW (1h) or huge timeouts
80 92fd2250 Iustin Pop
81 92fd2250 Iustin Pop
_TIMEOUTS = {
82 92fd2250 Iustin Pop
}
83 92fd2250 Iustin Pop
84 00267bfe Michael Hanselmann
#: Special value to describe an offline host
85 00267bfe Michael Hanselmann
_OFFLINE = object()
86 00267bfe Michael Hanselmann
87 4331f6cd Michael Hanselmann
88 4331f6cd Michael Hanselmann
def Init():
89 4331f6cd Michael Hanselmann
  """Initializes the module-global HTTP client manager.
90 4331f6cd Michael Hanselmann

91 33231500 Michael Hanselmann
  Must be called before using any RPC function and while exactly one thread is
92 33231500 Michael Hanselmann
  running.
93 4331f6cd Michael Hanselmann

94 4331f6cd Michael Hanselmann
  """
95 33231500 Michael Hanselmann
  # curl_global_init(3) and curl_global_cleanup(3) must be called with only
96 33231500 Michael Hanselmann
  # one thread running. This check is just a safety measure -- it doesn't
97 33231500 Michael Hanselmann
  # cover all cases.
98 33231500 Michael Hanselmann
  assert threading.activeCount() == 1, \
99 33231500 Michael Hanselmann
         "Found more than one active thread when initializing pycURL"
100 4331f6cd Michael Hanselmann
101 33231500 Michael Hanselmann
  logging.info("Using PycURL %s", pycurl.version)
102 8d0a4f99 Michael Hanselmann
103 33231500 Michael Hanselmann
  pycurl.global_init(pycurl.GLOBAL_ALL)
104 4331f6cd Michael Hanselmann
105 4331f6cd Michael Hanselmann
106 4331f6cd Michael Hanselmann
def Shutdown():
107 4331f6cd Michael Hanselmann
  """Stops the module-global HTTP client manager.
108 4331f6cd Michael Hanselmann

109 33231500 Michael Hanselmann
  Must be called before quitting the program and while exactly one thread is
110 33231500 Michael Hanselmann
  running.
111 4331f6cd Michael Hanselmann

112 4331f6cd Michael Hanselmann
  """
113 33231500 Michael Hanselmann
  pycurl.global_cleanup()
114 33231500 Michael Hanselmann
115 33231500 Michael Hanselmann
116 33231500 Michael Hanselmann
def _ConfigRpcCurl(curl):
117 33231500 Michael Hanselmann
  noded_cert = str(constants.NODED_CERT_FILE)
118 4331f6cd Michael Hanselmann
119 33231500 Michael Hanselmann
  curl.setopt(pycurl.FOLLOWLOCATION, False)
120 33231500 Michael Hanselmann
  curl.setopt(pycurl.CAINFO, noded_cert)
121 33231500 Michael Hanselmann
  curl.setopt(pycurl.SSL_VERIFYHOST, 0)
122 33231500 Michael Hanselmann
  curl.setopt(pycurl.SSL_VERIFYPEER, True)
123 33231500 Michael Hanselmann
  curl.setopt(pycurl.SSLCERTTYPE, "PEM")
124 33231500 Michael Hanselmann
  curl.setopt(pycurl.SSLCERT, noded_cert)
125 33231500 Michael Hanselmann
  curl.setopt(pycurl.SSLKEYTYPE, "PEM")
126 33231500 Michael Hanselmann
  curl.setopt(pycurl.SSLKEY, noded_cert)
127 33231500 Michael Hanselmann
  curl.setopt(pycurl.CONNECTTIMEOUT, _RPC_CONNECT_TIMEOUT)
128 33231500 Michael Hanselmann
129 33231500 Michael Hanselmann
130 92fd2250 Iustin Pop
def _RpcTimeout(secs):
131 92fd2250 Iustin Pop
  """Timeout decorator.
132 92fd2250 Iustin Pop

133 92fd2250 Iustin Pop
  When applied to a rpc call_* function, it updates the global timeout
134 92fd2250 Iustin Pop
  table with the given function/timeout.
135 92fd2250 Iustin Pop

136 92fd2250 Iustin Pop
  """
137 92fd2250 Iustin Pop
  def decorator(f):
138 92fd2250 Iustin Pop
    name = f.__name__
139 92fd2250 Iustin Pop
    assert name.startswith("call_")
140 92fd2250 Iustin Pop
    _TIMEOUTS[name[len("call_"):]] = secs
141 92fd2250 Iustin Pop
    return f
142 92fd2250 Iustin Pop
  return decorator
143 92fd2250 Iustin Pop
144 92fd2250 Iustin Pop
145 e0e916fe Iustin Pop
def RunWithRPC(fn):
146 e0e916fe Iustin Pop
  """RPC-wrapper decorator.
147 e0e916fe Iustin Pop

148 e0e916fe Iustin Pop
  When applied to a function, it runs it with the RPC system
149 e0e916fe Iustin Pop
  initialized, and it shutsdown the system afterwards. This means the
150 e0e916fe Iustin Pop
  function must be called without RPC being initialized.
151 e0e916fe Iustin Pop

152 e0e916fe Iustin Pop
  """
153 e0e916fe Iustin Pop
  def wrapper(*args, **kwargs):
154 e0e916fe Iustin Pop
    Init()
155 e0e916fe Iustin Pop
    try:
156 e0e916fe Iustin Pop
      return fn(*args, **kwargs)
157 e0e916fe Iustin Pop
    finally:
158 e0e916fe Iustin Pop
      Shutdown()
159 e0e916fe Iustin Pop
  return wrapper
160 e0e916fe Iustin Pop
161 e0e916fe Iustin Pop
162 30474135 Michael Hanselmann
def _Compress(data):
163 30474135 Michael Hanselmann
  """Compresses a string for transport over RPC.
164 30474135 Michael Hanselmann

165 30474135 Michael Hanselmann
  Small amounts of data are not compressed.
166 30474135 Michael Hanselmann

167 30474135 Michael Hanselmann
  @type data: str
168 30474135 Michael Hanselmann
  @param data: Data
169 30474135 Michael Hanselmann
  @rtype: tuple
170 30474135 Michael Hanselmann
  @return: Encoded data to send
171 30474135 Michael Hanselmann

172 30474135 Michael Hanselmann
  """
173 30474135 Michael Hanselmann
  # Small amounts of data are not compressed
174 30474135 Michael Hanselmann
  if len(data) < 512:
175 30474135 Michael Hanselmann
    return (constants.RPC_ENCODING_NONE, data)
176 30474135 Michael Hanselmann
177 30474135 Michael Hanselmann
  # Compress with zlib and encode in base64
178 30474135 Michael Hanselmann
  return (constants.RPC_ENCODING_ZLIB_BASE64,
179 30474135 Michael Hanselmann
          base64.b64encode(zlib.compress(data, 3)))
180 30474135 Michael Hanselmann
181 30474135 Michael Hanselmann
182 781de953 Iustin Pop
class RpcResult(object):
183 781de953 Iustin Pop
  """RPC Result class.
184 781de953 Iustin Pop

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

189 5bbd3f7f Michael Hanselmann
  @ivar data: the data payload, for successful results, or None
190 ed83f5cc Iustin Pop
  @ivar call: the name of the RPC call
191 ed83f5cc Iustin Pop
  @ivar node: the name of the node to which we made the call
192 ed83f5cc Iustin Pop
  @ivar offline: whether the operation failed because the node was
193 ed83f5cc Iustin Pop
      offline, as opposed to actual failure; offline=True will always
194 ed83f5cc Iustin Pop
      imply failed=True, in order to allow simpler checking if
195 ed83f5cc Iustin Pop
      the user doesn't care about the exact failure mode
196 4c4e4e1e Iustin Pop
  @ivar fail_msg: the error message if the call failed
197 ed83f5cc Iustin Pop

198 781de953 Iustin Pop
  """
199 ed83f5cc Iustin Pop
  def __init__(self, data=None, failed=False, offline=False,
200 ed83f5cc Iustin Pop
               call=None, node=None):
201 ed83f5cc Iustin Pop
    self.offline = offline
202 ed83f5cc Iustin Pop
    self.call = call
203 ed83f5cc Iustin Pop
    self.node = node
204 1645d22d Michael Hanselmann
205 ed83f5cc Iustin Pop
    if offline:
206 4c4e4e1e Iustin Pop
      self.fail_msg = "Node is marked offline"
207 f2def43a Iustin Pop
      self.data = self.payload = None
208 ed83f5cc Iustin Pop
    elif failed:
209 4c4e4e1e Iustin Pop
      self.fail_msg = self._EnsureErr(data)
210 f2def43a Iustin Pop
      self.data = self.payload = None
211 781de953 Iustin Pop
    else:
212 781de953 Iustin Pop
      self.data = data
213 d3c8b360 Iustin Pop
      if not isinstance(self.data, (tuple, list)):
214 4c4e4e1e Iustin Pop
        self.fail_msg = ("RPC layer error: invalid result type (%s)" %
215 4c4e4e1e Iustin Pop
                         type(self.data))
216 1645d22d Michael Hanselmann
        self.payload = None
217 d3c8b360 Iustin Pop
      elif len(data) != 2:
218 4c4e4e1e Iustin Pop
        self.fail_msg = ("RPC layer error: invalid result length (%d), "
219 4c4e4e1e Iustin Pop
                         "expected 2" % len(self.data))
220 1645d22d Michael Hanselmann
        self.payload = None
221 d3c8b360 Iustin Pop
      elif not self.data[0]:
222 4c4e4e1e Iustin Pop
        self.fail_msg = self._EnsureErr(self.data[1])
223 1645d22d Michael Hanselmann
        self.payload = None
224 f2def43a Iustin Pop
      else:
225 d3c8b360 Iustin Pop
        # finally success
226 4c4e4e1e Iustin Pop
        self.fail_msg = None
227 d3c8b360 Iustin Pop
        self.payload = data[1]
228 d3c8b360 Iustin Pop
229 2c0f74f2 Iustin Pop
    for attr_name in ["call", "data", "fail_msg",
230 2c0f74f2 Iustin Pop
                      "node", "offline", "payload"]:
231 2c0f74f2 Iustin Pop
      assert hasattr(self, attr_name), "Missing attribute %s" % attr_name
232 1645d22d Michael Hanselmann
233 d3c8b360 Iustin Pop
  @staticmethod
234 d3c8b360 Iustin Pop
  def _EnsureErr(val):
235 d3c8b360 Iustin Pop
    """Helper to ensure we return a 'True' value for error."""
236 d3c8b360 Iustin Pop
    if val:
237 d3c8b360 Iustin Pop
      return val
238 d3c8b360 Iustin Pop
    else:
239 d3c8b360 Iustin Pop
      return "No error information"
240 781de953 Iustin Pop
241 045dd6d9 Iustin Pop
  def Raise(self, msg, prereq=False, ecode=None):
242 781de953 Iustin Pop
    """If the result has failed, raise an OpExecError.
243 781de953 Iustin Pop

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

247 781de953 Iustin Pop
    """
248 4c4e4e1e Iustin Pop
    if not self.fail_msg:
249 4c4e4e1e Iustin Pop
      return
250 4c4e4e1e Iustin Pop
251 4c4e4e1e Iustin Pop
    if not msg: # one could pass None for default message
252 4c4e4e1e Iustin Pop
      msg = ("Call '%s' to node '%s' has failed: %s" %
253 4c4e4e1e Iustin Pop
             (self.call, self.node, self.fail_msg))
254 4c4e4e1e Iustin Pop
    else:
255 4c4e4e1e Iustin Pop
      msg = "%s: %s" % (msg, self.fail_msg)
256 4c4e4e1e Iustin Pop
    if prereq:
257 4c4e4e1e Iustin Pop
      ec = errors.OpPrereqError
258 4c4e4e1e Iustin Pop
    else:
259 4c4e4e1e Iustin Pop
      ec = errors.OpExecError
260 045dd6d9 Iustin Pop
    if ecode is not None:
261 27137e55 Iustin Pop
      args = (msg, ecode)
262 045dd6d9 Iustin Pop
    else:
263 045dd6d9 Iustin Pop
      args = (msg, )
264 b459a848 Andrea Spadaccini
    raise ec(*args) # pylint: disable=W0142
265 781de953 Iustin Pop
266 781de953 Iustin Pop
267 00267bfe Michael Hanselmann
def _SsconfResolver(node_list,
268 00267bfe Michael Hanselmann
                    ssc=ssconf.SimpleStore,
269 00267bfe Michael Hanselmann
                    nslookup_fn=netutils.Hostname.GetIP):
270 eb202c13 Manuel Franceschini
  """Return addresses for given node names.
271 eb202c13 Manuel Franceschini

272 eb202c13 Manuel Franceschini
  @type node_list: list
273 eb202c13 Manuel Franceschini
  @param node_list: List of node names
274 eb202c13 Manuel Franceschini
  @type ssc: class
275 eb202c13 Manuel Franceschini
  @param ssc: SimpleStore class that is used to obtain node->ip mappings
276 17f7fd27 Manuel Franceschini
  @type nslookup_fn: callable
277 17f7fd27 Manuel Franceschini
  @param nslookup_fn: function use to do NS lookup
278 00267bfe Michael Hanselmann
  @rtype: list of tuple; (string, string)
279 00267bfe Michael Hanselmann
  @return: List of tuples containing node name and IP address
280 eb202c13 Manuel Franceschini

281 eb202c13 Manuel Franceschini
  """
282 b43dcc5a Manuel Franceschini
  ss = ssc()
283 b43dcc5a Manuel Franceschini
  iplist = ss.GetNodePrimaryIPList()
284 b43dcc5a Manuel Franceschini
  family = ss.GetPrimaryIPFamily()
285 b705c7a6 Manuel Franceschini
  ipmap = dict(entry.split() for entry in iplist)
286 00267bfe Michael Hanselmann
287 00267bfe Michael Hanselmann
  result = []
288 b705c7a6 Manuel Franceschini
  for node in node_list:
289 00267bfe Michael Hanselmann
    ip = ipmap.get(node)
290 00267bfe Michael Hanselmann
    if ip is None:
291 00267bfe Michael Hanselmann
      ip = nslookup_fn(node, family=family)
292 00267bfe Michael Hanselmann
    result.append((node, ip))
293 00267bfe Michael Hanselmann
294 00267bfe Michael Hanselmann
  return result
295 00267bfe Michael Hanselmann
296 00267bfe Michael Hanselmann
297 00267bfe Michael Hanselmann
class _StaticResolver:
298 00267bfe Michael Hanselmann
  def __init__(self, addresses):
299 00267bfe Michael Hanselmann
    """Initializes this class.
300 00267bfe Michael Hanselmann

301 00267bfe Michael Hanselmann
    """
302 00267bfe Michael Hanselmann
    self._addresses = addresses
303 00267bfe Michael Hanselmann
304 00267bfe Michael Hanselmann
  def __call__(self, hosts):
305 00267bfe Michael Hanselmann
    """Returns static addresses for hosts.
306 00267bfe Michael Hanselmann

307 00267bfe Michael Hanselmann
    """
308 00267bfe Michael Hanselmann
    assert len(hosts) == len(self._addresses)
309 00267bfe Michael Hanselmann
    return zip(hosts, self._addresses)
310 00267bfe Michael Hanselmann
311 eb202c13 Manuel Franceschini
312 00267bfe Michael Hanselmann
def _CheckConfigNode(name, node):
313 00267bfe Michael Hanselmann
  """Checks if a node is online.
314 eb202c13 Manuel Franceschini

315 00267bfe Michael Hanselmann
  @type name: string
316 00267bfe Michael Hanselmann
  @param name: Node name
317 00267bfe Michael Hanselmann
  @type node: L{objects.Node} or None
318 00267bfe Michael Hanselmann
  @param node: Node object
319 eb202c13 Manuel Franceschini

320 00267bfe Michael Hanselmann
  """
321 00267bfe Michael Hanselmann
  if node is None:
322 00267bfe Michael Hanselmann
    # Depend on DNS for name resolution
323 00267bfe Michael Hanselmann
    ip = name
324 00267bfe Michael Hanselmann
  elif node.offline:
325 00267bfe Michael Hanselmann
    ip = _OFFLINE
326 00267bfe Michael Hanselmann
  else:
327 00267bfe Michael Hanselmann
    ip = node.primary_ip
328 00267bfe Michael Hanselmann
  return (name, ip)
329 a8083063 Iustin Pop
330 a8083063 Iustin Pop
331 00267bfe Michael Hanselmann
def _NodeConfigResolver(single_node_fn, all_nodes_fn, hosts):
332 00267bfe Michael Hanselmann
  """Calculate node addresses using configuration.
333 a8083063 Iustin Pop

334 a8083063 Iustin Pop
  """
335 00267bfe Michael Hanselmann
  # Special case for single-host lookups
336 00267bfe Michael Hanselmann
  if len(hosts) == 1:
337 00267bfe Michael Hanselmann
    (name, ) = hosts
338 00267bfe Michael Hanselmann
    return [_CheckConfigNode(name, single_node_fn(name))]
339 00267bfe Michael Hanselmann
  else:
340 00267bfe Michael Hanselmann
    all_nodes = all_nodes_fn()
341 00267bfe Michael Hanselmann
    return [_CheckConfigNode(name, all_nodes.get(name, None))
342 00267bfe Michael Hanselmann
            for name in hosts]
343 00267bfe Michael Hanselmann
344 00267bfe Michael Hanselmann
345 00267bfe Michael Hanselmann
class _RpcProcessor:
346 aea5caef Michael Hanselmann
  def __init__(self, resolver, port, lock_monitor_cb=None):
347 00267bfe Michael Hanselmann
    """Initializes this class.
348 00267bfe Michael Hanselmann

349 00267bfe Michael Hanselmann
    @param resolver: callable accepting a list of hostnames, returning a list
350 00267bfe Michael Hanselmann
      of tuples containing name and IP address (IP address can be the name or
351 00267bfe Michael Hanselmann
      the special value L{_OFFLINE} to mark offline machines)
352 00267bfe Michael Hanselmann
    @type port: int
353 00267bfe Michael Hanselmann
    @param port: TCP port
354 aea5caef Michael Hanselmann
    @param lock_monitor_cb: Callable for registering with lock monitor
355 3ef3c771 Iustin Pop

356 a8083063 Iustin Pop
    """
357 00267bfe Michael Hanselmann
    self._resolver = resolver
358 00267bfe Michael Hanselmann
    self._port = port
359 aea5caef Michael Hanselmann
    self._lock_monitor_cb = lock_monitor_cb
360 eb202c13 Manuel Franceschini
361 00267bfe Michael Hanselmann
  @staticmethod
362 00267bfe Michael Hanselmann
  def _PrepareRequests(hosts, port, procedure, body, read_timeout):
363 00267bfe Michael Hanselmann
    """Prepares requests by sorting offline hosts into separate list.
364 eb202c13 Manuel Franceschini

365 00267bfe Michael Hanselmann
    """
366 00267bfe Michael Hanselmann
    results = {}
367 00267bfe Michael Hanselmann
    requests = {}
368 bdf7d8c0 Iustin Pop
369 00267bfe Michael Hanselmann
    for (name, ip) in hosts:
370 00267bfe Michael Hanselmann
      if ip is _OFFLINE:
371 00267bfe Michael Hanselmann
        # Node is marked as offline
372 00267bfe Michael Hanselmann
        results[name] = RpcResult(node=name, offline=True, call=procedure)
373 00267bfe Michael Hanselmann
      else:
374 00267bfe Michael Hanselmann
        requests[name] = \
375 00267bfe Michael Hanselmann
          http.client.HttpClientRequest(str(ip), port,
376 00267bfe Michael Hanselmann
                                        http.HTTP_PUT, str("/%s" % procedure),
377 00267bfe Michael Hanselmann
                                        headers=_RPC_CLIENT_HEADERS,
378 00267bfe Michael Hanselmann
                                        post_data=body,
379 7cb2d205 Michael Hanselmann
                                        read_timeout=read_timeout,
380 abbf2cd9 Michael Hanselmann
                                        nicename="%s/%s" % (name, procedure),
381 abbf2cd9 Michael Hanselmann
                                        curl_config_fn=_ConfigRpcCurl)
382 a8083063 Iustin Pop
383 00267bfe Michael Hanselmann
    return (results, requests)
384 00267bfe Michael Hanselmann
385 00267bfe Michael Hanselmann
  @staticmethod
386 00267bfe Michael Hanselmann
  def _CombineResults(results, requests, procedure):
387 00267bfe Michael Hanselmann
    """Combines pre-computed results for offline hosts with actual call results.
388 bdf7d8c0 Iustin Pop

389 a8083063 Iustin Pop
    """
390 00267bfe Michael Hanselmann
    for name, req in requests.items():
391 00267bfe Michael Hanselmann
      if req.success and req.resp_status_code == http.HTTP_OK:
392 00267bfe Michael Hanselmann
        host_result = RpcResult(data=serializer.LoadJson(req.resp_body),
393 00267bfe Michael Hanselmann
                                node=name, call=procedure)
394 00267bfe Michael Hanselmann
      else:
395 00267bfe Michael Hanselmann
        # TODO: Better error reporting
396 00267bfe Michael Hanselmann
        if req.error:
397 00267bfe Michael Hanselmann
          msg = req.error
398 00267bfe Michael Hanselmann
        else:
399 00267bfe Michael Hanselmann
          msg = req.resp_body
400 eb202c13 Manuel Franceschini
401 00267bfe Michael Hanselmann
        logging.error("RPC error in %s on node %s: %s", procedure, name, msg)
402 00267bfe Michael Hanselmann
        host_result = RpcResult(data=msg, failed=True, node=name,
403 00267bfe Michael Hanselmann
                                call=procedure)
404 ecfe9491 Michael Hanselmann
405 00267bfe Michael Hanselmann
      results[name] = host_result
406 92fd2250 Iustin Pop
407 00267bfe Michael Hanselmann
    return results
408 a8083063 Iustin Pop
409 abbf2cd9 Michael Hanselmann
  def __call__(self, hosts, procedure, body, read_timeout=None,
410 abbf2cd9 Michael Hanselmann
               _req_process_fn=http.client.ProcessRequests):
411 00267bfe Michael Hanselmann
    """Makes an RPC request to a number of nodes.
412 ecfe9491 Michael Hanselmann

413 00267bfe Michael Hanselmann
    @type hosts: sequence
414 00267bfe Michael Hanselmann
    @param hosts: Hostnames
415 00267bfe Michael Hanselmann
    @type procedure: string
416 00267bfe Michael Hanselmann
    @param procedure: Request path
417 00267bfe Michael Hanselmann
    @type body: string
418 00267bfe Michael Hanselmann
    @param body: Request body
419 00267bfe Michael Hanselmann
    @type read_timeout: int or None
420 00267bfe Michael Hanselmann
    @param read_timeout: Read timeout for request
421 a8083063 Iustin Pop

422 a8083063 Iustin Pop
    """
423 00267bfe Michael Hanselmann
    if read_timeout is None:
424 83e7af18 Michael Hanselmann
      read_timeout = _TIMEOUTS.get(procedure, None)
425 83e7af18 Michael Hanselmann
426 83e7af18 Michael Hanselmann
    assert read_timeout is not None, \
427 83e7af18 Michael Hanselmann
      "Missing RPC read timeout for procedure '%s'" % procedure
428 a8083063 Iustin Pop
429 00267bfe Michael Hanselmann
    (results, requests) = \
430 00267bfe Michael Hanselmann
      self._PrepareRequests(self._resolver(hosts), self._port, procedure,
431 00267bfe Michael Hanselmann
                            str(body), read_timeout)
432 a8083063 Iustin Pop
433 abbf2cd9 Michael Hanselmann
    _req_process_fn(requests.values(), lock_monitor_cb=self._lock_monitor_cb)
434 a8083063 Iustin Pop
435 00267bfe Michael Hanselmann
    assert not frozenset(results).intersection(requests)
436 ecfe9491 Michael Hanselmann
437 00267bfe Michael Hanselmann
    return self._CombineResults(results, requests, procedure)
438 a8083063 Iustin Pop
439 a8083063 Iustin Pop
440 1651d116 Michael Hanselmann
def _EncodeImportExportIO(ieio, ieioargs):
441 1651d116 Michael Hanselmann
  """Encodes import/export I/O information.
442 1651d116 Michael Hanselmann

443 1651d116 Michael Hanselmann
  """
444 1651d116 Michael Hanselmann
  if ieio == constants.IEIO_RAW_DISK:
445 1651d116 Michael Hanselmann
    assert len(ieioargs) == 1
446 1651d116 Michael Hanselmann
    return (ieioargs[0].ToDict(), )
447 1651d116 Michael Hanselmann
448 1651d116 Michael Hanselmann
  if ieio == constants.IEIO_SCRIPT:
449 1651d116 Michael Hanselmann
    assert len(ieioargs) == 2
450 1651d116 Michael Hanselmann
    return (ieioargs[0].ToDict(), ieioargs[1])
451 1651d116 Michael Hanselmann
452 1651d116 Michael Hanselmann
  return ieioargs
453 1651d116 Michael Hanselmann
454 1651d116 Michael Hanselmann
455 200de241 Michael Hanselmann
class RpcRunner(_generated_rpc.RpcClientDefault):
456 87b3cb26 Michael Hanselmann
  """RPC runner class.
457 a8083063 Iustin Pop

458 87b3cb26 Michael Hanselmann
  """
459 87b3cb26 Michael Hanselmann
  def __init__(self, context):
460 87b3cb26 Michael Hanselmann
    """Initialized the RPC runner.
461 a8083063 Iustin Pop

462 87b3cb26 Michael Hanselmann
    @type context: C{masterd.GanetiContext}
463 87b3cb26 Michael Hanselmann
    @param context: Ganeti context
464 a8083063 Iustin Pop

465 72737a7f Iustin Pop
    """
466 200de241 Michael Hanselmann
    _generated_rpc.RpcClientDefault.__init__(self)
467 200de241 Michael Hanselmann
468 87b3cb26 Michael Hanselmann
    self._cfg = context.cfg
469 00267bfe Michael Hanselmann
    self._proc = _RpcProcessor(compat.partial(_NodeConfigResolver,
470 00267bfe Michael Hanselmann
                                              self._cfg.GetNodeInfo,
471 00267bfe Michael Hanselmann
                                              self._cfg.GetAllNodesInfo),
472 aea5caef Michael Hanselmann
                               netutils.GetDaemonPort(constants.NODED),
473 aea5caef Michael Hanselmann
                               lock_monitor_cb=context.glm.AddToLockMonitor)
474 a8083063 Iustin Pop
475 1bdcbbab Iustin Pop
  def _InstDict(self, instance, hvp=None, bep=None, osp=None):
476 26ba2bd8 Iustin Pop
    """Convert the given instance to a dict.
477 26ba2bd8 Iustin Pop

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

481 26ba2bd8 Iustin Pop
    @type instance: L{objects.Instance}
482 26ba2bd8 Iustin Pop
    @param instance: an Instance object
483 0eca8e0c Iustin Pop
    @type hvp: dict or None
484 5bbd3f7f Michael Hanselmann
    @param hvp: a dictionary with overridden hypervisor parameters
485 0eca8e0c Iustin Pop
    @type bep: dict or None
486 5bbd3f7f Michael Hanselmann
    @param bep: a dictionary with overridden backend parameters
487 1bdcbbab Iustin Pop
    @type osp: dict or None
488 8d8c4eff Michael Hanselmann
    @param osp: a dictionary with overridden os parameters
489 26ba2bd8 Iustin Pop
    @rtype: dict
490 26ba2bd8 Iustin Pop
    @return: the instance dict, with the hvparams filled with the
491 26ba2bd8 Iustin Pop
        cluster defaults
492 26ba2bd8 Iustin Pop

493 26ba2bd8 Iustin Pop
    """
494 26ba2bd8 Iustin Pop
    idict = instance.ToDict()
495 5b442704 Iustin Pop
    cluster = self._cfg.GetClusterInfo()
496 5b442704 Iustin Pop
    idict["hvparams"] = cluster.FillHV(instance)
497 0eca8e0c Iustin Pop
    if hvp is not None:
498 0eca8e0c Iustin Pop
      idict["hvparams"].update(hvp)
499 5b442704 Iustin Pop
    idict["beparams"] = cluster.FillBE(instance)
500 0eca8e0c Iustin Pop
    if bep is not None:
501 0eca8e0c Iustin Pop
      idict["beparams"].update(bep)
502 1bdcbbab Iustin Pop
    idict["osparams"] = cluster.SimpleFillOS(instance.os, instance.osparams)
503 1bdcbbab Iustin Pop
    if osp is not None:
504 1bdcbbab Iustin Pop
      idict["osparams"].update(osp)
505 b848ce79 Guido Trotter
    for nic in idict["nics"]:
506 b848ce79 Guido Trotter
      nic['nicparams'] = objects.FillDict(
507 b848ce79 Guido Trotter
        cluster.nicparams[constants.PP_DEFAULT],
508 b848ce79 Guido Trotter
        nic['nicparams'])
509 26ba2bd8 Iustin Pop
    return idict
510 26ba2bd8 Iustin Pop
511 e0036155 Iustin Pop
  def _MultiNodeCall(self, node_list, procedure, args, read_timeout=None):
512 160e2921 Iustin Pop
    """Helper for making a multi-node call
513 160e2921 Iustin Pop

514 160e2921 Iustin Pop
    """
515 160e2921 Iustin Pop
    body = serializer.DumpJson(args, indent=False)
516 00267bfe Michael Hanselmann
    return self._proc(node_list, procedure, body, read_timeout=read_timeout)
517 9a525d83 Michael Hanselmann
518 200de241 Michael Hanselmann
  def _Call(self, node_list, procedure, timeout, args):
519 200de241 Michael Hanselmann
    """Entry point for automatically generated RPC wrappers.
520 200de241 Michael Hanselmann

521 200de241 Michael Hanselmann
    """
522 200de241 Michael Hanselmann
    return self._MultiNodeCall(node_list, procedure, args, read_timeout=timeout)
523 200de241 Michael Hanselmann
524 00267bfe Michael Hanselmann
  @staticmethod
525 00267bfe Michael Hanselmann
  def _StaticMultiNodeCall(node_list, procedure, args,
526 e0036155 Iustin Pop
                           address_list=None, read_timeout=None):
527 160e2921 Iustin Pop
    """Helper for making a multi-node static call
528 160e2921 Iustin Pop

529 160e2921 Iustin Pop
    """
530 160e2921 Iustin Pop
    body = serializer.DumpJson(args, indent=False)
531 00267bfe Michael Hanselmann
532 00267bfe Michael Hanselmann
    if address_list is None:
533 00267bfe Michael Hanselmann
      resolver = _SsconfResolver
534 00267bfe Michael Hanselmann
    else:
535 00267bfe Michael Hanselmann
      # Caller provided an address list
536 00267bfe Michael Hanselmann
      resolver = _StaticResolver(address_list)
537 00267bfe Michael Hanselmann
538 00267bfe Michael Hanselmann
    proc = _RpcProcessor(resolver,
539 00267bfe Michael Hanselmann
                         netutils.GetDaemonPort(constants.NODED))
540 00267bfe Michael Hanselmann
    return proc(node_list, procedure, body, read_timeout=read_timeout)
541 9a525d83 Michael Hanselmann
542 e0036155 Iustin Pop
  def _SingleNodeCall(self, node, procedure, args, read_timeout=None):
543 160e2921 Iustin Pop
    """Helper for making a single-node call
544 9a525d83 Michael Hanselmann

545 9a525d83 Michael Hanselmann
    """
546 160e2921 Iustin Pop
    body = serializer.DumpJson(args, indent=False)
547 00267bfe Michael Hanselmann
    return self._proc([node], procedure, body, read_timeout=read_timeout)[node]
548 9a525d83 Michael Hanselmann
549 9a525d83 Michael Hanselmann
  @classmethod
550 e0036155 Iustin Pop
  def _StaticSingleNodeCall(cls, node, procedure, args, read_timeout=None):
551 160e2921 Iustin Pop
    """Helper for making a single-node static call
552 9a525d83 Michael Hanselmann

553 9a525d83 Michael Hanselmann
    """
554 160e2921 Iustin Pop
    body = serializer.DumpJson(args, indent=False)
555 00267bfe Michael Hanselmann
    proc = _RpcProcessor(_SsconfResolver,
556 00267bfe Michael Hanselmann
                         netutils.GetDaemonPort(constants.NODED))
557 00267bfe Michael Hanselmann
    return proc([node], procedure, body, read_timeout=read_timeout)[node]
558 9a525d83 Michael Hanselmann
559 efc71a02 Michael Hanselmann
  @staticmethod
560 efc71a02 Michael Hanselmann
  def _BlockdevFindPostProc(result):
561 efc71a02 Michael Hanselmann
    if not result.fail_msg and result.payload is not None:
562 efc71a02 Michael Hanselmann
      result.payload = objects.BlockDevStatus.FromDict(result.payload)
563 efc71a02 Michael Hanselmann
    return result
564 efc71a02 Michael Hanselmann
565 efc71a02 Michael Hanselmann
  @staticmethod
566 efc71a02 Michael Hanselmann
  def _BlockdevGetMirrorStatusPostProc(result):
567 efc71a02 Michael Hanselmann
    if not result.fail_msg:
568 efc71a02 Michael Hanselmann
      result.payload = [objects.BlockDevStatus.FromDict(i)
569 efc71a02 Michael Hanselmann
                        for i in result.payload]
570 efc71a02 Michael Hanselmann
    return result
571 efc71a02 Michael Hanselmann
572 efc71a02 Michael Hanselmann
  @staticmethod
573 efc71a02 Michael Hanselmann
  def _BlockdevGetMirrorStatusMultiPostProc(result):
574 efc71a02 Michael Hanselmann
    for nres in result.values():
575 efc71a02 Michael Hanselmann
      if nres.fail_msg:
576 efc71a02 Michael Hanselmann
        continue
577 efc71a02 Michael Hanselmann
578 efc71a02 Michael Hanselmann
      for idx, (success, status) in enumerate(nres.payload):
579 efc71a02 Michael Hanselmann
        if success:
580 efc71a02 Michael Hanselmann
          nres.payload[idx] = (success, objects.BlockDevStatus.FromDict(status))
581 efc71a02 Michael Hanselmann
582 efc71a02 Michael Hanselmann
    return result
583 efc71a02 Michael Hanselmann
584 efc71a02 Michael Hanselmann
  @staticmethod
585 efc71a02 Michael Hanselmann
  def _OsGetPostProc(result):
586 efc71a02 Michael Hanselmann
    if not result.fail_msg and isinstance(result.payload, dict):
587 efc71a02 Michael Hanselmann
      result.payload = objects.OS.FromDict(result.payload)
588 efc71a02 Michael Hanselmann
    return result
589 efc71a02 Michael Hanselmann
590 efc71a02 Michael Hanselmann
  @staticmethod
591 efc71a02 Michael Hanselmann
  def _PrepareFinalizeExportDisks(snap_disks):
592 efc71a02 Michael Hanselmann
    flat_disks = []
593 efc71a02 Michael Hanselmann
594 efc71a02 Michael Hanselmann
    for disk in snap_disks:
595 efc71a02 Michael Hanselmann
      if isinstance(disk, bool):
596 efc71a02 Michael Hanselmann
        flat_disks.append(disk)
597 efc71a02 Michael Hanselmann
      else:
598 efc71a02 Michael Hanselmann
        flat_disks.append(disk.ToDict())
599 efc71a02 Michael Hanselmann
600 efc71a02 Michael Hanselmann
    return flat_disks
601 efc71a02 Michael Hanselmann
602 efc71a02 Michael Hanselmann
  @staticmethod
603 efc71a02 Michael Hanselmann
  def _ImpExpStatusPostProc(result):
604 efc71a02 Michael Hanselmann
    """Post-processor for import/export status.
605 efc71a02 Michael Hanselmann

606 efc71a02 Michael Hanselmann
    @rtype: Payload containing list of L{objects.ImportExportStatus} instances
607 efc71a02 Michael Hanselmann
    @return: Returns a list of the state of each named import/export or None if
608 efc71a02 Michael Hanselmann
             a status couldn't be retrieved
609 efc71a02 Michael Hanselmann

610 efc71a02 Michael Hanselmann
    """
611 efc71a02 Michael Hanselmann
    if not result.fail_msg:
612 efc71a02 Michael Hanselmann
      decoded = []
613 efc71a02 Michael Hanselmann
614 efc71a02 Michael Hanselmann
      for i in result.payload:
615 efc71a02 Michael Hanselmann
        if i is None:
616 efc71a02 Michael Hanselmann
          decoded.append(None)
617 efc71a02 Michael Hanselmann
          continue
618 efc71a02 Michael Hanselmann
        decoded.append(objects.ImportExportStatus.FromDict(i))
619 efc71a02 Michael Hanselmann
620 efc71a02 Michael Hanselmann
      result.payload = decoded
621 efc71a02 Michael Hanselmann
622 efc71a02 Michael Hanselmann
    return result
623 efc71a02 Michael Hanselmann
624 781de953 Iustin Pop
  #
625 781de953 Iustin Pop
  # Begin RPC calls
626 781de953 Iustin Pop
  #
627 781de953 Iustin Pop
628 92fd2250 Iustin Pop
  @_RpcTimeout(_TMO_URGENT)
629 2be7273c Apollon Oikonomopoulos
  def call_bdev_sizes(self, node_list, devices):
630 2be7273c Apollon Oikonomopoulos
    """Gets the sizes of requested block devices present on a node
631 2be7273c Apollon Oikonomopoulos

632 2be7273c Apollon Oikonomopoulos
    This is a multi-node call.
633 2be7273c Apollon Oikonomopoulos

634 2be7273c Apollon Oikonomopoulos
    """
635 2be7273c Apollon Oikonomopoulos
    return self._MultiNodeCall(node_list, "bdev_sizes", [devices])
636 2be7273c Apollon Oikonomopoulos
637 92fd2250 Iustin Pop
  @_RpcTimeout(_TMO_NORMAL)
638 e337de97 Michael Hanselmann
  def call_storage_list(self, node_list, su_name, su_args, name, fields):
639 8979196a Michael Hanselmann
    """Get list of storage units.
640 e337de97 Michael Hanselmann

641 e337de97 Michael Hanselmann
    This is a multi-node call.
642 e337de97 Michael Hanselmann

643 e337de97 Michael Hanselmann
    """
644 e337de97 Michael Hanselmann
    return self._MultiNodeCall(node_list, "storage_list",
645 e337de97 Michael Hanselmann
                               [su_name, su_args, name, fields])
646 e337de97 Michael Hanselmann
647 92fd2250 Iustin Pop
  @_RpcTimeout(_TMO_NORMAL)
648 8979196a Michael Hanselmann
  def call_storage_modify(self, node, su_name, su_args, name, changes):
649 8979196a Michael Hanselmann
    """Modify a storage unit.
650 8979196a Michael Hanselmann

651 8979196a Michael Hanselmann
    This is a single-node call.
652 8979196a Michael Hanselmann

653 8979196a Michael Hanselmann
    """
654 8979196a Michael Hanselmann
    return self._SingleNodeCall(node, "storage_modify",
655 8979196a Michael Hanselmann
                                [su_name, su_args, name, changes])
656 8979196a Michael Hanselmann
657 92fd2250 Iustin Pop
  @_RpcTimeout(_TMO_NORMAL)
658 637b8d7e Michael Hanselmann
  def call_storage_execute(self, node, su_name, su_args, name, op):
659 637b8d7e Michael Hanselmann
    """Executes an operation on a storage unit.
660 637b8d7e Michael Hanselmann

661 637b8d7e Michael Hanselmann
    This is a single-node call.
662 637b8d7e Michael Hanselmann

663 637b8d7e Michael Hanselmann
    """
664 637b8d7e Michael Hanselmann
    return self._SingleNodeCall(node, "storage_execute",
665 637b8d7e Michael Hanselmann
                                [su_name, su_args, name, op])
666 637b8d7e Michael Hanselmann
667 92fd2250 Iustin Pop
  @_RpcTimeout(_TMO_NORMAL)
668 323f9095 Stephen Shirley
  def call_instance_start(self, node, instance, hvp, bep, startup_paused):
669 72737a7f Iustin Pop
    """Starts an instance.
670 a8083063 Iustin Pop

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

673 72737a7f Iustin Pop
    """
674 0eca8e0c Iustin Pop
    idict = self._InstDict(instance, hvp=hvp, bep=bep)
675 323f9095 Stephen Shirley
    return self._SingleNodeCall(node, "instance_start", [idict, startup_paused])
676 a8083063 Iustin Pop
677 92fd2250 Iustin Pop
  @_RpcTimeout(_TMO_NORMAL)
678 6263189c Guido Trotter
  def call_instance_shutdown(self, node, instance, timeout):
679 72737a7f Iustin Pop
    """Stops an instance.
680 a8083063 Iustin Pop

681 72737a7f Iustin Pop
    This is a single-node call.
682 2a10865c Iustin Pop

683 72737a7f Iustin Pop
    """
684 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "instance_shutdown",
685 6263189c Guido Trotter
                                [self._InstDict(instance), timeout])
686 2a10865c Iustin Pop
687 92fd2250 Iustin Pop
  @_RpcTimeout(_TMO_NORMAL)
688 6906a9d8 Guido Trotter
  def call_migration_info(self, node, instance):
689 6906a9d8 Guido Trotter
    """Gather the information necessary to prepare an instance migration.
690 6906a9d8 Guido Trotter

691 6906a9d8 Guido Trotter
    This is a single-node call.
692 6906a9d8 Guido Trotter

693 6906a9d8 Guido Trotter
    @type node: string
694 6906a9d8 Guido Trotter
    @param node: the node on which the instance is currently running
695 6906a9d8 Guido Trotter
    @type instance: C{objects.Instance}
696 6906a9d8 Guido Trotter
    @param instance: the instance definition
697 6906a9d8 Guido Trotter

698 6906a9d8 Guido Trotter
    """
699 6906a9d8 Guido Trotter
    return self._SingleNodeCall(node, "migration_info",
700 6906a9d8 Guido Trotter
                                [self._InstDict(instance)])
701 6906a9d8 Guido Trotter
702 92fd2250 Iustin Pop
  @_RpcTimeout(_TMO_NORMAL)
703 6906a9d8 Guido Trotter
  def call_accept_instance(self, node, instance, info, target):
704 6906a9d8 Guido Trotter
    """Prepare a node to accept an instance.
705 6906a9d8 Guido Trotter

706 6906a9d8 Guido Trotter
    This is a single-node call.
707 6906a9d8 Guido Trotter

708 6906a9d8 Guido Trotter
    @type node: string
709 6906a9d8 Guido Trotter
    @param node: the target node for the migration
710 6906a9d8 Guido Trotter
    @type instance: C{objects.Instance}
711 6906a9d8 Guido Trotter
    @param instance: the instance definition
712 6906a9d8 Guido Trotter
    @type info: opaque/hypervisor specific (string/data)
713 6906a9d8 Guido Trotter
    @param info: result for the call_migration_info call
714 6906a9d8 Guido Trotter
    @type target: string
715 6906a9d8 Guido Trotter
    @param target: target hostname (usually ip address) (on the node itself)
716 6906a9d8 Guido Trotter

717 6906a9d8 Guido Trotter
    """
718 6906a9d8 Guido Trotter
    return self._SingleNodeCall(node, "accept_instance",
719 6906a9d8 Guido Trotter
                                [self._InstDict(instance), info, target])
720 6906a9d8 Guido Trotter
721 92fd2250 Iustin Pop
  @_RpcTimeout(_TMO_NORMAL)
722 6a1434d7 Andrea Spadaccini
  def call_instance_finalize_migration_dst(self, node, instance, info, success):
723 6906a9d8 Guido Trotter
    """Finalize any target-node migration specific operation.
724 6906a9d8 Guido Trotter

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

728 6906a9d8 Guido Trotter
    This is a single-node call.
729 6906a9d8 Guido Trotter

730 6906a9d8 Guido Trotter
    @type node: string
731 6906a9d8 Guido Trotter
    @param node: the target node for the migration
732 6906a9d8 Guido Trotter
    @type instance: C{objects.Instance}
733 6906a9d8 Guido Trotter
    @param instance: the instance definition
734 6906a9d8 Guido Trotter
    @type info: opaque/hypervisor specific (string/data)
735 6906a9d8 Guido Trotter
    @param info: result for the call_migration_info call
736 6906a9d8 Guido Trotter
    @type success: boolean
737 6906a9d8 Guido Trotter
    @param success: whether the migration was a success or a failure
738 6906a9d8 Guido Trotter

739 6906a9d8 Guido Trotter
    """
740 6a1434d7 Andrea Spadaccini
    return self._SingleNodeCall(node, "instance_finalize_migration_dst",
741 6906a9d8 Guido Trotter
                                [self._InstDict(instance), info, success])
742 6906a9d8 Guido Trotter
743 92fd2250 Iustin Pop
  @_RpcTimeout(_TMO_SLOW)
744 72737a7f Iustin Pop
  def call_instance_migrate(self, node, instance, target, live):
745 72737a7f Iustin Pop
    """Migrate an instance.
746 2a10865c Iustin Pop

747 72737a7f Iustin Pop
    This is a single-node call.
748 2a10865c Iustin Pop

749 72737a7f Iustin Pop
    @type node: string
750 72737a7f Iustin Pop
    @param node: the node on which the instance is currently running
751 72737a7f Iustin Pop
    @type instance: C{objects.Instance}
752 72737a7f Iustin Pop
    @param instance: the instance definition
753 72737a7f Iustin Pop
    @type target: string
754 72737a7f Iustin Pop
    @param target: the target node name
755 72737a7f Iustin Pop
    @type live: boolean
756 72737a7f Iustin Pop
    @param live: whether the migration should be done live or not (the
757 72737a7f Iustin Pop
        interpretation of this parameter is left to the hypervisor)
758 007a2f3e Alexander Schreiber

759 72737a7f Iustin Pop
    """
760 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "instance_migrate",
761 9a525d83 Michael Hanselmann
                                [self._InstDict(instance), target, live])
762 007a2f3e Alexander Schreiber
763 6a1434d7 Andrea Spadaccini
  @_RpcTimeout(_TMO_SLOW)
764 6a1434d7 Andrea Spadaccini
  def call_instance_finalize_migration_src(self, node, instance, success, live):
765 6a1434d7 Andrea Spadaccini
    """Finalize the instance migration on the source node.
766 6a1434d7 Andrea Spadaccini

767 6a1434d7 Andrea Spadaccini
    This is a single-node call.
768 6a1434d7 Andrea Spadaccini

769 6a1434d7 Andrea Spadaccini
    @type instance: L{objects.Instance}
770 6a1434d7 Andrea Spadaccini
    @param instance: the instance that was migrated
771 6a1434d7 Andrea Spadaccini
    @type success: bool
772 6a1434d7 Andrea Spadaccini
    @param success: whether the migration succeeded or not
773 6a1434d7 Andrea Spadaccini
    @type live: bool
774 6a1434d7 Andrea Spadaccini
    @param live: whether the user requested a live migration or not
775 6a1434d7 Andrea Spadaccini

776 6a1434d7 Andrea Spadaccini
    """
777 6a1434d7 Andrea Spadaccini
    return self._SingleNodeCall(node, "instance_finalize_migration_src",
778 6a1434d7 Andrea Spadaccini
                                [self._InstDict(instance), success, live])
779 6a1434d7 Andrea Spadaccini
780 6a1434d7 Andrea Spadaccini
  @_RpcTimeout(_TMO_SLOW)
781 6a1434d7 Andrea Spadaccini
  def call_instance_get_migration_status(self, node, instance):
782 6a1434d7 Andrea Spadaccini
    """Report migration status.
783 6a1434d7 Andrea Spadaccini

784 6a1434d7 Andrea Spadaccini
    This is a single-node call that must be executed on the source node.
785 6a1434d7 Andrea Spadaccini

786 6a1434d7 Andrea Spadaccini
    @type instance: L{objects.Instance}
787 6a1434d7 Andrea Spadaccini
    @param instance: the instance that is being migrated
788 6a1434d7 Andrea Spadaccini
    @rtype: L{objects.MigrationStatus}
789 6a1434d7 Andrea Spadaccini
    @return: the status of the current migration (one of
790 6a1434d7 Andrea Spadaccini
             L{constants.HV_MIGRATION_VALID_STATUSES}), plus any additional
791 6a1434d7 Andrea Spadaccini
             progress info that can be retrieved from the hypervisor
792 6a1434d7 Andrea Spadaccini

793 6a1434d7 Andrea Spadaccini
    """
794 6a1434d7 Andrea Spadaccini
    result = self._SingleNodeCall(node, "instance_get_migration_status",
795 6a1434d7 Andrea Spadaccini
                                  [self._InstDict(instance)])
796 6a1434d7 Andrea Spadaccini
    if not result.fail_msg and result.payload is not None:
797 6a1434d7 Andrea Spadaccini
      result.payload = objects.MigrationStatus.FromDict(result.payload)
798 6a1434d7 Andrea Spadaccini
    return result
799 6a1434d7 Andrea Spadaccini
800 92fd2250 Iustin Pop
  @_RpcTimeout(_TMO_NORMAL)
801 17c3f802 Guido Trotter
  def call_instance_reboot(self, node, inst, reboot_type, shutdown_timeout):
802 72737a7f Iustin Pop
    """Reboots an instance.
803 007a2f3e Alexander Schreiber

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

806 72737a7f Iustin Pop
    """
807 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "instance_reboot",
808 17c3f802 Guido Trotter
                                [self._InstDict(inst), reboot_type,
809 17c3f802 Guido Trotter
                                 shutdown_timeout])
810 a8083063 Iustin Pop
811 92fd2250 Iustin Pop
  @_RpcTimeout(_TMO_1DAY)
812 8d8c4eff Michael Hanselmann
  def call_instance_os_add(self, node, inst, reinstall, debug, osparams=None):
813 72737a7f Iustin Pop
    """Installs an OS on the given instance.
814 a8083063 Iustin Pop

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

817 72737a7f Iustin Pop
    """
818 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "instance_os_add",
819 8d8c4eff Michael Hanselmann
                                [self._InstDict(inst, osp=osparams),
820 8d8c4eff Michael Hanselmann
                                 reinstall, debug])
821 decd5f45 Iustin Pop
822 92fd2250 Iustin Pop
  @_RpcTimeout(_TMO_SLOW)
823 4a0e011f Iustin Pop
  def call_instance_run_rename(self, node, inst, old_name, debug):
824 72737a7f Iustin Pop
    """Run the OS rename script for an instance.
825 decd5f45 Iustin Pop

826 72737a7f Iustin Pop
    This is a single-node call.
827 a8083063 Iustin Pop

828 72737a7f Iustin Pop
    """
829 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "instance_run_rename",
830 4a0e011f Iustin Pop
                                [self._InstDict(inst), old_name, debug])
831 a8083063 Iustin Pop
832 92fd2250 Iustin Pop
  @_RpcTimeout(_TMO_URGENT)
833 72737a7f Iustin Pop
  def call_instance_info(self, node, instance, hname):
834 72737a7f Iustin Pop
    """Returns information about a single instance.
835 a8083063 Iustin Pop

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

838 9a525d83 Michael Hanselmann
    @type node: list
839 9a525d83 Michael Hanselmann
    @param node: the list of nodes to query
840 72737a7f Iustin Pop
    @type instance: string
841 72737a7f Iustin Pop
    @param instance: the instance name
842 72737a7f Iustin Pop
    @type hname: string
843 72737a7f Iustin Pop
    @param hname: the hypervisor type of the instance
844 a8083063 Iustin Pop

845 72737a7f Iustin Pop
    """
846 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "instance_info", [instance, hname])
847 e69d05fd Iustin Pop
848 92fd2250 Iustin Pop
  @_RpcTimeout(_TMO_NORMAL)
849 56e7640c Iustin Pop
  def call_instance_migratable(self, node, instance):
850 56e7640c Iustin Pop
    """Checks whether the given instance can be migrated.
851 56e7640c Iustin Pop

852 56e7640c Iustin Pop
    This is a single-node call.
853 56e7640c Iustin Pop

854 56e7640c Iustin Pop
    @param node: the node to query
855 56e7640c Iustin Pop
    @type instance: L{objects.Instance}
856 56e7640c Iustin Pop
    @param instance: the instance to check
857 56e7640c Iustin Pop

858 56e7640c Iustin Pop

859 56e7640c Iustin Pop
    """
860 56e7640c Iustin Pop
    return self._SingleNodeCall(node, "instance_migratable",
861 56e7640c Iustin Pop
                                [self._InstDict(instance)])
862 56e7640c Iustin Pop
863 92fd2250 Iustin Pop
  @_RpcTimeout(_TMO_URGENT)
864 72737a7f Iustin Pop
  def call_all_instances_info(self, node_list, hypervisor_list):
865 72737a7f Iustin Pop
    """Returns information about all instances on the given nodes.
866 a8083063 Iustin Pop

867 72737a7f Iustin Pop
    This is a multi-node call.
868 a8083063 Iustin Pop

869 72737a7f Iustin Pop
    @type node_list: list
870 72737a7f Iustin Pop
    @param node_list: the list of nodes to query
871 72737a7f Iustin Pop
    @type hypervisor_list: list
872 72737a7f Iustin Pop
    @param hypervisor_list: the hypervisors to query for instances
873 a8083063 Iustin Pop

874 72737a7f Iustin Pop
    """
875 9a525d83 Michael Hanselmann
    return self._MultiNodeCall(node_list, "all_instances_info",
876 9a525d83 Michael Hanselmann
                               [hypervisor_list])
877 e69d05fd Iustin Pop
878 92fd2250 Iustin Pop
  @_RpcTimeout(_TMO_URGENT)
879 72737a7f Iustin Pop
  def call_instance_list(self, node_list, hypervisor_list):
880 72737a7f Iustin Pop
    """Returns the list of running instances on a given node.
881 a8083063 Iustin Pop

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

884 72737a7f Iustin Pop
    @type node_list: list
885 72737a7f Iustin Pop
    @param node_list: the list of nodes to query
886 72737a7f Iustin Pop
    @type hypervisor_list: list
887 72737a7f Iustin Pop
    @param hypervisor_list: the hypervisors to query for instances
888 16abfbc2 Alexander Schreiber

889 72737a7f Iustin Pop
    """
890 9a525d83 Michael Hanselmann
    return self._MultiNodeCall(node_list, "instance_list", [hypervisor_list])
891 16abfbc2 Alexander Schreiber
892 9a525d83 Michael Hanselmann
  @classmethod
893 92fd2250 Iustin Pop
  @_RpcTimeout(_TMO_FAST)
894 fb460cf7 Andrea Spadaccini
  def call_node_start_master_daemons(cls, node, no_voting):
895 fb460cf7 Andrea Spadaccini
    """Starts master daemons on a node.
896 a8083063 Iustin Pop

897 72737a7f Iustin Pop
    This is a single-node call.
898 a8083063 Iustin Pop

899 72737a7f Iustin Pop
    """
900 fb460cf7 Andrea Spadaccini
    return cls._StaticSingleNodeCall(node, "node_start_master_daemons",
901 fb460cf7 Andrea Spadaccini
                                     [no_voting])
902 a8083063 Iustin Pop
903 9a525d83 Michael Hanselmann
  @classmethod
904 92fd2250 Iustin Pop
  @_RpcTimeout(_TMO_FAST)
905 fb460cf7 Andrea Spadaccini
  def call_node_activate_master_ip(cls, node):
906 fb460cf7 Andrea Spadaccini
    """Activates master IP on a node.
907 a8083063 Iustin Pop

908 72737a7f Iustin Pop
    This is a single-node call.
909 4e071d3b Iustin Pop

910 72737a7f Iustin Pop
    """
911 fb460cf7 Andrea Spadaccini
    return cls._StaticSingleNodeCall(node, "node_activate_master_ip", [])
912 fb460cf7 Andrea Spadaccini
913 fb460cf7 Andrea Spadaccini
  @classmethod
914 fb460cf7 Andrea Spadaccini
  @_RpcTimeout(_TMO_FAST)
915 fb460cf7 Andrea Spadaccini
  def call_node_stop_master(cls, node):
916 fb460cf7 Andrea Spadaccini
    """Deactivates master IP and stops master daemons on a node.
917 fb460cf7 Andrea Spadaccini

918 fb460cf7 Andrea Spadaccini
    This is a single-node call.
919 fb460cf7 Andrea Spadaccini

920 fb460cf7 Andrea Spadaccini
    """
921 fb460cf7 Andrea Spadaccini
    return cls._StaticSingleNodeCall(node, "node_stop_master", [])
922 fb460cf7 Andrea Spadaccini
923 fb460cf7 Andrea Spadaccini
  @classmethod
924 fb460cf7 Andrea Spadaccini
  @_RpcTimeout(_TMO_FAST)
925 fb460cf7 Andrea Spadaccini
  def call_node_deactivate_master_ip(cls, node):
926 fb460cf7 Andrea Spadaccini
    """Deactivates master IP on a node.
927 fb460cf7 Andrea Spadaccini

928 fb460cf7 Andrea Spadaccini
    This is a single-node call.
929 fb460cf7 Andrea Spadaccini

930 fb460cf7 Andrea Spadaccini
    """
931 fb460cf7 Andrea Spadaccini
    return cls._StaticSingleNodeCall(node, "node_deactivate_master_ip", [])
932 4e071d3b Iustin Pop
933 9a525d83 Michael Hanselmann
  @classmethod
934 5a8648eb Andrea Spadaccini
  @_RpcTimeout(_TMO_FAST)
935 5a8648eb Andrea Spadaccini
  def call_node_change_master_netmask(cls, node, netmask):
936 5a8648eb Andrea Spadaccini
    """Change master IP netmask.
937 5a8648eb Andrea Spadaccini

938 5a8648eb Andrea Spadaccini
    This is a single-node call.
939 5a8648eb Andrea Spadaccini

940 5a8648eb Andrea Spadaccini
    """
941 5a8648eb Andrea Spadaccini
    return cls._StaticSingleNodeCall(node, "node_change_master_netmask",
942 5a8648eb Andrea Spadaccini
                  [netmask])
943 5a8648eb Andrea Spadaccini
944 5a8648eb Andrea Spadaccini
  @classmethod
945 92fd2250 Iustin Pop
  @_RpcTimeout(_TMO_URGENT)
946 9a525d83 Michael Hanselmann
  def call_master_info(cls, node_list):
947 72737a7f Iustin Pop
    """Query master info.
948 4e071d3b Iustin Pop

949 72737a7f Iustin Pop
    This is a multi-node call.
950 a8083063 Iustin Pop

951 72737a7f Iustin Pop
    """
952 72737a7f Iustin Pop
    # TODO: should this method query down nodes?
953 9a525d83 Michael Hanselmann
    return cls._StaticMultiNodeCall(node_list, "master_info", [])
954 a8083063 Iustin Pop
955 8f215968 Michael Hanselmann
  @classmethod
956 92fd2250 Iustin Pop
  @_RpcTimeout(_TMO_URGENT)
957 8f215968 Michael Hanselmann
  def call_version(cls, node_list):
958 72737a7f Iustin Pop
    """Query node version.
959 a8083063 Iustin Pop

960 72737a7f Iustin Pop
    This is a multi-node call.
961 a8083063 Iustin Pop

962 72737a7f Iustin Pop
    """
963 8f215968 Michael Hanselmann
    return cls._StaticMultiNodeCall(node_list, "version", [])
964 a8083063 Iustin Pop
965 92fd2250 Iustin Pop
  @_RpcTimeout(_TMO_NORMAL)
966 72737a7f Iustin Pop
  def call_blockdev_create(self, node, bdev, size, owner, on_primary, info):
967 72737a7f Iustin Pop
    """Request creation of a given block device.
968 a8083063 Iustin Pop

969 72737a7f Iustin Pop
    This is a single-node call.
970 a8083063 Iustin Pop

971 72737a7f Iustin Pop
    """
972 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "blockdev_create",
973 9a525d83 Michael Hanselmann
                                [bdev.ToDict(), size, owner, on_primary, info])
974 a8083063 Iustin Pop
975 271b7cf9 René Nussbaumer
  @_RpcTimeout(_TMO_SLOW)
976 271b7cf9 René Nussbaumer
  def call_blockdev_wipe(self, node, bdev, offset, size):
977 271b7cf9 René Nussbaumer
    """Request wipe at given offset with given size of a block device.
978 271b7cf9 René Nussbaumer

979 271b7cf9 René Nussbaumer
    This is a single-node call.
980 271b7cf9 René Nussbaumer

981 271b7cf9 René Nussbaumer
    """
982 271b7cf9 René Nussbaumer
    return self._SingleNodeCall(node, "blockdev_wipe",
983 271b7cf9 René Nussbaumer
                                [bdev.ToDict(), offset, size])
984 271b7cf9 René Nussbaumer
985 92fd2250 Iustin Pop
  @_RpcTimeout(_TMO_NORMAL)
986 72737a7f Iustin Pop
  def call_blockdev_remove(self, node, bdev):
987 72737a7f Iustin Pop
    """Request removal of a given block device.
988 a8083063 Iustin Pop

989 72737a7f Iustin Pop
    This is a single-node call.
990 f3e513ad Iustin Pop

991 72737a7f Iustin Pop
    """
992 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "blockdev_remove", [bdev.ToDict()])
993 f3e513ad Iustin Pop
994 92fd2250 Iustin Pop
  @_RpcTimeout(_TMO_NORMAL)
995 72737a7f Iustin Pop
  def call_blockdev_rename(self, node, devlist):
996 72737a7f Iustin Pop
    """Request rename of the given block devices.
997 f3e513ad Iustin Pop

998 72737a7f Iustin Pop
    This is a single-node call.
999 a8083063 Iustin Pop

1000 72737a7f Iustin Pop
    """
1001 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "blockdev_rename",
1002 8a31717c Michael Hanselmann
                                [[(d.ToDict(), uid) for d, uid in devlist]])
1003 a8083063 Iustin Pop
1004 92fd2250 Iustin Pop
  @_RpcTimeout(_TMO_NORMAL)
1005 9c007da8 René Nussbaumer
  def call_blockdev_pause_resume_sync(self, node, disks, pause):
1006 9c007da8 René Nussbaumer
    """Request a pause/resume of given block device.
1007 9c007da8 René Nussbaumer

1008 9c007da8 René Nussbaumer
    This is a single-node call.
1009 9c007da8 René Nussbaumer

1010 9c007da8 René Nussbaumer
    """
1011 9c007da8 René Nussbaumer
    return self._SingleNodeCall(node, "blockdev_pause_resume_sync",
1012 9c007da8 René Nussbaumer
                                [[bdev.ToDict() for bdev in disks], pause])
1013 9c007da8 René Nussbaumer
1014 9c007da8 René Nussbaumer
  @_RpcTimeout(_TMO_NORMAL)
1015 c417e115 Iustin Pop
  def call_blockdev_assemble(self, node, disk, owner, on_primary, idx):
1016 72737a7f Iustin Pop
    """Request assembling of a given block device.
1017 a8083063 Iustin Pop

1018 72737a7f Iustin Pop
    This is a single-node call.
1019 a8083063 Iustin Pop

1020 72737a7f Iustin Pop
    """
1021 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "blockdev_assemble",
1022 c417e115 Iustin Pop
                                [disk.ToDict(), owner, on_primary, idx])
1023 a8083063 Iustin Pop
1024 92fd2250 Iustin Pop
  @_RpcTimeout(_TMO_NORMAL)
1025 72737a7f Iustin Pop
  def call_blockdev_shutdown(self, node, disk):
1026 72737a7f Iustin Pop
    """Request shutdown of a given block device.
1027 a8083063 Iustin Pop

1028 72737a7f Iustin Pop
    This is a single-node call.
1029 a8083063 Iustin Pop

1030 72737a7f Iustin Pop
    """
1031 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "blockdev_shutdown", [disk.ToDict()])
1032 a8083063 Iustin Pop
1033 92fd2250 Iustin Pop
  @_RpcTimeout(_TMO_NORMAL)
1034 72737a7f Iustin Pop
  def call_blockdev_addchildren(self, node, bdev, ndevs):
1035 72737a7f Iustin Pop
    """Request adding a list of children to a (mirroring) device.
1036 a8083063 Iustin Pop

1037 72737a7f Iustin Pop
    This is a single-node call.
1038 a8083063 Iustin Pop

1039 72737a7f Iustin Pop
    """
1040 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "blockdev_addchildren",
1041 9a525d83 Michael Hanselmann
                                [bdev.ToDict(),
1042 9a525d83 Michael Hanselmann
                                 [disk.ToDict() for disk in ndevs]])
1043 a8083063 Iustin Pop
1044 92fd2250 Iustin Pop
  @_RpcTimeout(_TMO_NORMAL)
1045 72737a7f Iustin Pop
  def call_blockdev_removechildren(self, node, bdev, ndevs):
1046 72737a7f Iustin Pop
    """Request removing a list of children from a (mirroring) device.
1047 a8083063 Iustin Pop

1048 72737a7f Iustin Pop
    This is a single-node call.
1049 a8083063 Iustin Pop

1050 72737a7f Iustin Pop
    """
1051 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "blockdev_removechildren",
1052 9a525d83 Michael Hanselmann
                                [bdev.ToDict(),
1053 9a525d83 Michael Hanselmann
                                 [disk.ToDict() for disk in ndevs]])
1054 a8083063 Iustin Pop
1055 92fd2250 Iustin Pop
  @_RpcTimeout(_TMO_NORMAL)
1056 72737a7f Iustin Pop
  def call_blockdev_getmirrorstatus(self, node, disks):
1057 72737a7f Iustin Pop
    """Request status of a (mirroring) device.
1058 a8083063 Iustin Pop

1059 72737a7f Iustin Pop
    This is a single-node call.
1060 a8083063 Iustin Pop

1061 72737a7f Iustin Pop
    """
1062 36145b12 Michael Hanselmann
    result = self._SingleNodeCall(node, "blockdev_getmirrorstatus",
1063 36145b12 Michael Hanselmann
                                  [dsk.ToDict() for dsk in disks])
1064 edb4b374 Michael Hanselmann
    if not result.fail_msg:
1065 36145b12 Michael Hanselmann
      result.payload = [objects.BlockDevStatus.FromDict(i)
1066 36145b12 Michael Hanselmann
                        for i in result.payload]
1067 36145b12 Michael Hanselmann
    return result
1068 a8083063 Iustin Pop
1069 92fd2250 Iustin Pop
  @_RpcTimeout(_TMO_NORMAL)
1070 b8d26c6e Michael Hanselmann
  def call_blockdev_getmirrorstatus_multi(self, node_list, node_disks):
1071 b8d26c6e Michael Hanselmann
    """Request status of (mirroring) devices from multiple nodes.
1072 b8d26c6e Michael Hanselmann

1073 b8d26c6e Michael Hanselmann
    This is a multi-node call.
1074 b8d26c6e Michael Hanselmann

1075 b8d26c6e Michael Hanselmann
    """
1076 b8d26c6e Michael Hanselmann
    result = self._MultiNodeCall(node_list, "blockdev_getmirrorstatus_multi",
1077 b8d26c6e Michael Hanselmann
                                 [dict((name, [dsk.ToDict() for dsk in disks])
1078 b8d26c6e Michael Hanselmann
                                       for name, disks in node_disks.items())])
1079 b8d26c6e Michael Hanselmann
    for nres in result.values():
1080 c6a9dffa Michael Hanselmann
      if nres.fail_msg:
1081 c6a9dffa Michael Hanselmann
        continue
1082 c6a9dffa Michael Hanselmann
1083 c6a9dffa Michael Hanselmann
      for idx, (success, status) in enumerate(nres.payload):
1084 c6a9dffa Michael Hanselmann
        if success:
1085 c6a9dffa Michael Hanselmann
          nres.payload[idx] = (success, objects.BlockDevStatus.FromDict(status))
1086 c6a9dffa Michael Hanselmann
1087 b8d26c6e Michael Hanselmann
    return result
1088 b8d26c6e Michael Hanselmann
1089 b8d26c6e Michael Hanselmann
  @_RpcTimeout(_TMO_NORMAL)
1090 72737a7f Iustin Pop
  def call_blockdev_find(self, node, disk):
1091 72737a7f Iustin Pop
    """Request identification of a given block device.
1092 72737a7f Iustin Pop

1093 72737a7f Iustin Pop
    This is a single-node call.
1094 a8083063 Iustin Pop

1095 72737a7f Iustin Pop
    """
1096 96acbc09 Michael Hanselmann
    result = self._SingleNodeCall(node, "blockdev_find", [disk.ToDict()])
1097 edb4b374 Michael Hanselmann
    if not result.fail_msg and result.payload is not None:
1098 96acbc09 Michael Hanselmann
      result.payload = objects.BlockDevStatus.FromDict(result.payload)
1099 96acbc09 Michael Hanselmann
    return result
1100 d61cbe76 Iustin Pop
1101 92fd2250 Iustin Pop
  @_RpcTimeout(_TMO_NORMAL)
1102 b2e7666a Iustin Pop
  def call_blockdev_close(self, node, instance_name, disks):
1103 72737a7f Iustin Pop
    """Closes the given block devices.
1104 d61cbe76 Iustin Pop

1105 72737a7f Iustin Pop
    This is a single-node call.
1106 d61cbe76 Iustin Pop

1107 72737a7f Iustin Pop
    """
1108 b2e7666a Iustin Pop
    params = [instance_name, [cf.ToDict() for cf in disks]]
1109 b2e7666a Iustin Pop
    return self._SingleNodeCall(node, "blockdev_close", params)
1110 a8083063 Iustin Pop
1111 92fd2250 Iustin Pop
  @_RpcTimeout(_TMO_NORMAL)
1112 ccfbbd2d Iustin Pop
  def call_blockdev_getsize(self, node, disks):
1113 968a7623 Iustin Pop
    """Returns the size of the given disks.
1114 968a7623 Iustin Pop

1115 968a7623 Iustin Pop
    This is a single-node call.
1116 968a7623 Iustin Pop

1117 968a7623 Iustin Pop
    """
1118 968a7623 Iustin Pop
    params = [[cf.ToDict() for cf in disks]]
1119 968a7623 Iustin Pop
    return self._SingleNodeCall(node, "blockdev_getsize", params)
1120 968a7623 Iustin Pop
1121 92fd2250 Iustin Pop
  @_RpcTimeout(_TMO_NORMAL)
1122 6b93ec9d Iustin Pop
  def call_drbd_disconnect_net(self, node_list, nodes_ip, disks):
1123 6b93ec9d Iustin Pop
    """Disconnects the network of the given drbd devices.
1124 6b93ec9d Iustin Pop

1125 6b93ec9d Iustin Pop
    This is a multi-node call.
1126 6b93ec9d Iustin Pop

1127 6b93ec9d Iustin Pop
    """
1128 6b93ec9d Iustin Pop
    return self._MultiNodeCall(node_list, "drbd_disconnect_net",
1129 6b93ec9d Iustin Pop
                               [nodes_ip, [cf.ToDict() for cf in disks]])
1130 6b93ec9d Iustin Pop
1131 92fd2250 Iustin Pop
  @_RpcTimeout(_TMO_NORMAL)
1132 6b93ec9d Iustin Pop
  def call_drbd_attach_net(self, node_list, nodes_ip,
1133 6b93ec9d Iustin Pop
                           disks, instance_name, multimaster):
1134 6b93ec9d Iustin Pop
    """Disconnects the given drbd devices.
1135 6b93ec9d Iustin Pop

1136 6b93ec9d Iustin Pop
    This is a multi-node call.
1137 6b93ec9d Iustin Pop

1138 6b93ec9d Iustin Pop
    """
1139 6b93ec9d Iustin Pop
    return self._MultiNodeCall(node_list, "drbd_attach_net",
1140 6b93ec9d Iustin Pop
                               [nodes_ip, [cf.ToDict() for cf in disks],
1141 6b93ec9d Iustin Pop
                                instance_name, multimaster])
1142 6b93ec9d Iustin Pop
1143 92fd2250 Iustin Pop
  @_RpcTimeout(_TMO_SLOW)
1144 6b93ec9d Iustin Pop
  def call_drbd_wait_sync(self, node_list, nodes_ip, disks):
1145 6b93ec9d Iustin Pop
    """Waits for the synchronization of drbd devices is complete.
1146 6b93ec9d Iustin Pop

1147 6b93ec9d Iustin Pop
    This is a multi-node call.
1148 6b93ec9d Iustin Pop

1149 6b93ec9d Iustin Pop
    """
1150 6b93ec9d Iustin Pop
    return self._MultiNodeCall(node_list, "drbd_wait_sync",
1151 6b93ec9d Iustin Pop
                               [nodes_ip, [cf.ToDict() for cf in disks]])
1152 6b93ec9d Iustin Pop
1153 c46b9782 Luca Bigliardi
  @_RpcTimeout(_TMO_URGENT)
1154 c46b9782 Luca Bigliardi
  def call_drbd_helper(self, node_list):
1155 c46b9782 Luca Bigliardi
    """Gets drbd helper.
1156 c46b9782 Luca Bigliardi

1157 c46b9782 Luca Bigliardi
    This is a multi-node call.
1158 c46b9782 Luca Bigliardi

1159 c46b9782 Luca Bigliardi
    """
1160 c46b9782 Luca Bigliardi
    return self._MultiNodeCall(node_list, "drbd_helper", [])
1161 c46b9782 Luca Bigliardi
1162 9a525d83 Michael Hanselmann
  @classmethod
1163 92fd2250 Iustin Pop
  @_RpcTimeout(_TMO_NORMAL)
1164 9a525d83 Michael Hanselmann
  def call_upload_file(cls, node_list, file_name, address_list=None):
1165 72737a7f Iustin Pop
    """Upload a file.
1166 72737a7f Iustin Pop

1167 72737a7f Iustin Pop
    The node will refuse the operation in case the file is not on the
1168 72737a7f Iustin Pop
    approved file list.
1169 72737a7f Iustin Pop

1170 72737a7f Iustin Pop
    This is a multi-node call.
1171 a8083063 Iustin Pop

1172 6b294c53 Iustin Pop
    @type node_list: list
1173 6b294c53 Iustin Pop
    @param node_list: the list of node names to upload to
1174 6b294c53 Iustin Pop
    @type file_name: str
1175 6b294c53 Iustin Pop
    @param file_name: the filename to upload
1176 6b294c53 Iustin Pop
    @type address_list: list or None
1177 6b294c53 Iustin Pop
    @keyword address_list: an optional list of node addresses, in order
1178 6b294c53 Iustin Pop
        to optimize the RPC speed
1179 6b294c53 Iustin Pop

1180 72737a7f Iustin Pop
    """
1181 12bce260 Michael Hanselmann
    file_contents = utils.ReadFile(file_name)
1182 30474135 Michael Hanselmann
    data = _Compress(file_contents)
1183 72737a7f Iustin Pop
    st = os.stat(file_name)
1184 9a914f7a René Nussbaumer
    getents = runtime.GetEnts()
1185 9a914f7a René Nussbaumer
    params = [file_name, data, st.st_mode, getents.LookupUid(st.st_uid),
1186 9a914f7a René Nussbaumer
              getents.LookupGid(st.st_gid), st.st_atime, st.st_mtime]
1187 9a525d83 Michael Hanselmann
    return cls._StaticMultiNodeCall(node_list, "upload_file", params,
1188 9a525d83 Michael Hanselmann
                                    address_list=address_list)
1189 72737a7f Iustin Pop
1190 6ddc95ec Michael Hanselmann
  @classmethod
1191 92fd2250 Iustin Pop
  @_RpcTimeout(_TMO_NORMAL)
1192 03d1dba2 Michael Hanselmann
  def call_write_ssconf_files(cls, node_list, values):
1193 6ddc95ec Michael Hanselmann
    """Write ssconf files.
1194 6ddc95ec Michael Hanselmann

1195 6ddc95ec Michael Hanselmann
    This is a multi-node call.
1196 6ddc95ec Michael Hanselmann

1197 6ddc95ec Michael Hanselmann
    """
1198 03d1dba2 Michael Hanselmann
    return cls._StaticMultiNodeCall(node_list, "write_ssconf_files", [values])
1199 6ddc95ec Michael Hanselmann
1200 4f6014d4 René Nussbaumer
  @_RpcTimeout(_TMO_NORMAL)
1201 a59faf4b Iustin Pop
  def call_blockdev_grow(self, node, cf_bdev, amount, dryrun):
1202 72737a7f Iustin Pop
    """Request a snapshot of the given block device.
1203 4c8ba8b3 Iustin Pop

1204 72737a7f Iustin Pop
    This is a single-node call.
1205 4c8ba8b3 Iustin Pop

1206 72737a7f Iustin Pop
    """
1207 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "blockdev_grow",
1208 a59faf4b Iustin Pop
                                [cf_bdev.ToDict(), amount, dryrun])
1209 4c8ba8b3 Iustin Pop
1210 92fd2250 Iustin Pop
  @_RpcTimeout(_TMO_1DAY)
1211 858f3d18 Iustin Pop
  def call_blockdev_export(self, node, cf_bdev,
1212 858f3d18 Iustin Pop
                           dest_node, dest_path, cluster_name):
1213 858f3d18 Iustin Pop
    """Export a given disk to another node.
1214 858f3d18 Iustin Pop

1215 858f3d18 Iustin Pop
    This is a single-node call.
1216 858f3d18 Iustin Pop

1217 858f3d18 Iustin Pop
    """
1218 858f3d18 Iustin Pop
    return self._SingleNodeCall(node, "blockdev_export",
1219 858f3d18 Iustin Pop
                                [cf_bdev.ToDict(), dest_node, dest_path,
1220 858f3d18 Iustin Pop
                                 cluster_name])
1221 858f3d18 Iustin Pop
1222 92fd2250 Iustin Pop
  @_RpcTimeout(_TMO_NORMAL)
1223 72737a7f Iustin Pop
  def call_blockdev_snapshot(self, node, cf_bdev):
1224 72737a7f Iustin Pop
    """Request a snapshot of the given block device.
1225 a8083063 Iustin Pop

1226 72737a7f Iustin Pop
    This is a single-node call.
1227 a8083063 Iustin Pop

1228 72737a7f Iustin Pop
    """
1229 9a525d83 Michael Hanselmann
    return self._SingleNodeCall(node, "blockdev_snapshot", [cf_bdev.ToDict()])
1230 a8083063 Iustin Pop
1231 9a525d83 Michael Hanselmann
  @classmethod
1232 92fd2250 Iustin Pop
  @_RpcTimeout(_TMO_NORMAL)
1233 b989b9d9 Ken Wehr
  def call_node_leave_cluster(cls, node, modify_ssh_setup):
1234 72737a7f Iustin Pop
    """Requests a node to clean the cluster information it has.
1235 a8083063 Iustin Pop

1236 72737a7f Iustin Pop
    This will remove the configuration information from the ganeti data
1237 72737a7f Iustin Pop
    dir.
1238 a8083063 Iustin Pop

1239 72737a7f Iustin Pop
    This is a single-node call.
1240 a8083063 Iustin Pop

1241 72737a7f Iustin Pop
    """
1242 b989b9d9 Ken Wehr
    return cls._StaticSingleNodeCall(node, "node_leave_cluster",
1243 b989b9d9 Ken Wehr
                                     [modify_ssh_setup])
1244 dcb93971 Michael Hanselmann
1245 0436da49 Michael Hanselmann
  def call_test_delay(self, node_list, duration, read_timeout=None):
1246 72737a7f Iustin Pop
    """Sleep for a fixed time on given node(s).
1247 06009e27 Iustin Pop

1248 72737a7f Iustin Pop
    This is a multi-node call.
1249 06009e27 Iustin Pop

1250 72737a7f Iustin Pop
    """
1251 0436da49 Michael Hanselmann
    assert read_timeout is None
1252 0436da49 Michael Hanselmann
    return self.call_test_delay(node_list, duration,
1253 0436da49 Michael Hanselmann
                                read_timeout=int(duration + 5))
1254 5e04ed8b Manuel Franceschini
1255 9a525d83 Michael Hanselmann
  @classmethod
1256 d2cd6944 Iustin Pop
  @_RpcTimeout(_TMO_URGENT)
1257 9a525d83 Michael Hanselmann
  def call_jobqueue_update(cls, node_list, address_list, file_name, content):
1258 72737a7f Iustin Pop
    """Update job queue.
1259 ca52cdeb Michael Hanselmann

1260 72737a7f Iustin Pop
    This is a multi-node call.
1261 ca52cdeb Michael Hanselmann

1262 72737a7f Iustin Pop
    """
1263 9a525d83 Michael Hanselmann
    return cls._StaticMultiNodeCall(node_list, "jobqueue_update",
1264 30474135 Michael Hanselmann
                                    [file_name, _Compress(content)],
1265 9a525d83 Michael Hanselmann
                                    address_list=address_list)
1266 ca52cdeb Michael Hanselmann
1267 9a525d83 Michael Hanselmann
  @classmethod
1268 92fd2250 Iustin Pop
  @_RpcTimeout(_TMO_NORMAL)
1269 9a525d83 Michael Hanselmann
  def call_jobqueue_purge(cls, node):
1270 72737a7f Iustin Pop
    """Purge job queue.
1271 ca52cdeb Michael Hanselmann

1272 72737a7f Iustin Pop
    This is a single-node call.
1273 ca52cdeb Michael Hanselmann

1274 72737a7f Iustin Pop
    """
1275 9a525d83 Michael Hanselmann
    return cls._StaticSingleNodeCall(node, "jobqueue_purge", [])
1276 af5ebcb1 Michael Hanselmann
1277 9a525d83 Michael Hanselmann
  @classmethod
1278 d2cd6944 Iustin Pop
  @_RpcTimeout(_TMO_URGENT)
1279 dd875d32 Michael Hanselmann
  def call_jobqueue_rename(cls, node_list, address_list, rename):
1280 72737a7f Iustin Pop
    """Rename a job queue file.
1281 af5ebcb1 Michael Hanselmann

1282 72737a7f Iustin Pop
    This is a multi-node call.
1283 af5ebcb1 Michael Hanselmann

1284 72737a7f Iustin Pop
    """
1285 dd875d32 Michael Hanselmann
    return cls._StaticMultiNodeCall(node_list, "jobqueue_rename", rename,
1286 9a525d83 Michael Hanselmann
                                    address_list=address_list)
1287 6217e295 Iustin Pop
1288 92fd2250 Iustin Pop
  @_RpcTimeout(_TMO_NORMAL)
1289 6217e295 Iustin Pop
  def call_hypervisor_validate_params(self, node_list, hvname, hvparams):
1290 6217e295 Iustin Pop
    """Validate the hypervisor params.
1291 6217e295 Iustin Pop

1292 6217e295 Iustin Pop
    This is a multi-node call.
1293 6217e295 Iustin Pop

1294 6217e295 Iustin Pop
    @type node_list: list
1295 6217e295 Iustin Pop
    @param node_list: the list of nodes to query
1296 6217e295 Iustin Pop
    @type hvname: string
1297 6217e295 Iustin Pop
    @param hvname: the hypervisor name
1298 6217e295 Iustin Pop
    @type hvparams: dict
1299 6217e295 Iustin Pop
    @param hvparams: the hypervisor parameters to be validated
1300 6217e295 Iustin Pop

1301 6217e295 Iustin Pop
    """
1302 6217e295 Iustin Pop
    cluster = self._cfg.GetClusterInfo()
1303 abe609b2 Guido Trotter
    hv_full = objects.FillDict(cluster.hvparams.get(hvname, {}), hvparams)
1304 9a525d83 Michael Hanselmann
    return self._MultiNodeCall(node_list, "hypervisor_validate_params",
1305 9a525d83 Michael Hanselmann
                               [hvname, hv_full])
1306 f942a838 Michael Hanselmann
1307 92fd2250 Iustin Pop
  @_RpcTimeout(_TMO_NORMAL)
1308 6613661a Iustin Pop
  def call_import_start(self, node, opts, instance, component,
1309 6613661a Iustin Pop
                        dest, dest_args):
1310 1651d116 Michael Hanselmann
    """Starts a listener for an import.
1311 1651d116 Michael Hanselmann

1312 1651d116 Michael Hanselmann
    This is a single-node call.
1313 1651d116 Michael Hanselmann

1314 1651d116 Michael Hanselmann
    @type node: string
1315 1651d116 Michael Hanselmann
    @param node: Node name
1316 1651d116 Michael Hanselmann
    @type instance: C{objects.Instance}
1317 1651d116 Michael Hanselmann
    @param instance: Instance object
1318 6613661a Iustin Pop
    @type component: string
1319 6613661a Iustin Pop
    @param component: which part of the instance is being imported
1320 1651d116 Michael Hanselmann

1321 1651d116 Michael Hanselmann
    """
1322 ef40fbfb Michael Hanselmann
    return self._SingleNodeCall(node, "import_start",
1323 eb630f50 Michael Hanselmann
                                [opts.ToDict(),
1324 6613661a Iustin Pop
                                 self._InstDict(instance), component, dest,
1325 1651d116 Michael Hanselmann
                                 _EncodeImportExportIO(dest, dest_args)])
1326 1651d116 Michael Hanselmann
1327 92fd2250 Iustin Pop
  @_RpcTimeout(_TMO_NORMAL)
1328 eb630f50 Michael Hanselmann
  def call_export_start(self, node, opts, host, port,
1329 6613661a Iustin Pop
                        instance, component, source, source_args):
1330 1651d116 Michael Hanselmann
    """Starts an export daemon.
1331 1651d116 Michael Hanselmann

1332 1651d116 Michael Hanselmann
    This is a single-node call.
1333 1651d116 Michael Hanselmann

1334 1651d116 Michael Hanselmann
    @type node: string
1335 1651d116 Michael Hanselmann
    @param node: Node name
1336 1651d116 Michael Hanselmann
    @type instance: C{objects.Instance}
1337 1651d116 Michael Hanselmann
    @param instance: Instance object
1338 6613661a Iustin Pop
    @type component: string
1339 6613661a Iustin Pop
    @param component: which part of the instance is being imported
1340 1651d116 Michael Hanselmann

1341 1651d116 Michael Hanselmann
    """
1342 ef40fbfb Michael Hanselmann
    return self._SingleNodeCall(node, "export_start",
1343 eb630f50 Michael Hanselmann
                                [opts.ToDict(), host, port,
1344 6613661a Iustin Pop
                                 self._InstDict(instance),
1345 6613661a Iustin Pop
                                 component, source,
1346 1651d116 Michael Hanselmann
                                 _EncodeImportExportIO(source, source_args)])