Statistics
| Branch: | Tag: | Revision:

root / lib / rpc.py @ d868edb4

History | View | Annotate | Download (27.1 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 81010134 Iustin Pop
import httplib
36 58b311ca Iustin Pop
import logging
37 a8083063 Iustin Pop
38 81010134 Iustin Pop
import simplejson
39 a8083063 Iustin Pop
40 a8083063 Iustin Pop
from ganeti import utils
41 a8083063 Iustin Pop
from ganeti import objects
42 a8083063 Iustin Pop
43 7c0d6283 Michael Hanselmann
44 a8083063 Iustin Pop
class NodeController:
45 a8083063 Iustin Pop
  """Node-handling class.
46 a8083063 Iustin Pop

47 a8083063 Iustin Pop
  For each node that we speak with, we create an instance of this
48 a8083063 Iustin Pop
  class, so that we have a safe place to store the details of this
49 a8083063 Iustin Pop
  individual call.
50 a8083063 Iustin Pop

51 a8083063 Iustin Pop
  """
52 bdf7d8c0 Iustin Pop
  def __init__(self, parent, node, address=None):
53 bdf7d8c0 Iustin Pop
    """Constructor for the node controller.
54 bdf7d8c0 Iustin Pop

55 bdf7d8c0 Iustin Pop
    @type parent: L{Client}
56 bdf7d8c0 Iustin Pop
    @param parent: the C{Client} instance which holds global parameters for
57 bdf7d8c0 Iustin Pop
        the call
58 bdf7d8c0 Iustin Pop
    @type node: str
59 bdf7d8c0 Iustin Pop
    @param node: the name of the node we connect to; it is used for error
60 bdf7d8c0 Iustin Pop
        messages and in cases we the address paramater is not passed
61 bdf7d8c0 Iustin Pop
    @type address: str
62 bdf7d8c0 Iustin Pop
    @keyword address: the node's address, in case we know it, so that we
63 bdf7d8c0 Iustin Pop
        don't need to resolve it; testing shows that httplib has high
64 bdf7d8c0 Iustin Pop
        overhead in resolving addresses (even when speficied in /etc/hosts)
65 bdf7d8c0 Iustin Pop

66 bdf7d8c0 Iustin Pop
    """
67 a8083063 Iustin Pop
    self.parent = parent
68 a8083063 Iustin Pop
    self.node = node
69 bdf7d8c0 Iustin Pop
    if address is None:
70 bdf7d8c0 Iustin Pop
      address = node
71 81010134 Iustin Pop
    self.failed = False
72 a8083063 Iustin Pop
73 bdf7d8c0 Iustin Pop
    self.http_conn = hc = httplib.HTTPConnection(address, parent.port)
74 a8083063 Iustin Pop
    try:
75 81010134 Iustin Pop
      hc.connect()
76 bdf7d8c0 Iustin Pop
      hc.putrequest('PUT', "/%s" % parent.procedure,
77 81010134 Iustin Pop
                    skip_accept_encoding=True)
78 bdf7d8c0 Iustin Pop
      hc.putheader('Content-Length', parent.body_length)
79 81010134 Iustin Pop
      hc.endheaders()
80 81010134 Iustin Pop
      hc.send(parent.body)
81 bdf7d8c0 Iustin Pop
    except socket.error:
82 58b311ca Iustin Pop
      logging.exception("Error connecting to node %s", node)
83 81010134 Iustin Pop
      self.failed = True
84 81010134 Iustin Pop
85 3ef3c771 Iustin Pop
  def GetResponse(self):
86 81010134 Iustin Pop
    """Try to process the response from the node.
87 a8083063 Iustin Pop

88 a8083063 Iustin Pop
    """
89 81010134 Iustin Pop
    if self.failed:
90 81010134 Iustin Pop
      # we already failed in connect
91 a8083063 Iustin Pop
      return False
92 81010134 Iustin Pop
    resp = self.http_conn.getresponse()
93 81010134 Iustin Pop
    if resp.status != 200:
94 a8083063 Iustin Pop
      return False
95 81010134 Iustin Pop
    try:
96 81010134 Iustin Pop
      length = int(resp.getheader('Content-Length', '0'))
97 81010134 Iustin Pop
    except ValueError:
98 81010134 Iustin Pop
      return False
99 81010134 Iustin Pop
    if not length:
100 58b311ca Iustin Pop
      logging.error("Zero-length reply from node %s", self.node)
101 81010134 Iustin Pop
      return False
102 81010134 Iustin Pop
    payload = resp.read(length)
103 81010134 Iustin Pop
    unload = simplejson.loads(payload)
104 81010134 Iustin Pop
    return unload
105 a8083063 Iustin Pop
106 a8083063 Iustin Pop
107 a8083063 Iustin Pop
class Client:
108 a8083063 Iustin Pop
  """RPC Client class.
109 a8083063 Iustin Pop

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

114 a8083063 Iustin Pop
  One current bug is that generic failure is still signalled by
115 a8083063 Iustin Pop
  'False' result, which is not good. This overloading of values can
116 a8083063 Iustin Pop
  cause bugs.
117 a8083063 Iustin Pop

118 bdf7d8c0 Iustin Pop
  @var body_length: cached string value of the length of the body (so that
119 bdf7d8c0 Iustin Pop
      individual C{NodeController} instances don't have to recompute it)
120 bdf7d8c0 Iustin Pop

121 a8083063 Iustin Pop
  """
122 a8083063 Iustin Pop
  result_set = False
123 a8083063 Iustin Pop
  result = False
124 a8083063 Iustin Pop
  allresult = []
125 a8083063 Iustin Pop
126 a8083063 Iustin Pop
  def __init__(self, procedure, args):
127 eb1328a9 Michael Hanselmann
    self.port = utils.GetNodeDaemonPort()
128 eb1328a9 Michael Hanselmann
    self.nodepw = utils.GetNodeDaemonPassword()
129 a8083063 Iustin Pop
    self.nc = {}
130 a8083063 Iustin Pop
    self.results = {}
131 a8083063 Iustin Pop
    self.procedure = procedure
132 a8083063 Iustin Pop
    self.args = args
133 81010134 Iustin Pop
    self.body = simplejson.dumps(args)
134 bdf7d8c0 Iustin Pop
    self.body_length = str(len(self.body))
135 a8083063 Iustin Pop
136 a8083063 Iustin Pop
  #--- generic connector -------------
137 a8083063 Iustin Pop
138 bdf7d8c0 Iustin Pop
  def ConnectList(self, node_list, address_list=None):
139 a8083063 Iustin Pop
    """Add a list of nodes to the target nodes.
140 a8083063 Iustin Pop

141 3ef3c771 Iustin Pop
    @type node_list: list
142 3ef3c771 Iustin Pop
    @param node_list: the list of node names to connect
143 bdf7d8c0 Iustin Pop
    @type address_list: list or None
144 bdf7d8c0 Iustin Pop
    @keyword address_list: either None or a list with node addresses,
145 bdf7d8c0 Iustin Pop
        which must have the same length as the node list
146 3ef3c771 Iustin Pop

147 a8083063 Iustin Pop
    """
148 bdf7d8c0 Iustin Pop
    if address_list is None:
149 bdf7d8c0 Iustin Pop
      address_list = [None for _ in node_list]
150 bdf7d8c0 Iustin Pop
    else:
151 bdf7d8c0 Iustin Pop
      assert len(node_list) == len(address_list), \
152 bdf7d8c0 Iustin Pop
             "Name and address lists should have the same length"
153 bdf7d8c0 Iustin Pop
    for node, address in zip(node_list, address_list):
154 bdf7d8c0 Iustin Pop
      self.ConnectNode(node, address)
155 bdf7d8c0 Iustin Pop
156 bdf7d8c0 Iustin Pop
  def ConnectNode(self, name, address=None):
157 a8083063 Iustin Pop
    """Add a node to the target list.
158 a8083063 Iustin Pop

159 bdf7d8c0 Iustin Pop
    @type name: str
160 bdf7d8c0 Iustin Pop
    @param name: the node name
161 bdf7d8c0 Iustin Pop
    @type address: str
162 bdf7d8c0 Iustin Pop
    @keyword address: the node address, if known
163 bdf7d8c0 Iustin Pop

164 a8083063 Iustin Pop
    """
165 bdf7d8c0 Iustin Pop
    self.nc[name] = NodeController(self, name, address)
166 a8083063 Iustin Pop
167 3ef3c771 Iustin Pop
  def GetResults(self):
168 a8083063 Iustin Pop
    """Return the results of the call.
169 a8083063 Iustin Pop

170 a8083063 Iustin Pop
    """
171 a8083063 Iustin Pop
    return self.results
172 a8083063 Iustin Pop
173 3ef3c771 Iustin Pop
  def Run(self):
174 3ef3c771 Iustin Pop
    """Gather results from the node controllers.
175 a8083063 Iustin Pop

176 3ef3c771 Iustin Pop
    This function simply calls GetResponse() for each of our node
177 3ef3c771 Iustin Pop
    controllers.
178 a8083063 Iustin Pop

179 a8083063 Iustin Pop
    """
180 81010134 Iustin Pop
    for node, nc in self.nc.items():
181 3ef3c771 Iustin Pop
      self.results[node] = nc.GetResponse()
182 a8083063 Iustin Pop
183 a8083063 Iustin Pop
184 72737a7f Iustin Pop
class RpcRunner(object):
185 72737a7f Iustin Pop
  """RPC runner class"""
186 a8083063 Iustin Pop
187 72737a7f Iustin Pop
  def __init__(self, cfg):
188 72737a7f Iustin Pop
    """Initialized the rpc runner.
189 a8083063 Iustin Pop

190 72737a7f Iustin Pop
    @type cfg:  C{config.ConfigWriter}
191 72737a7f Iustin Pop
    @param cfg: the configuration object that will be used to get data
192 72737a7f Iustin Pop
                about the cluster
193 a8083063 Iustin Pop

194 72737a7f Iustin Pop
    """
195 72737a7f Iustin Pop
    self._cfg = cfg
196 a8083063 Iustin Pop
197 26ba2bd8 Iustin Pop
  def _InstDict(self, instance):
198 26ba2bd8 Iustin Pop
    """Convert the given instance to a dict.
199 26ba2bd8 Iustin Pop

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

203 26ba2bd8 Iustin Pop
    @type instance: L{objects.Instance}
204 26ba2bd8 Iustin Pop
    @param instance: an Instance object
205 26ba2bd8 Iustin Pop
    @rtype: dict
206 26ba2bd8 Iustin Pop
    @return: the instance dict, with the hvparams filled with the
207 26ba2bd8 Iustin Pop
        cluster defaults
208 26ba2bd8 Iustin Pop

209 26ba2bd8 Iustin Pop
    """
210 26ba2bd8 Iustin Pop
    idict = instance.ToDict()
211 5b442704 Iustin Pop
    cluster = self._cfg.GetClusterInfo()
212 5b442704 Iustin Pop
    idict["hvparams"] = cluster.FillHV(instance)
213 5b442704 Iustin Pop
    idict["beparams"] = cluster.FillBE(instance)
214 26ba2bd8 Iustin Pop
    return idict
215 26ba2bd8 Iustin Pop
216 25348212 Iustin Pop
  def _ConnectList(self, client, node_list):
217 25348212 Iustin Pop
    """Helper for computing node addresses.
218 25348212 Iustin Pop

219 25348212 Iustin Pop
    @type client: L{Client}
220 25348212 Iustin Pop
    @param client: a C{Client} instance
221 25348212 Iustin Pop
    @type node_list: list
222 25348212 Iustin Pop
    @param node_list: the node list we should connect
223 25348212 Iustin Pop

224 25348212 Iustin Pop
    """
225 25348212 Iustin Pop
    all_nodes = self._cfg.GetAllNodesInfo()
226 25348212 Iustin Pop
    addr_list = []
227 25348212 Iustin Pop
    for node in node_list:
228 25348212 Iustin Pop
      if node in all_nodes:
229 25348212 Iustin Pop
        val = all_nodes[node].primary_ip
230 25348212 Iustin Pop
      else:
231 25348212 Iustin Pop
        val = None
232 25348212 Iustin Pop
      addr_list.append(val)
233 25348212 Iustin Pop
    client.ConnectList(node_list, address_list=addr_list)
234 25348212 Iustin Pop
235 25348212 Iustin Pop
  def _ConnectNode(self, client, node):
236 25348212 Iustin Pop
    """Helper for computing one node's address.
237 25348212 Iustin Pop

238 25348212 Iustin Pop
    @type client: L{Client}
239 25348212 Iustin Pop
    @param client: a C{Client} instance
240 25348212 Iustin Pop
    @type node: str
241 25348212 Iustin Pop
    @param node: the node we should connect
242 25348212 Iustin Pop

243 25348212 Iustin Pop
    """
244 25348212 Iustin Pop
    node_info = self._cfg.GetNodeInfo(node)
245 25348212 Iustin Pop
    if node_info is not None:
246 25348212 Iustin Pop
      addr = node_info.primary_ip
247 25348212 Iustin Pop
    else:
248 25348212 Iustin Pop
      addr = None
249 25348212 Iustin Pop
    client.ConnectNode(node, address=addr)
250 25348212 Iustin Pop
251 72737a7f Iustin Pop
  def call_volume_list(self, node_list, vg_name):
252 72737a7f Iustin Pop
    """Gets the logical volumes present in a given volume group.
253 a8083063 Iustin Pop

254 72737a7f Iustin Pop
    This is a multi-node call.
255 a8083063 Iustin Pop

256 72737a7f Iustin Pop
    """
257 72737a7f Iustin Pop
    c = Client("volume_list", [vg_name])
258 25348212 Iustin Pop
    self._ConnectList(c, node_list)
259 3ef3c771 Iustin Pop
    c.Run()
260 3ef3c771 Iustin Pop
    return c.GetResults()
261 a8083063 Iustin Pop
262 72737a7f Iustin Pop
  def call_vg_list(self, node_list):
263 72737a7f Iustin Pop
    """Gets the volume group list.
264 a8083063 Iustin Pop

265 72737a7f Iustin Pop
    This is a multi-node call.
266 a8083063 Iustin Pop

267 72737a7f Iustin Pop
    """
268 72737a7f Iustin Pop
    c = Client("vg_list", [])
269 25348212 Iustin Pop
    self._ConnectList(c, node_list)
270 3ef3c771 Iustin Pop
    c.Run()
271 3ef3c771 Iustin Pop
    return c.GetResults()
272 a8083063 Iustin Pop
273 72737a7f Iustin Pop
  def call_bridges_exist(self, node, bridges_list):
274 72737a7f Iustin Pop
    """Checks if a node has all the bridges given.
275 a8083063 Iustin Pop

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

280 72737a7f Iustin Pop
    This is a single-node call.
281 a8083063 Iustin Pop

282 72737a7f Iustin Pop
    """
283 72737a7f Iustin Pop
    c = Client("bridges_exist", [bridges_list])
284 25348212 Iustin Pop
    self._ConnectNode(c, node)
285 3ef3c771 Iustin Pop
    c.Run()
286 3ef3c771 Iustin Pop
    return c.GetResults().get(node, False)
287 a8083063 Iustin Pop
288 72737a7f Iustin Pop
  def call_instance_start(self, node, instance, extra_args):
289 72737a7f Iustin Pop
    """Starts an instance.
290 a8083063 Iustin Pop

291 72737a7f Iustin Pop
    This is a single-node call.
292 a8083063 Iustin Pop

293 72737a7f Iustin Pop
    """
294 26ba2bd8 Iustin Pop
    c = Client("instance_start", [self._InstDict(instance), extra_args])
295 25348212 Iustin Pop
    self._ConnectNode(c, node)
296 3ef3c771 Iustin Pop
    c.Run()
297 3ef3c771 Iustin Pop
    return c.GetResults().get(node, False)
298 a8083063 Iustin Pop
299 72737a7f Iustin Pop
  def call_instance_shutdown(self, node, instance):
300 72737a7f Iustin Pop
    """Stops an instance.
301 a8083063 Iustin Pop

302 72737a7f Iustin Pop
    This is a single-node call.
303 2a10865c Iustin Pop

304 72737a7f Iustin Pop
    """
305 26ba2bd8 Iustin Pop
    c = Client("instance_shutdown", [self._InstDict(instance)])
306 25348212 Iustin Pop
    self._ConnectNode(c, node)
307 3ef3c771 Iustin Pop
    c.Run()
308 3ef3c771 Iustin Pop
    return c.GetResults().get(node, False)
309 2a10865c Iustin Pop
310 72737a7f Iustin Pop
  def call_instance_migrate(self, node, instance, target, live):
311 72737a7f Iustin Pop
    """Migrate an instance.
312 2a10865c Iustin Pop

313 72737a7f Iustin Pop
    This is a single-node call.
314 2a10865c Iustin Pop

315 72737a7f Iustin Pop
    @type node: string
316 72737a7f Iustin Pop
    @param node: the node on which the instance is currently running
317 72737a7f Iustin Pop
    @type instance: C{objects.Instance}
318 72737a7f Iustin Pop
    @param instance: the instance definition
319 72737a7f Iustin Pop
    @type target: string
320 72737a7f Iustin Pop
    @param target: the target node name
321 72737a7f Iustin Pop
    @type live: boolean
322 72737a7f Iustin Pop
    @param live: whether the migration should be done live or not (the
323 72737a7f Iustin Pop
        interpretation of this parameter is left to the hypervisor)
324 007a2f3e Alexander Schreiber

325 72737a7f Iustin Pop
    """
326 26ba2bd8 Iustin Pop
    c = Client("instance_migrate", [self._InstDict(instance), target, live])
327 25348212 Iustin Pop
    self._ConnectNode(c, node)
328 3ef3c771 Iustin Pop
    c.Run()
329 3ef3c771 Iustin Pop
    return c.GetResults().get(node, False)
330 007a2f3e Alexander Schreiber
331 72737a7f Iustin Pop
  def call_instance_reboot(self, node, instance, reboot_type, extra_args):
332 72737a7f Iustin Pop
    """Reboots an instance.
333 007a2f3e Alexander Schreiber

334 72737a7f Iustin Pop
    This is a single-node call.
335 a8083063 Iustin Pop

336 72737a7f Iustin Pop
    """
337 26ba2bd8 Iustin Pop
    c = Client("instance_reboot", [self._InstDict(instance),
338 26ba2bd8 Iustin Pop
                                   reboot_type, extra_args])
339 25348212 Iustin Pop
    self._ConnectNode(c, node)
340 3ef3c771 Iustin Pop
    c.Run()
341 3ef3c771 Iustin Pop
    return c.GetResults().get(node, False)
342 a8083063 Iustin Pop
343 d15a9ad3 Guido Trotter
  def call_instance_os_add(self, node, inst):
344 72737a7f Iustin Pop
    """Installs an OS on the given instance.
345 a8083063 Iustin Pop

346 72737a7f Iustin Pop
    This is a single-node call.
347 decd5f45 Iustin Pop

348 72737a7f Iustin Pop
    """
349 d15a9ad3 Guido Trotter
    params = [self._InstDict(inst)]
350 72737a7f Iustin Pop
    c = Client("instance_os_add", params)
351 25348212 Iustin Pop
    self._ConnectNode(c, node)
352 3ef3c771 Iustin Pop
    c.Run()
353 3ef3c771 Iustin Pop
    return c.GetResults().get(node, False)
354 decd5f45 Iustin Pop
355 d15a9ad3 Guido Trotter
  def call_instance_run_rename(self, node, inst, old_name):
356 72737a7f Iustin Pop
    """Run the OS rename script for an instance.
357 decd5f45 Iustin Pop

358 72737a7f Iustin Pop
    This is a single-node call.
359 a8083063 Iustin Pop

360 72737a7f Iustin Pop
    """
361 d15a9ad3 Guido Trotter
    params = [self._InstDict(inst), old_name]
362 72737a7f Iustin Pop
    c = Client("instance_run_rename", params)
363 25348212 Iustin Pop
    self._ConnectNode(c, node)
364 3ef3c771 Iustin Pop
    c.Run()
365 3ef3c771 Iustin Pop
    return c.GetResults().get(node, False)
366 a8083063 Iustin Pop
367 72737a7f Iustin Pop
  def call_instance_info(self, node, instance, hname):
368 72737a7f Iustin Pop
    """Returns information about a single instance.
369 a8083063 Iustin Pop

370 72737a7f Iustin Pop
    This is a single-node call.
371 a8083063 Iustin Pop

372 72737a7f Iustin Pop
    @type node_list: list
373 72737a7f Iustin Pop
    @param node_list: the list of nodes to query
374 72737a7f Iustin Pop
    @type instance: string
375 72737a7f Iustin Pop
    @param instance: the instance name
376 72737a7f Iustin Pop
    @type hname: string
377 72737a7f Iustin Pop
    @param hname: the hypervisor type of the instance
378 a8083063 Iustin Pop

379 72737a7f Iustin Pop
    """
380 16ad1a83 Iustin Pop
    c = Client("instance_info", [instance, hname])
381 25348212 Iustin Pop
    self._ConnectNode(c, node)
382 3ef3c771 Iustin Pop
    c.Run()
383 3ef3c771 Iustin Pop
    return c.GetResults().get(node, False)
384 e69d05fd Iustin Pop
385 72737a7f Iustin Pop
  def call_all_instances_info(self, node_list, hypervisor_list):
386 72737a7f Iustin Pop
    """Returns information about all instances on the given nodes.
387 a8083063 Iustin Pop

388 72737a7f Iustin Pop
    This is a multi-node call.
389 a8083063 Iustin Pop

390 72737a7f Iustin Pop
    @type node_list: list
391 72737a7f Iustin Pop
    @param node_list: the list of nodes to query
392 72737a7f Iustin Pop
    @type hypervisor_list: list
393 72737a7f Iustin Pop
    @param hypervisor_list: the hypervisors to query for instances
394 a8083063 Iustin Pop

395 72737a7f Iustin Pop
    """
396 72737a7f Iustin Pop
    c = Client("all_instances_info", [hypervisor_list])
397 25348212 Iustin Pop
    self._ConnectList(c, node_list)
398 3ef3c771 Iustin Pop
    c.Run()
399 3ef3c771 Iustin Pop
    return c.GetResults()
400 e69d05fd Iustin Pop
401 72737a7f Iustin Pop
  def call_instance_list(self, node_list, hypervisor_list):
402 72737a7f Iustin Pop
    """Returns the list of running instances on a given node.
403 a8083063 Iustin Pop

404 72737a7f Iustin Pop
    This is a multi-node call.
405 a8083063 Iustin Pop

406 72737a7f Iustin Pop
    @type node_list: list
407 72737a7f Iustin Pop
    @param node_list: the list of nodes to query
408 72737a7f Iustin Pop
    @type hypervisor_list: list
409 72737a7f Iustin Pop
    @param hypervisor_list: the hypervisors to query for instances
410 16abfbc2 Alexander Schreiber

411 72737a7f Iustin Pop
    """
412 72737a7f Iustin Pop
    c = Client("instance_list", [hypervisor_list])
413 25348212 Iustin Pop
    self._ConnectList(c, node_list)
414 3ef3c771 Iustin Pop
    c.Run()
415 3ef3c771 Iustin Pop
    return c.GetResults()
416 16abfbc2 Alexander Schreiber
417 72737a7f Iustin Pop
  def call_node_tcp_ping(self, node, source, target, port, timeout,
418 72737a7f Iustin Pop
                         live_port_needed):
419 72737a7f Iustin Pop
    """Do a TcpPing on the remote node
420 a8083063 Iustin Pop

421 72737a7f Iustin Pop
    This is a single-node call.
422 caad16e2 Iustin Pop

423 72737a7f Iustin Pop
    """
424 72737a7f Iustin Pop
    c = Client("node_tcp_ping", [source, target, port, timeout,
425 72737a7f Iustin Pop
                                 live_port_needed])
426 25348212 Iustin Pop
    self._ConnectNode(c, node)
427 3ef3c771 Iustin Pop
    c.Run()
428 3ef3c771 Iustin Pop
    return c.GetResults().get(node, False)
429 a8083063 Iustin Pop
430 caad16e2 Iustin Pop
  def call_node_has_ip_address(self, node, address):
431 caad16e2 Iustin Pop
    """Checks if a node has the given IP address.
432 caad16e2 Iustin Pop

433 caad16e2 Iustin Pop
    This is a single-node call.
434 caad16e2 Iustin Pop

435 caad16e2 Iustin Pop
    """
436 caad16e2 Iustin Pop
    c = Client("node_has_ip_address", [address])
437 25348212 Iustin Pop
    self._ConnectNode(c, node)
438 3ef3c771 Iustin Pop
    c.Run()
439 3ef3c771 Iustin Pop
    return c.GetResults().get(node, False)
440 a8083063 Iustin Pop
441 72737a7f Iustin Pop
  def call_node_info(self, node_list, vg_name, hypervisor_type):
442 72737a7f Iustin Pop
    """Return node information.
443 e69d05fd Iustin Pop

444 72737a7f Iustin Pop
    This will return memory information and volume group size and free
445 72737a7f Iustin Pop
    space.
446 a8083063 Iustin Pop

447 72737a7f Iustin Pop
    This is a multi-node call.
448 a8083063 Iustin Pop

449 72737a7f Iustin Pop
    @type node_list: list
450 72737a7f Iustin Pop
    @param node_list: the list of nodes to query
451 72737a7f Iustin Pop
    @type vgname: C{string}
452 72737a7f Iustin Pop
    @param vgname: the name of the volume group to ask for disk space
453 72737a7f Iustin Pop
        information
454 72737a7f Iustin Pop
    @type hypervisor_type: C{str}
455 72737a7f Iustin Pop
    @param hypervisor_type: the name of the hypervisor to ask for
456 72737a7f Iustin Pop
        memory information
457 a8083063 Iustin Pop

458 72737a7f Iustin Pop
    """
459 72737a7f Iustin Pop
    c = Client("node_info", [vg_name, hypervisor_type])
460 25348212 Iustin Pop
    self._ConnectList(c, node_list)
461 3ef3c771 Iustin Pop
    c.Run()
462 3ef3c771 Iustin Pop
    retux = c.GetResults()
463 a8083063 Iustin Pop
464 72737a7f Iustin Pop
    for node_name in retux:
465 72737a7f Iustin Pop
      ret = retux.get(node_name, False)
466 72737a7f Iustin Pop
      if type(ret) != dict:
467 58b311ca Iustin Pop
        logging.error("could not connect to node %s", node_name)
468 72737a7f Iustin Pop
        ret = {}
469 a8083063 Iustin Pop
470 72737a7f Iustin Pop
      utils.CheckDict(ret,
471 72737a7f Iustin Pop
                      { 'memory_total' : '-',
472 72737a7f Iustin Pop
                        'memory_dom0' : '-',
473 72737a7f Iustin Pop
                        'memory_free' : '-',
474 72737a7f Iustin Pop
                        'vg_size' : 'node_unreachable',
475 72737a7f Iustin Pop
                        'vg_free' : '-' },
476 72737a7f Iustin Pop
                      "call_node_info",
477 72737a7f Iustin Pop
                      )
478 72737a7f Iustin Pop
    return retux
479 a8083063 Iustin Pop
480 72737a7f Iustin Pop
  def call_node_add(self, node, dsa, dsapub, rsa, rsapub, ssh, sshpub):
481 72737a7f Iustin Pop
    """Add a node to the cluster.
482 a8083063 Iustin Pop

483 72737a7f Iustin Pop
    This is a single-node call.
484 a8083063 Iustin Pop

485 72737a7f Iustin Pop
    """
486 72737a7f Iustin Pop
    params = [dsa, dsapub, rsa, rsapub, ssh, sshpub]
487 72737a7f Iustin Pop
    c = Client("node_add", params)
488 25348212 Iustin Pop
    self._ConnectNode(c, node)
489 3ef3c771 Iustin Pop
    c.Run()
490 3ef3c771 Iustin Pop
    return c.GetResults().get(node, False)
491 a8083063 Iustin Pop
492 72737a7f Iustin Pop
  def call_node_verify(self, node_list, checkdict, cluster_name):
493 72737a7f Iustin Pop
    """Request verification of given parameters.
494 a8083063 Iustin Pop

495 72737a7f Iustin Pop
    This is a multi-node call.
496 a8083063 Iustin Pop

497 72737a7f Iustin Pop
    """
498 72737a7f Iustin Pop
    c = Client("node_verify", [checkdict, cluster_name])
499 25348212 Iustin Pop
    self._ConnectList(c, node_list)
500 3ef3c771 Iustin Pop
    c.Run()
501 3ef3c771 Iustin Pop
    return c.GetResults()
502 a8083063 Iustin Pop
503 72737a7f Iustin Pop
  @staticmethod
504 72737a7f Iustin Pop
  def call_node_start_master(node, start_daemons):
505 72737a7f Iustin Pop
    """Tells a node to activate itself as a master.
506 a8083063 Iustin Pop

507 72737a7f Iustin Pop
    This is a single-node call.
508 a8083063 Iustin Pop

509 72737a7f Iustin Pop
    """
510 72737a7f Iustin Pop
    c = Client("node_start_master", [start_daemons])
511 3ef3c771 Iustin Pop
    c.ConnectNode(node)
512 3ef3c771 Iustin Pop
    c.Run()
513 3ef3c771 Iustin Pop
    return c.GetResults().get(node, False)
514 a8083063 Iustin Pop
515 72737a7f Iustin Pop
  @staticmethod
516 72737a7f Iustin Pop
  def call_node_stop_master(node, stop_daemons):
517 72737a7f Iustin Pop
    """Tells a node to demote itself from master status.
518 a8083063 Iustin Pop

519 72737a7f Iustin Pop
    This is a single-node call.
520 4e071d3b Iustin Pop

521 72737a7f Iustin Pop
    """
522 72737a7f Iustin Pop
    c = Client("node_stop_master", [stop_daemons])
523 3ef3c771 Iustin Pop
    c.ConnectNode(node)
524 3ef3c771 Iustin Pop
    c.Run()
525 3ef3c771 Iustin Pop
    return c.GetResults().get(node, False)
526 4e071d3b Iustin Pop
527 72737a7f Iustin Pop
  @staticmethod
528 72737a7f Iustin Pop
  def call_master_info(node_list):
529 72737a7f Iustin Pop
    """Query master info.
530 4e071d3b Iustin Pop

531 72737a7f Iustin Pop
    This is a multi-node call.
532 a8083063 Iustin Pop

533 72737a7f Iustin Pop
    """
534 72737a7f Iustin Pop
    # TODO: should this method query down nodes?
535 72737a7f Iustin Pop
    c = Client("master_info", [])
536 3ef3c771 Iustin Pop
    c.ConnectList(node_list)
537 3ef3c771 Iustin Pop
    c.Run()
538 3ef3c771 Iustin Pop
    return c.GetResults()
539 a8083063 Iustin Pop
540 72737a7f Iustin Pop
  def call_version(self, node_list):
541 72737a7f Iustin Pop
    """Query node version.
542 a8083063 Iustin Pop

543 72737a7f Iustin Pop
    This is a multi-node call.
544 a8083063 Iustin Pop

545 72737a7f Iustin Pop
    """
546 72737a7f Iustin Pop
    c = Client("version", [])
547 25348212 Iustin Pop
    self._ConnectList(c, node_list)
548 3ef3c771 Iustin Pop
    c.Run()
549 3ef3c771 Iustin Pop
    return c.GetResults()
550 a8083063 Iustin Pop
551 72737a7f Iustin Pop
  def call_blockdev_create(self, node, bdev, size, owner, on_primary, info):
552 72737a7f Iustin Pop
    """Request creation of a given block device.
553 a8083063 Iustin Pop

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

556 72737a7f Iustin Pop
    """
557 72737a7f Iustin Pop
    params = [bdev.ToDict(), size, owner, on_primary, info]
558 72737a7f Iustin Pop
    c = Client("blockdev_create", params)
559 25348212 Iustin Pop
    self._ConnectNode(c, node)
560 3ef3c771 Iustin Pop
    c.Run()
561 3ef3c771 Iustin Pop
    return c.GetResults().get(node, False)
562 a8083063 Iustin Pop
563 72737a7f Iustin Pop
  def call_blockdev_remove(self, node, bdev):
564 72737a7f Iustin Pop
    """Request removal of a given block device.
565 a8083063 Iustin Pop

566 72737a7f Iustin Pop
    This is a single-node call.
567 f3e513ad Iustin Pop

568 72737a7f Iustin Pop
    """
569 72737a7f Iustin Pop
    c = Client("blockdev_remove", [bdev.ToDict()])
570 25348212 Iustin Pop
    self._ConnectNode(c, node)
571 3ef3c771 Iustin Pop
    c.Run()
572 3ef3c771 Iustin Pop
    return c.GetResults().get(node, False)
573 f3e513ad Iustin Pop
574 72737a7f Iustin Pop
  def call_blockdev_rename(self, node, devlist):
575 72737a7f Iustin Pop
    """Request rename of the given block devices.
576 f3e513ad Iustin Pop

577 72737a7f Iustin Pop
    This is a single-node call.
578 a8083063 Iustin Pop

579 72737a7f Iustin Pop
    """
580 72737a7f Iustin Pop
    params = [(d.ToDict(), uid) for d, uid in devlist]
581 72737a7f Iustin Pop
    c = Client("blockdev_rename", params)
582 25348212 Iustin Pop
    self._ConnectNode(c, node)
583 3ef3c771 Iustin Pop
    c.Run()
584 3ef3c771 Iustin Pop
    return c.GetResults().get(node, False)
585 a8083063 Iustin Pop
586 72737a7f Iustin Pop
  def call_blockdev_assemble(self, node, disk, owner, on_primary):
587 72737a7f Iustin Pop
    """Request assembling of a given block device.
588 a8083063 Iustin Pop

589 72737a7f Iustin Pop
    This is a single-node call.
590 a8083063 Iustin Pop

591 72737a7f Iustin Pop
    """
592 72737a7f Iustin Pop
    params = [disk.ToDict(), owner, on_primary]
593 72737a7f Iustin Pop
    c = Client("blockdev_assemble", params)
594 25348212 Iustin Pop
    self._ConnectNode(c, node)
595 3ef3c771 Iustin Pop
    c.Run()
596 3ef3c771 Iustin Pop
    return c.GetResults().get(node, False)
597 a8083063 Iustin Pop
598 72737a7f Iustin Pop
  def call_blockdev_shutdown(self, node, disk):
599 72737a7f Iustin Pop
    """Request shutdown of a given block device.
600 a8083063 Iustin Pop

601 72737a7f Iustin Pop
    This is a single-node call.
602 a8083063 Iustin Pop

603 72737a7f Iustin Pop
    """
604 72737a7f Iustin Pop
    c = Client("blockdev_shutdown", [disk.ToDict()])
605 25348212 Iustin Pop
    self._ConnectNode(c, node)
606 3ef3c771 Iustin Pop
    c.Run()
607 3ef3c771 Iustin Pop
    return c.GetResults().get(node, False)
608 a8083063 Iustin Pop
609 72737a7f Iustin Pop
  def call_blockdev_addchildren(self, node, bdev, ndevs):
610 72737a7f Iustin Pop
    """Request adding a list of children to a (mirroring) device.
611 a8083063 Iustin Pop

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

614 72737a7f Iustin Pop
    """
615 72737a7f Iustin Pop
    params = [bdev.ToDict(), [disk.ToDict() for disk in ndevs]]
616 72737a7f Iustin Pop
    c = Client("blockdev_addchildren", params)
617 25348212 Iustin Pop
    self._ConnectNode(c, node)
618 3ef3c771 Iustin Pop
    c.Run()
619 3ef3c771 Iustin Pop
    return c.GetResults().get(node, False)
620 a8083063 Iustin Pop
621 72737a7f Iustin Pop
  def call_blockdev_removechildren(self, node, bdev, ndevs):
622 72737a7f Iustin Pop
    """Request removing a list of children from a (mirroring) device.
623 a8083063 Iustin Pop

624 72737a7f Iustin Pop
    This is a single-node call.
625 a8083063 Iustin Pop

626 72737a7f Iustin Pop
    """
627 72737a7f Iustin Pop
    params = [bdev.ToDict(), [disk.ToDict() for disk in ndevs]]
628 72737a7f Iustin Pop
    c = Client("blockdev_removechildren", params)
629 25348212 Iustin Pop
    self._ConnectNode(c, node)
630 3ef3c771 Iustin Pop
    c.Run()
631 3ef3c771 Iustin Pop
    return c.GetResults().get(node, False)
632 a8083063 Iustin Pop
633 72737a7f Iustin Pop
  def call_blockdev_getmirrorstatus(self, node, disks):
634 72737a7f Iustin Pop
    """Request status of a (mirroring) device.
635 a8083063 Iustin Pop

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

638 72737a7f Iustin Pop
    """
639 72737a7f Iustin Pop
    params = [dsk.ToDict() for dsk in disks]
640 72737a7f Iustin Pop
    c = Client("blockdev_getmirrorstatus", params)
641 25348212 Iustin Pop
    self._ConnectNode(c, node)
642 3ef3c771 Iustin Pop
    c.Run()
643 3ef3c771 Iustin Pop
    return c.GetResults().get(node, False)
644 a8083063 Iustin Pop
645 72737a7f Iustin Pop
  def call_blockdev_find(self, node, disk):
646 72737a7f Iustin Pop
    """Request identification of a given block device.
647 72737a7f Iustin Pop

648 72737a7f Iustin Pop
    This is a single-node call.
649 a8083063 Iustin Pop

650 72737a7f Iustin Pop
    """
651 72737a7f Iustin Pop
    c = Client("blockdev_find", [disk.ToDict()])
652 25348212 Iustin Pop
    self._ConnectNode(c, node)
653 3ef3c771 Iustin Pop
    c.Run()
654 3ef3c771 Iustin Pop
    return c.GetResults().get(node, False)
655 d61cbe76 Iustin Pop
656 72737a7f Iustin Pop
  def call_blockdev_close(self, node, disks):
657 72737a7f Iustin Pop
    """Closes the given block devices.
658 d61cbe76 Iustin Pop

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

661 72737a7f Iustin Pop
    """
662 72737a7f Iustin Pop
    params = [cf.ToDict() for cf in disks]
663 72737a7f Iustin Pop
    c = Client("blockdev_close", params)
664 25348212 Iustin Pop
    self._ConnectNode(c, node)
665 3ef3c771 Iustin Pop
    c.Run()
666 3ef3c771 Iustin Pop
    return c.GetResults().get(node, False)
667 a8083063 Iustin Pop
668 72737a7f Iustin Pop
  @staticmethod
669 6b294c53 Iustin Pop
  def call_upload_file(node_list, file_name, address_list=None):
670 72737a7f Iustin Pop
    """Upload a file.
671 72737a7f Iustin Pop

672 72737a7f Iustin Pop
    The node will refuse the operation in case the file is not on the
673 72737a7f Iustin Pop
    approved file list.
674 72737a7f Iustin Pop

675 72737a7f Iustin Pop
    This is a multi-node call.
676 a8083063 Iustin Pop

677 6b294c53 Iustin Pop
    @type node_list: list
678 6b294c53 Iustin Pop
    @param node_list: the list of node names to upload to
679 6b294c53 Iustin Pop
    @type file_name: str
680 6b294c53 Iustin Pop
    @param file_name: the filename to upload
681 6b294c53 Iustin Pop
    @type address_list: list or None
682 6b294c53 Iustin Pop
    @keyword address_list: an optional list of node addresses, in order
683 6b294c53 Iustin Pop
        to optimize the RPC speed
684 6b294c53 Iustin Pop

685 72737a7f Iustin Pop
    """
686 72737a7f Iustin Pop
    fh = file(file_name)
687 72737a7f Iustin Pop
    try:
688 72737a7f Iustin Pop
      data = fh.read()
689 72737a7f Iustin Pop
    finally:
690 72737a7f Iustin Pop
      fh.close()
691 72737a7f Iustin Pop
    st = os.stat(file_name)
692 72737a7f Iustin Pop
    params = [file_name, data, st.st_mode, st.st_uid, st.st_gid,
693 72737a7f Iustin Pop
              st.st_atime, st.st_mtime]
694 72737a7f Iustin Pop
    c = Client("upload_file", params)
695 6b294c53 Iustin Pop
    c.ConnectList(node_list, address_list=address_list)
696 3ef3c771 Iustin Pop
    c.Run()
697 3ef3c771 Iustin Pop
    return c.GetResults()
698 72737a7f Iustin Pop
699 72737a7f Iustin Pop
  def call_os_diagnose(self, node_list):
700 72737a7f Iustin Pop
    """Request a diagnose of OS definitions.
701 72737a7f Iustin Pop

702 72737a7f Iustin Pop
    This is a multi-node call.
703 a8083063 Iustin Pop

704 72737a7f Iustin Pop
    """
705 72737a7f Iustin Pop
    c = Client("os_diagnose", [])
706 25348212 Iustin Pop
    self._ConnectList(c, node_list)
707 3ef3c771 Iustin Pop
    c.Run()
708 3ef3c771 Iustin Pop
    result = c.GetResults()
709 72737a7f Iustin Pop
    new_result = {}
710 72737a7f Iustin Pop
    for node_name in result:
711 72737a7f Iustin Pop
      if result[node_name]:
712 72737a7f Iustin Pop
        nr = [objects.OS.FromDict(oss) for oss in result[node_name]]
713 72737a7f Iustin Pop
      else:
714 72737a7f Iustin Pop
        nr = []
715 72737a7f Iustin Pop
      new_result[node_name] = nr
716 72737a7f Iustin Pop
    return new_result
717 a8083063 Iustin Pop
718 72737a7f Iustin Pop
  def call_os_get(self, node, name):
719 72737a7f Iustin Pop
    """Returns an OS definition.
720 a8083063 Iustin Pop

721 72737a7f Iustin Pop
    This is a single-node call.
722 a8083063 Iustin Pop

723 72737a7f Iustin Pop
    """
724 72737a7f Iustin Pop
    c = Client("os_get", [name])
725 25348212 Iustin Pop
    self._ConnectNode(c, node)
726 3ef3c771 Iustin Pop
    c.Run()
727 3ef3c771 Iustin Pop
    result = c.GetResults().get(node, False)
728 72737a7f Iustin Pop
    if isinstance(result, dict):
729 72737a7f Iustin Pop
      return objects.OS.FromDict(result)
730 72737a7f Iustin Pop
    else:
731 72737a7f Iustin Pop
      return result
732 a8083063 Iustin Pop
733 72737a7f Iustin Pop
  def call_hooks_runner(self, node_list, hpath, phase, env):
734 72737a7f Iustin Pop
    """Call the hooks runner.
735 a8083063 Iustin Pop

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

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

742 72737a7f Iustin Pop
    """
743 72737a7f Iustin Pop
    params = [hpath, phase, env]
744 72737a7f Iustin Pop
    c = Client("hooks_runner", params)
745 25348212 Iustin Pop
    self._ConnectList(c, node_list)
746 3ef3c771 Iustin Pop
    c.Run()
747 3ef3c771 Iustin Pop
    result = c.GetResults()
748 72737a7f Iustin Pop
    return result
749 a8083063 Iustin Pop
750 72737a7f Iustin Pop
  def call_iallocator_runner(self, node, name, idata):
751 72737a7f Iustin Pop
    """Call an iallocator on a remote node
752 8d528b7c Iustin Pop

753 72737a7f Iustin Pop
    Args:
754 72737a7f Iustin Pop
      - name: the iallocator name
755 72737a7f Iustin Pop
      - input: the json-encoded input string
756 8d528b7c Iustin Pop

757 72737a7f Iustin Pop
    This is a single-node call.
758 8d528b7c Iustin Pop

759 72737a7f Iustin Pop
    """
760 72737a7f Iustin Pop
    params = [name, idata]
761 72737a7f Iustin Pop
    c = Client("iallocator_runner", params)
762 25348212 Iustin Pop
    self._ConnectNode(c, node)
763 3ef3c771 Iustin Pop
    c.Run()
764 3ef3c771 Iustin Pop
    result = c.GetResults().get(node, False)
765 72737a7f Iustin Pop
    return result
766 8d528b7c Iustin Pop
767 72737a7f Iustin Pop
  def call_blockdev_grow(self, node, cf_bdev, amount):
768 72737a7f Iustin Pop
    """Request a snapshot of the given block device.
769 4c8ba8b3 Iustin Pop

770 72737a7f Iustin Pop
    This is a single-node call.
771 4c8ba8b3 Iustin Pop

772 72737a7f Iustin Pop
    """
773 72737a7f Iustin Pop
    c = Client("blockdev_grow", [cf_bdev.ToDict(), amount])
774 25348212 Iustin Pop
    self._ConnectNode(c, node)
775 3ef3c771 Iustin Pop
    c.Run()
776 3ef3c771 Iustin Pop
    return c.GetResults().get(node, False)
777 4c8ba8b3 Iustin Pop
778 72737a7f Iustin Pop
  def call_blockdev_snapshot(self, node, cf_bdev):
779 72737a7f Iustin Pop
    """Request a snapshot of the given block device.
780 a8083063 Iustin Pop

781 72737a7f Iustin Pop
    This is a single-node call.
782 a8083063 Iustin Pop

783 72737a7f Iustin Pop
    """
784 72737a7f Iustin Pop
    c = Client("blockdev_snapshot", [cf_bdev.ToDict()])
785 25348212 Iustin Pop
    self._ConnectNode(c, node)
786 3ef3c771 Iustin Pop
    c.Run()
787 3ef3c771 Iustin Pop
    return c.GetResults().get(node, False)
788 a8083063 Iustin Pop
789 72737a7f Iustin Pop
  def call_snapshot_export(self, node, snap_bdev, dest_node, instance,
790 74c47259 Iustin Pop
                           cluster_name, idx):
791 72737a7f Iustin Pop
    """Request the export of a given snapshot.
792 a8083063 Iustin Pop

793 72737a7f Iustin Pop
    This is a single-node call.
794 a8083063 Iustin Pop

795 72737a7f Iustin Pop
    """
796 26ba2bd8 Iustin Pop
    params = [snap_bdev.ToDict(), dest_node,
797 74c47259 Iustin Pop
              self._InstDict(instance), cluster_name, idx]
798 72737a7f Iustin Pop
    c = Client("snapshot_export", params)
799 25348212 Iustin Pop
    self._ConnectNode(c, node)
800 3ef3c771 Iustin Pop
    c.Run()
801 3ef3c771 Iustin Pop
    return c.GetResults().get(node, False)
802 a8083063 Iustin Pop
803 72737a7f Iustin Pop
  def call_finalize_export(self, node, instance, snap_disks):
804 72737a7f Iustin Pop
    """Request the completion of an export operation.
805 a8083063 Iustin Pop

806 72737a7f Iustin Pop
    This writes the export config file, etc.
807 a8083063 Iustin Pop

808 72737a7f Iustin Pop
    This is a single-node call.
809 a8083063 Iustin Pop

810 72737a7f Iustin Pop
    """
811 72737a7f Iustin Pop
    flat_disks = []
812 72737a7f Iustin Pop
    for disk in snap_disks:
813 72737a7f Iustin Pop
      flat_disks.append(disk.ToDict())
814 26ba2bd8 Iustin Pop
    params = [self._InstDict(instance), flat_disks]
815 72737a7f Iustin Pop
    c = Client("finalize_export", params)
816 25348212 Iustin Pop
    self._ConnectNode(c, node)
817 3ef3c771 Iustin Pop
    c.Run()
818 3ef3c771 Iustin Pop
    return c.GetResults().get(node, False)
819 a8083063 Iustin Pop
820 72737a7f Iustin Pop
  def call_export_info(self, node, path):
821 72737a7f Iustin Pop
    """Queries the export information in a given path.
822 a8083063 Iustin Pop

823 72737a7f Iustin Pop
    This is a single-node call.
824 a8083063 Iustin Pop

825 72737a7f Iustin Pop
    """
826 72737a7f Iustin Pop
    c = Client("export_info", [path])
827 25348212 Iustin Pop
    self._ConnectNode(c, node)
828 3ef3c771 Iustin Pop
    c.Run()
829 3ef3c771 Iustin Pop
    result = c.GetResults().get(node, False)
830 72737a7f Iustin Pop
    if not result:
831 72737a7f Iustin Pop
      return result
832 72737a7f Iustin Pop
    return objects.SerializableConfigParser.Loads(str(result))
833 a8083063 Iustin Pop
834 6c0af70e Guido Trotter
  def call_instance_os_import(self, node, inst, src_node, src_images,
835 6c0af70e Guido Trotter
                              cluster_name):
836 72737a7f Iustin Pop
    """Request the import of a backup into an instance.
837 a8083063 Iustin Pop

838 72737a7f Iustin Pop
    This is a single-node call.
839 a8083063 Iustin Pop

840 72737a7f Iustin Pop
    """
841 6c0af70e Guido Trotter
    params = [self._InstDict(inst), src_node, src_images, cluster_name]
842 72737a7f Iustin Pop
    c = Client("instance_os_import", params)
843 25348212 Iustin Pop
    self._ConnectNode(c, node)
844 3ef3c771 Iustin Pop
    c.Run()
845 3ef3c771 Iustin Pop
    return c.GetResults().get(node, False)
846 a8083063 Iustin Pop
847 72737a7f Iustin Pop
  def call_export_list(self, node_list):
848 72737a7f Iustin Pop
    """Gets the stored exports list.
849 a8083063 Iustin Pop

850 72737a7f Iustin Pop
    This is a multi-node call.
851 a8083063 Iustin Pop

852 72737a7f Iustin Pop
    """
853 72737a7f Iustin Pop
    c = Client("export_list", [])
854 25348212 Iustin Pop
    self._ConnectList(c, node_list)
855 3ef3c771 Iustin Pop
    c.Run()
856 3ef3c771 Iustin Pop
    result = c.GetResults()
857 72737a7f Iustin Pop
    return result
858 a8083063 Iustin Pop
859 72737a7f Iustin Pop
  def call_export_remove(self, node, export):
860 72737a7f Iustin Pop
    """Requests removal of a given export.
861 a8083063 Iustin Pop

862 72737a7f Iustin Pop
    This is a single-node call.
863 a8083063 Iustin Pop

864 72737a7f Iustin Pop
    """
865 72737a7f Iustin Pop
    c = Client("export_remove", [export])
866 25348212 Iustin Pop
    self._ConnectNode(c, node)
867 3ef3c771 Iustin Pop
    c.Run()
868 3ef3c771 Iustin Pop
    return c.GetResults().get(node, False)
869 a8083063 Iustin Pop
870 15396f60 Michael Hanselmann
  @staticmethod
871 15396f60 Michael Hanselmann
  def call_node_leave_cluster(node):
872 72737a7f Iustin Pop
    """Requests a node to clean the cluster information it has.
873 a8083063 Iustin Pop

874 72737a7f Iustin Pop
    This will remove the configuration information from the ganeti data
875 72737a7f Iustin Pop
    dir.
876 a8083063 Iustin Pop

877 72737a7f Iustin Pop
    This is a single-node call.
878 a8083063 Iustin Pop

879 72737a7f Iustin Pop
    """
880 72737a7f Iustin Pop
    c = Client("node_leave_cluster", [])
881 3ef3c771 Iustin Pop
    c.ConnectNode(node)
882 3ef3c771 Iustin Pop
    c.Run()
883 3ef3c771 Iustin Pop
    return c.GetResults().get(node, False)
884 dcb93971 Michael Hanselmann
885 72737a7f Iustin Pop
  def call_node_volumes(self, node_list):
886 72737a7f Iustin Pop
    """Gets all volumes on node(s).
887 dcb93971 Michael Hanselmann

888 72737a7f Iustin Pop
    This is a multi-node call.
889 dcb93971 Michael Hanselmann

890 72737a7f Iustin Pop
    """
891 72737a7f Iustin Pop
    c = Client("node_volumes", [])
892 25348212 Iustin Pop
    self._ConnectList(c, node_list)
893 3ef3c771 Iustin Pop
    c.Run()
894 3ef3c771 Iustin Pop
    return c.GetResults()
895 06009e27 Iustin Pop
896 72737a7f Iustin Pop
  def call_test_delay(self, node_list, duration):
897 72737a7f Iustin Pop
    """Sleep for a fixed time on given node(s).
898 06009e27 Iustin Pop

899 72737a7f Iustin Pop
    This is a multi-node call.
900 06009e27 Iustin Pop

901 72737a7f Iustin Pop
    """
902 72737a7f Iustin Pop
    c = Client("test_delay", [duration])
903 25348212 Iustin Pop
    self._ConnectList(c, node_list)
904 3ef3c771 Iustin Pop
    c.Run()
905 3ef3c771 Iustin Pop
    return c.GetResults()
906 5e04ed8b Manuel Franceschini
907 72737a7f Iustin Pop
  def call_file_storage_dir_create(self, node, file_storage_dir):
908 72737a7f Iustin Pop
    """Create the given file storage directory.
909 5e04ed8b Manuel Franceschini

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

912 72737a7f Iustin Pop
    """
913 72737a7f Iustin Pop
    c = Client("file_storage_dir_create", [file_storage_dir])
914 25348212 Iustin Pop
    self._ConnectNode(c, node)
915 3ef3c771 Iustin Pop
    c.Run()
916 3ef3c771 Iustin Pop
    return c.GetResults().get(node, False)
917 5e04ed8b Manuel Franceschini
918 72737a7f Iustin Pop
  def call_file_storage_dir_remove(self, node, file_storage_dir):
919 72737a7f Iustin Pop
    """Remove the given file storage directory.
920 5e04ed8b Manuel Franceschini

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

923 72737a7f Iustin Pop
    """
924 72737a7f Iustin Pop
    c = Client("file_storage_dir_remove", [file_storage_dir])
925 25348212 Iustin Pop
    self._ConnectNode(c, node)
926 3ef3c771 Iustin Pop
    c.Run()
927 3ef3c771 Iustin Pop
    return c.GetResults().get(node, False)
928 5e04ed8b Manuel Franceschini
929 72737a7f Iustin Pop
  def call_file_storage_dir_rename(self, node, old_file_storage_dir,
930 72737a7f Iustin Pop
                                   new_file_storage_dir):
931 72737a7f Iustin Pop
    """Rename file storage directory.
932 5e04ed8b Manuel Franceschini

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

935 72737a7f Iustin Pop
    """
936 72737a7f Iustin Pop
    c = Client("file_storage_dir_rename",
937 72737a7f Iustin Pop
               [old_file_storage_dir, new_file_storage_dir])
938 25348212 Iustin Pop
    self._ConnectNode(c, node)
939 3ef3c771 Iustin Pop
    c.Run()
940 3ef3c771 Iustin Pop
    return c.GetResults().get(node, False)
941 ca52cdeb Michael Hanselmann
942 72737a7f Iustin Pop
  @staticmethod
943 99aabbed Iustin Pop
  def call_jobqueue_update(node_list, address_list, file_name, content):
944 72737a7f Iustin Pop
    """Update job queue.
945 ca52cdeb Michael Hanselmann

946 72737a7f Iustin Pop
    This is a multi-node call.
947 ca52cdeb Michael Hanselmann

948 72737a7f Iustin Pop
    """
949 72737a7f Iustin Pop
    c = Client("jobqueue_update", [file_name, content])
950 99aabbed Iustin Pop
    c.ConnectList(node_list, address_list=address_list)
951 3ef3c771 Iustin Pop
    c.Run()
952 3ef3c771 Iustin Pop
    result = c.GetResults()
953 72737a7f Iustin Pop
    return result
954 ca52cdeb Michael Hanselmann
955 72737a7f Iustin Pop
  @staticmethod
956 72737a7f Iustin Pop
  def call_jobqueue_purge(node):
957 72737a7f Iustin Pop
    """Purge job queue.
958 ca52cdeb Michael Hanselmann

959 72737a7f Iustin Pop
    This is a single-node call.
960 ca52cdeb Michael Hanselmann

961 72737a7f Iustin Pop
    """
962 72737a7f Iustin Pop
    c = Client("jobqueue_purge", [])
963 3ef3c771 Iustin Pop
    c.ConnectNode(node)
964 3ef3c771 Iustin Pop
    c.Run()
965 3ef3c771 Iustin Pop
    return c.GetResults().get(node, False)
966 af5ebcb1 Michael Hanselmann
967 72737a7f Iustin Pop
  @staticmethod
968 99aabbed Iustin Pop
  def call_jobqueue_rename(node_list, address_list, old, new):
969 72737a7f Iustin Pop
    """Rename a job queue file.
970 af5ebcb1 Michael Hanselmann

971 72737a7f Iustin Pop
    This is a multi-node call.
972 af5ebcb1 Michael Hanselmann

973 72737a7f Iustin Pop
    """
974 72737a7f Iustin Pop
    c = Client("jobqueue_rename", [old, new])
975 99aabbed Iustin Pop
    c.ConnectList(node_list, address_list=address_list)
976 3ef3c771 Iustin Pop
    c.Run()
977 3ef3c771 Iustin Pop
    result = c.GetResults()
978 72737a7f Iustin Pop
    return result
979 6217e295 Iustin Pop
980 6217e295 Iustin Pop
981 5d672980 Iustin Pop
  @staticmethod
982 5d672980 Iustin Pop
  def call_jobqueue_set_drain(node_list, drain_flag):
983 5d672980 Iustin Pop
    """Set the drain flag on the queue.
984 5d672980 Iustin Pop

985 5d672980 Iustin Pop
    This is a multi-node call.
986 5d672980 Iustin Pop

987 5d672980 Iustin Pop
    @type node_list: list
988 5d672980 Iustin Pop
    @param node_list: the list of nodes to query
989 5d672980 Iustin Pop
    @type drain_flag: bool
990 5d672980 Iustin Pop
    @param drain_flag: if True, will set the drain flag, otherwise reset it.
991 5d672980 Iustin Pop

992 5d672980 Iustin Pop
    """
993 5d672980 Iustin Pop
    c = Client("jobqueue_set_drain", [drain_flag])
994 3ef3c771 Iustin Pop
    c.ConnectList(node_list)
995 3ef3c771 Iustin Pop
    c.Run()
996 3ef3c771 Iustin Pop
    result = c.GetResults()
997 5d672980 Iustin Pop
    return result
998 5d672980 Iustin Pop
999 5d672980 Iustin Pop
1000 6217e295 Iustin Pop
  def call_hypervisor_validate_params(self, node_list, hvname, hvparams):
1001 6217e295 Iustin Pop
    """Validate the hypervisor params.
1002 6217e295 Iustin Pop

1003 6217e295 Iustin Pop
    This is a multi-node call.
1004 6217e295 Iustin Pop

1005 6217e295 Iustin Pop
    @type node_list: list
1006 6217e295 Iustin Pop
    @param node_list: the list of nodes to query
1007 6217e295 Iustin Pop
    @type hvname: string
1008 6217e295 Iustin Pop
    @param hvname: the hypervisor name
1009 6217e295 Iustin Pop
    @type hvparams: dict
1010 6217e295 Iustin Pop
    @param hvparams: the hypervisor parameters to be validated
1011 6217e295 Iustin Pop

1012 6217e295 Iustin Pop
    """
1013 6217e295 Iustin Pop
    cluster = self._cfg.GetClusterInfo()
1014 6217e295 Iustin Pop
    hv_full = cluster.FillDict(cluster.hvparams.get(hvname, {}), hvparams)
1015 6217e295 Iustin Pop
    c = Client("hypervisor_validate_params", [hvname, hv_full])
1016 25348212 Iustin Pop
    self._ConnectList(c, node_list)
1017 3ef3c771 Iustin Pop
    c.Run()
1018 3ef3c771 Iustin Pop
    result = c.GetResults()
1019 6217e295 Iustin Pop
    return result