Statistics
| Branch: | Tag: | Revision:

root / lib / rpc.py @ 26ba2bd8

History | View | Annotate | Download (23.4 kB)

1 2f31098c Iustin Pop
#
2 a8083063 Iustin Pop
#
3 a8083063 Iustin Pop
4 a8083063 Iustin Pop
# Copyright (C) 2006, 2007 Google Inc.
5 a8083063 Iustin Pop
#
6 a8083063 Iustin Pop
# This program is free software; you can redistribute it and/or modify
7 a8083063 Iustin Pop
# it under the terms of the GNU General Public License as published by
8 a8083063 Iustin Pop
# the Free Software Foundation; either version 2 of the License, or
9 a8083063 Iustin Pop
# (at your option) any later version.
10 a8083063 Iustin Pop
#
11 a8083063 Iustin Pop
# This program is distributed in the hope that it will be useful, but
12 a8083063 Iustin Pop
# WITHOUT ANY WARRANTY; without even the implied warranty of
13 a8083063 Iustin Pop
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 a8083063 Iustin Pop
# General Public License for more details.
15 a8083063 Iustin Pop
#
16 a8083063 Iustin Pop
# You should have received a copy of the GNU General Public License
17 a8083063 Iustin Pop
# along with this program; if not, write to the Free Software
18 a8083063 Iustin Pop
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 a8083063 Iustin Pop
# 02110-1301, USA.
20 a8083063 Iustin Pop
21 a8083063 Iustin Pop
22 a8083063 Iustin Pop
"""Script to show add a new node to the cluster
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 a8083063 Iustin Pop
37 81010134 Iustin Pop
import simplejson
38 a8083063 Iustin Pop
39 a8083063 Iustin Pop
from ganeti import logger
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 a8083063 Iustin Pop
  def __init__(self, parent, node):
53 a8083063 Iustin Pop
    self.parent = parent
54 a8083063 Iustin Pop
    self.node = node
55 81010134 Iustin Pop
    self.failed = False
56 a8083063 Iustin Pop
57 81010134 Iustin Pop
    self.http_conn = hc = httplib.HTTPConnection(node, self.parent.port)
58 a8083063 Iustin Pop
    try:
59 81010134 Iustin Pop
      hc.connect()
60 81010134 Iustin Pop
      hc.putrequest('PUT', "/%s" % self.parent.procedure,
61 81010134 Iustin Pop
                    skip_accept_encoding=True)
62 81010134 Iustin Pop
      hc.putheader('Content-Length', str(len(parent.body)))
63 81010134 Iustin Pop
      hc.endheaders()
64 81010134 Iustin Pop
      hc.send(parent.body)
65 81010134 Iustin Pop
    except socket.error, err:
66 81010134 Iustin Pop
      logger.Error("Error connecting to %s: %s" % (node, str(err)))
67 81010134 Iustin Pop
      self.failed = True
68 81010134 Iustin Pop
69 81010134 Iustin Pop
  def get_response(self):
70 81010134 Iustin Pop
    """Try to process the response from the node.
71 a8083063 Iustin Pop

72 a8083063 Iustin Pop
    """
73 81010134 Iustin Pop
    if self.failed:
74 81010134 Iustin Pop
      # we already failed in connect
75 a8083063 Iustin Pop
      return False
76 81010134 Iustin Pop
    resp = self.http_conn.getresponse()
77 81010134 Iustin Pop
    if resp.status != 200:
78 a8083063 Iustin Pop
      return False
79 81010134 Iustin Pop
    try:
80 81010134 Iustin Pop
      length = int(resp.getheader('Content-Length', '0'))
81 81010134 Iustin Pop
    except ValueError:
82 81010134 Iustin Pop
      return False
83 81010134 Iustin Pop
    if not length:
84 81010134 Iustin Pop
      logger.Error("Zero-length reply from %s" % self.node)
85 81010134 Iustin Pop
      return False
86 81010134 Iustin Pop
    payload = resp.read(length)
87 81010134 Iustin Pop
    unload = simplejson.loads(payload)
88 81010134 Iustin Pop
    return unload
89 a8083063 Iustin Pop
90 a8083063 Iustin Pop
91 a8083063 Iustin Pop
class Client:
92 a8083063 Iustin Pop
  """RPC Client class.
93 a8083063 Iustin Pop

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

98 a8083063 Iustin Pop
  One current bug is that generic failure is still signalled by
99 a8083063 Iustin Pop
  'False' result, which is not good. This overloading of values can
100 a8083063 Iustin Pop
  cause bugs.
101 a8083063 Iustin Pop

102 a8083063 Iustin Pop
  """
103 a8083063 Iustin Pop
  result_set = False
104 a8083063 Iustin Pop
  result = False
105 a8083063 Iustin Pop
  allresult = []
106 a8083063 Iustin Pop
107 a8083063 Iustin Pop
  def __init__(self, procedure, args):
108 eb1328a9 Michael Hanselmann
    self.port = utils.GetNodeDaemonPort()
109 eb1328a9 Michael Hanselmann
    self.nodepw = utils.GetNodeDaemonPassword()
110 a8083063 Iustin Pop
    self.nc = {}
111 a8083063 Iustin Pop
    self.results = {}
112 a8083063 Iustin Pop
    self.procedure = procedure
113 a8083063 Iustin Pop
    self.args = args
114 81010134 Iustin Pop
    self.body = simplejson.dumps(args)
115 a8083063 Iustin Pop
116 a8083063 Iustin Pop
  #--- generic connector -------------
117 a8083063 Iustin Pop
118 a8083063 Iustin Pop
  def connect_list(self, node_list):
119 a8083063 Iustin Pop
    """Add a list of nodes to the target nodes.
120 a8083063 Iustin Pop

121 a8083063 Iustin Pop
    """
122 a8083063 Iustin Pop
    for node in node_list:
123 a8083063 Iustin Pop
      self.connect(node)
124 a8083063 Iustin Pop
125 a8083063 Iustin Pop
  def connect(self, connect_node):
126 a8083063 Iustin Pop
    """Add a node to the target list.
127 a8083063 Iustin Pop

128 a8083063 Iustin Pop
    """
129 a8083063 Iustin Pop
    self.nc[connect_node] = nc = NodeController(self, connect_node)
130 a8083063 Iustin Pop
131 a8083063 Iustin Pop
  def getresult(self):
132 a8083063 Iustin Pop
    """Return the results of the call.
133 a8083063 Iustin Pop

134 a8083063 Iustin Pop
    """
135 a8083063 Iustin Pop
    return self.results
136 a8083063 Iustin Pop
137 a8083063 Iustin Pop
  def run(self):
138 a8083063 Iustin Pop
    """Wrapper over reactor.run().
139 a8083063 Iustin Pop

140 a8083063 Iustin Pop
    This function simply calls reactor.run() if we have any requests
141 a8083063 Iustin Pop
    queued, otherwise it does nothing.
142 a8083063 Iustin Pop

143 a8083063 Iustin Pop
    """
144 81010134 Iustin Pop
    for node, nc in self.nc.items():
145 81010134 Iustin Pop
      self.results[node] = nc.get_response()
146 a8083063 Iustin Pop
147 a8083063 Iustin Pop
148 72737a7f Iustin Pop
class RpcRunner(object):
149 72737a7f Iustin Pop
  """RPC runner class"""
150 a8083063 Iustin Pop
151 72737a7f Iustin Pop
  def __init__(self, cfg):
152 72737a7f Iustin Pop
    """Initialized the rpc runner.
153 a8083063 Iustin Pop

154 72737a7f Iustin Pop
    @type cfg:  C{config.ConfigWriter}
155 72737a7f Iustin Pop
    @param cfg: the configuration object that will be used to get data
156 72737a7f Iustin Pop
                about the cluster
157 a8083063 Iustin Pop

158 72737a7f Iustin Pop
    """
159 72737a7f Iustin Pop
    self._cfg = cfg
160 a8083063 Iustin Pop
161 26ba2bd8 Iustin Pop
  def _InstDict(self, instance):
162 26ba2bd8 Iustin Pop
    """Convert the given instance to a dict.
163 26ba2bd8 Iustin Pop

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

167 26ba2bd8 Iustin Pop
    @type instance: L{objects.Instance}
168 26ba2bd8 Iustin Pop
    @param instance: an Instance object
169 26ba2bd8 Iustin Pop
    @rtype: dict
170 26ba2bd8 Iustin Pop
    @return: the instance dict, with the hvparams filled with the
171 26ba2bd8 Iustin Pop
        cluster defaults
172 26ba2bd8 Iustin Pop

173 26ba2bd8 Iustin Pop
    """
174 26ba2bd8 Iustin Pop
    idict = instance.ToDict()
175 26ba2bd8 Iustin Pop
    idict["hvparams"] = self._cfg.GetClusterInfo().FillHV(instance)
176 26ba2bd8 Iustin Pop
    return idict
177 26ba2bd8 Iustin Pop
178 72737a7f Iustin Pop
  def call_volume_list(self, node_list, vg_name):
179 72737a7f Iustin Pop
    """Gets the logical volumes present in a given volume group.
180 a8083063 Iustin Pop

181 72737a7f Iustin Pop
    This is a multi-node call.
182 a8083063 Iustin Pop

183 72737a7f Iustin Pop
    """
184 72737a7f Iustin Pop
    c = Client("volume_list", [vg_name])
185 72737a7f Iustin Pop
    c.connect_list(node_list)
186 72737a7f Iustin Pop
    c.run()
187 72737a7f Iustin Pop
    return c.getresult()
188 a8083063 Iustin Pop
189 72737a7f Iustin Pop
  def call_vg_list(self, node_list):
190 72737a7f Iustin Pop
    """Gets the volume group list.
191 a8083063 Iustin Pop

192 72737a7f Iustin Pop
    This is a multi-node call.
193 a8083063 Iustin Pop

194 72737a7f Iustin Pop
    """
195 72737a7f Iustin Pop
    c = Client("vg_list", [])
196 72737a7f Iustin Pop
    c.connect_list(node_list)
197 72737a7f Iustin Pop
    c.run()
198 72737a7f Iustin Pop
    return c.getresult()
199 a8083063 Iustin Pop
200 72737a7f Iustin Pop
  def call_bridges_exist(self, node, bridges_list):
201 72737a7f Iustin Pop
    """Checks if a node has all the bridges given.
202 a8083063 Iustin Pop

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

207 72737a7f Iustin Pop
    This is a single-node call.
208 a8083063 Iustin Pop

209 72737a7f Iustin Pop
    """
210 72737a7f Iustin Pop
    c = Client("bridges_exist", [bridges_list])
211 72737a7f Iustin Pop
    c.connect(node)
212 72737a7f Iustin Pop
    c.run()
213 72737a7f Iustin Pop
    return c.getresult().get(node, False)
214 a8083063 Iustin Pop
215 72737a7f Iustin Pop
  def call_instance_start(self, node, instance, extra_args):
216 72737a7f Iustin Pop
    """Starts an instance.
217 a8083063 Iustin Pop

218 72737a7f Iustin Pop
    This is a single-node call.
219 a8083063 Iustin Pop

220 72737a7f Iustin Pop
    """
221 26ba2bd8 Iustin Pop
    c = Client("instance_start", [self._InstDict(instance), extra_args])
222 72737a7f Iustin Pop
    c.connect(node)
223 72737a7f Iustin Pop
    c.run()
224 72737a7f Iustin Pop
    return c.getresult().get(node, False)
225 a8083063 Iustin Pop
226 72737a7f Iustin Pop
  def call_instance_shutdown(self, node, instance):
227 72737a7f Iustin Pop
    """Stops an instance.
228 a8083063 Iustin Pop

229 72737a7f Iustin Pop
    This is a single-node call.
230 2a10865c Iustin Pop

231 72737a7f Iustin Pop
    """
232 26ba2bd8 Iustin Pop
    c = Client("instance_shutdown", [self._InstDict(instance)])
233 72737a7f Iustin Pop
    c.connect(node)
234 72737a7f Iustin Pop
    c.run()
235 72737a7f Iustin Pop
    return c.getresult().get(node, False)
236 2a10865c Iustin Pop
237 72737a7f Iustin Pop
  def call_instance_migrate(self, node, instance, target, live):
238 72737a7f Iustin Pop
    """Migrate an instance.
239 2a10865c Iustin Pop

240 72737a7f Iustin Pop
    This is a single-node call.
241 2a10865c Iustin Pop

242 72737a7f Iustin Pop
    @type node: string
243 72737a7f Iustin Pop
    @param node: the node on which the instance is currently running
244 72737a7f Iustin Pop
    @type instance: C{objects.Instance}
245 72737a7f Iustin Pop
    @param instance: the instance definition
246 72737a7f Iustin Pop
    @type target: string
247 72737a7f Iustin Pop
    @param target: the target node name
248 72737a7f Iustin Pop
    @type live: boolean
249 72737a7f Iustin Pop
    @param live: whether the migration should be done live or not (the
250 72737a7f Iustin Pop
        interpretation of this parameter is left to the hypervisor)
251 007a2f3e Alexander Schreiber

252 72737a7f Iustin Pop
    """
253 26ba2bd8 Iustin Pop
    c = Client("instance_migrate", [self._InstDict(instance), target, live])
254 72737a7f Iustin Pop
    c.connect(node)
255 72737a7f Iustin Pop
    c.run()
256 72737a7f Iustin Pop
    return c.getresult().get(node, False)
257 007a2f3e Alexander Schreiber
258 72737a7f Iustin Pop
  def call_instance_reboot(self, node, instance, reboot_type, extra_args):
259 72737a7f Iustin Pop
    """Reboots an instance.
260 007a2f3e Alexander Schreiber

261 72737a7f Iustin Pop
    This is a single-node call.
262 a8083063 Iustin Pop

263 72737a7f Iustin Pop
    """
264 26ba2bd8 Iustin Pop
    c = Client("instance_reboot", [self._InstDict(instance),
265 26ba2bd8 Iustin Pop
                                   reboot_type, extra_args])
266 72737a7f Iustin Pop
    c.connect(node)
267 72737a7f Iustin Pop
    c.run()
268 72737a7f Iustin Pop
    return c.getresult().get(node, False)
269 a8083063 Iustin Pop
270 72737a7f Iustin Pop
  def call_instance_os_add(self, node, inst, osdev, swapdev):
271 72737a7f Iustin Pop
    """Installs an OS on the given instance.
272 a8083063 Iustin Pop

273 72737a7f Iustin Pop
    This is a single-node call.
274 decd5f45 Iustin Pop

275 72737a7f Iustin Pop
    """
276 26ba2bd8 Iustin Pop
    params = [self._InstDict(inst), osdev, swapdev]
277 72737a7f Iustin Pop
    c = Client("instance_os_add", params)
278 72737a7f Iustin Pop
    c.connect(node)
279 72737a7f Iustin Pop
    c.run()
280 72737a7f Iustin Pop
    return c.getresult().get(node, False)
281 decd5f45 Iustin Pop
282 72737a7f Iustin Pop
  def call_instance_run_rename(self, node, inst, old_name, osdev, swapdev):
283 72737a7f Iustin Pop
    """Run the OS rename script for an instance.
284 decd5f45 Iustin Pop

285 72737a7f Iustin Pop
    This is a single-node call.
286 a8083063 Iustin Pop

287 72737a7f Iustin Pop
    """
288 26ba2bd8 Iustin Pop
    params = [self._InstDict(inst), old_name, osdev, swapdev]
289 72737a7f Iustin Pop
    c = Client("instance_run_rename", params)
290 72737a7f Iustin Pop
    c.connect(node)
291 72737a7f Iustin Pop
    c.run()
292 72737a7f Iustin Pop
    return c.getresult().get(node, False)
293 a8083063 Iustin Pop
294 72737a7f Iustin Pop
  def call_instance_info(self, node, instance, hname):
295 72737a7f Iustin Pop
    """Returns information about a single instance.
296 a8083063 Iustin Pop

297 72737a7f Iustin Pop
    This is a single-node call.
298 a8083063 Iustin Pop

299 72737a7f Iustin Pop
    @type node_list: list
300 72737a7f Iustin Pop
    @param node_list: the list of nodes to query
301 72737a7f Iustin Pop
    @type instance: string
302 72737a7f Iustin Pop
    @param instance: the instance name
303 72737a7f Iustin Pop
    @type hname: string
304 72737a7f Iustin Pop
    @param hname: the hypervisor type of the instance
305 a8083063 Iustin Pop

306 72737a7f Iustin Pop
    """
307 16ad1a83 Iustin Pop
    c = Client("instance_info", [instance, hname])
308 72737a7f Iustin Pop
    c.connect(node)
309 72737a7f Iustin Pop
    c.run()
310 72737a7f Iustin Pop
    return c.getresult().get(node, False)
311 e69d05fd Iustin Pop
312 72737a7f Iustin Pop
  def call_all_instances_info(self, node_list, hypervisor_list):
313 72737a7f Iustin Pop
    """Returns information about all instances on the given nodes.
314 a8083063 Iustin Pop

315 72737a7f Iustin Pop
    This is a multi-node call.
316 a8083063 Iustin Pop

317 72737a7f Iustin Pop
    @type node_list: list
318 72737a7f Iustin Pop
    @param node_list: the list of nodes to query
319 72737a7f Iustin Pop
    @type hypervisor_list: list
320 72737a7f Iustin Pop
    @param hypervisor_list: the hypervisors to query for instances
321 a8083063 Iustin Pop

322 72737a7f Iustin Pop
    """
323 72737a7f Iustin Pop
    c = Client("all_instances_info", [hypervisor_list])
324 72737a7f Iustin Pop
    c.connect_list(node_list)
325 72737a7f Iustin Pop
    c.run()
326 72737a7f Iustin Pop
    return c.getresult()
327 e69d05fd Iustin Pop
328 72737a7f Iustin Pop
  def call_instance_list(self, node_list, hypervisor_list):
329 72737a7f Iustin Pop
    """Returns the list of running instances on a given node.
330 a8083063 Iustin Pop

331 72737a7f Iustin Pop
    This is a multi-node call.
332 a8083063 Iustin Pop

333 72737a7f Iustin Pop
    @type node_list: list
334 72737a7f Iustin Pop
    @param node_list: the list of nodes to query
335 72737a7f Iustin Pop
    @type hypervisor_list: list
336 72737a7f Iustin Pop
    @param hypervisor_list: the hypervisors to query for instances
337 16abfbc2 Alexander Schreiber

338 72737a7f Iustin Pop
    """
339 72737a7f Iustin Pop
    c = Client("instance_list", [hypervisor_list])
340 72737a7f Iustin Pop
    c.connect_list(node_list)
341 72737a7f Iustin Pop
    c.run()
342 72737a7f Iustin Pop
    return c.getresult()
343 16abfbc2 Alexander Schreiber
344 72737a7f Iustin Pop
  def call_node_tcp_ping(self, node, source, target, port, timeout,
345 72737a7f Iustin Pop
                         live_port_needed):
346 72737a7f Iustin Pop
    """Do a TcpPing on the remote node
347 a8083063 Iustin Pop

348 72737a7f Iustin Pop
    This is a single-node call.
349 caad16e2 Iustin Pop

350 72737a7f Iustin Pop
    """
351 72737a7f Iustin Pop
    c = Client("node_tcp_ping", [source, target, port, timeout,
352 72737a7f Iustin Pop
                                 live_port_needed])
353 72737a7f Iustin Pop
    c.connect(node)
354 72737a7f Iustin Pop
    c.run()
355 72737a7f Iustin Pop
    return c.getresult().get(node, False)
356 a8083063 Iustin Pop
357 caad16e2 Iustin Pop
  def call_node_has_ip_address(self, node, address):
358 caad16e2 Iustin Pop
    """Checks if a node has the given IP address.
359 caad16e2 Iustin Pop

360 caad16e2 Iustin Pop
    This is a single-node call.
361 caad16e2 Iustin Pop

362 caad16e2 Iustin Pop
    """
363 caad16e2 Iustin Pop
    c = Client("node_has_ip_address", [address])
364 caad16e2 Iustin Pop
    c.connect(node)
365 caad16e2 Iustin Pop
    c.run()
366 caad16e2 Iustin Pop
    return c.getresult().get(node, False)
367 a8083063 Iustin Pop
368 72737a7f Iustin Pop
  def call_node_info(self, node_list, vg_name, hypervisor_type):
369 72737a7f Iustin Pop
    """Return node information.
370 e69d05fd Iustin Pop

371 72737a7f Iustin Pop
    This will return memory information and volume group size and free
372 72737a7f Iustin Pop
    space.
373 a8083063 Iustin Pop

374 72737a7f Iustin Pop
    This is a multi-node call.
375 a8083063 Iustin Pop

376 72737a7f Iustin Pop
    @type node_list: list
377 72737a7f Iustin Pop
    @param node_list: the list of nodes to query
378 72737a7f Iustin Pop
    @type vgname: C{string}
379 72737a7f Iustin Pop
    @param vgname: the name of the volume group to ask for disk space
380 72737a7f Iustin Pop
        information
381 72737a7f Iustin Pop
    @type hypervisor_type: C{str}
382 72737a7f Iustin Pop
    @param hypervisor_type: the name of the hypervisor to ask for
383 72737a7f Iustin Pop
        memory information
384 a8083063 Iustin Pop

385 72737a7f Iustin Pop
    """
386 72737a7f Iustin Pop
    c = Client("node_info", [vg_name, hypervisor_type])
387 72737a7f Iustin Pop
    c.connect_list(node_list)
388 72737a7f Iustin Pop
    c.run()
389 72737a7f Iustin Pop
    retux = c.getresult()
390 a8083063 Iustin Pop
391 72737a7f Iustin Pop
    for node_name in retux:
392 72737a7f Iustin Pop
      ret = retux.get(node_name, False)
393 72737a7f Iustin Pop
      if type(ret) != dict:
394 72737a7f Iustin Pop
        logger.Error("could not connect to node %s" % (node_name))
395 72737a7f Iustin Pop
        ret = {}
396 a8083063 Iustin Pop
397 72737a7f Iustin Pop
      utils.CheckDict(ret,
398 72737a7f Iustin Pop
                      { 'memory_total' : '-',
399 72737a7f Iustin Pop
                        'memory_dom0' : '-',
400 72737a7f Iustin Pop
                        'memory_free' : '-',
401 72737a7f Iustin Pop
                        'vg_size' : 'node_unreachable',
402 72737a7f Iustin Pop
                        'vg_free' : '-' },
403 72737a7f Iustin Pop
                      "call_node_info",
404 72737a7f Iustin Pop
                      )
405 72737a7f Iustin Pop
    return retux
406 a8083063 Iustin Pop
407 72737a7f Iustin Pop
  def call_node_add(self, node, dsa, dsapub, rsa, rsapub, ssh, sshpub):
408 72737a7f Iustin Pop
    """Add a node to the cluster.
409 a8083063 Iustin Pop

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

412 72737a7f Iustin Pop
    """
413 72737a7f Iustin Pop
    params = [dsa, dsapub, rsa, rsapub, ssh, sshpub]
414 72737a7f Iustin Pop
    c = Client("node_add", params)
415 72737a7f Iustin Pop
    c.connect(node)
416 72737a7f Iustin Pop
    c.run()
417 72737a7f Iustin Pop
    return c.getresult().get(node, False)
418 a8083063 Iustin Pop
419 72737a7f Iustin Pop
  def call_node_verify(self, node_list, checkdict, cluster_name):
420 72737a7f Iustin Pop
    """Request verification of given parameters.
421 a8083063 Iustin Pop

422 72737a7f Iustin Pop
    This is a multi-node call.
423 a8083063 Iustin Pop

424 72737a7f Iustin Pop
    """
425 72737a7f Iustin Pop
    c = Client("node_verify", [checkdict, cluster_name])
426 72737a7f Iustin Pop
    c.connect_list(node_list)
427 72737a7f Iustin Pop
    c.run()
428 72737a7f Iustin Pop
    return c.getresult()
429 a8083063 Iustin Pop
430 72737a7f Iustin Pop
  @staticmethod
431 72737a7f Iustin Pop
  def call_node_start_master(node, start_daemons):
432 72737a7f Iustin Pop
    """Tells a node to activate itself as a master.
433 a8083063 Iustin Pop

434 72737a7f Iustin Pop
    This is a single-node call.
435 a8083063 Iustin Pop

436 72737a7f Iustin Pop
    """
437 72737a7f Iustin Pop
    c = Client("node_start_master", [start_daemons])
438 72737a7f Iustin Pop
    c.connect(node)
439 72737a7f Iustin Pop
    c.run()
440 72737a7f Iustin Pop
    return c.getresult().get(node, False)
441 a8083063 Iustin Pop
442 72737a7f Iustin Pop
  @staticmethod
443 72737a7f Iustin Pop
  def call_node_stop_master(node, stop_daemons):
444 72737a7f Iustin Pop
    """Tells a node to demote itself from master status.
445 a8083063 Iustin Pop

446 72737a7f Iustin Pop
    This is a single-node call.
447 4e071d3b Iustin Pop

448 72737a7f Iustin Pop
    """
449 72737a7f Iustin Pop
    c = Client("node_stop_master", [stop_daemons])
450 72737a7f Iustin Pop
    c.connect(node)
451 72737a7f Iustin Pop
    c.run()
452 72737a7f Iustin Pop
    return c.getresult().get(node, False)
453 4e071d3b Iustin Pop
454 72737a7f Iustin Pop
  @staticmethod
455 72737a7f Iustin Pop
  def call_master_info(node_list):
456 72737a7f Iustin Pop
    """Query master info.
457 4e071d3b Iustin Pop

458 72737a7f Iustin Pop
    This is a multi-node call.
459 a8083063 Iustin Pop

460 72737a7f Iustin Pop
    """
461 72737a7f Iustin Pop
    # TODO: should this method query down nodes?
462 72737a7f Iustin Pop
    c = Client("master_info", [])
463 72737a7f Iustin Pop
    c.connect_list(node_list)
464 72737a7f Iustin Pop
    c.run()
465 72737a7f Iustin Pop
    return c.getresult()
466 a8083063 Iustin Pop
467 72737a7f Iustin Pop
  def call_version(self, node_list):
468 72737a7f Iustin Pop
    """Query node version.
469 a8083063 Iustin Pop

470 72737a7f Iustin Pop
    This is a multi-node call.
471 a8083063 Iustin Pop

472 72737a7f Iustin Pop
    """
473 72737a7f Iustin Pop
    c = Client("version", [])
474 72737a7f Iustin Pop
    c.connect_list(node_list)
475 72737a7f Iustin Pop
    c.run()
476 72737a7f Iustin Pop
    return c.getresult()
477 a8083063 Iustin Pop
478 72737a7f Iustin Pop
  def call_blockdev_create(self, node, bdev, size, owner, on_primary, info):
479 72737a7f Iustin Pop
    """Request creation of a given block device.
480 a8083063 Iustin Pop

481 72737a7f Iustin Pop
    This is a single-node call.
482 a8083063 Iustin Pop

483 72737a7f Iustin Pop
    """
484 72737a7f Iustin Pop
    params = [bdev.ToDict(), size, owner, on_primary, info]
485 72737a7f Iustin Pop
    c = Client("blockdev_create", params)
486 72737a7f Iustin Pop
    c.connect(node)
487 72737a7f Iustin Pop
    c.run()
488 72737a7f Iustin Pop
    return c.getresult().get(node, False)
489 a8083063 Iustin Pop
490 72737a7f Iustin Pop
  def call_blockdev_remove(self, node, bdev):
491 72737a7f Iustin Pop
    """Request removal of a given block device.
492 a8083063 Iustin Pop

493 72737a7f Iustin Pop
    This is a single-node call.
494 f3e513ad Iustin Pop

495 72737a7f Iustin Pop
    """
496 72737a7f Iustin Pop
    c = Client("blockdev_remove", [bdev.ToDict()])
497 72737a7f Iustin Pop
    c.connect(node)
498 72737a7f Iustin Pop
    c.run()
499 72737a7f Iustin Pop
    return c.getresult().get(node, False)
500 f3e513ad Iustin Pop
501 72737a7f Iustin Pop
  def call_blockdev_rename(self, node, devlist):
502 72737a7f Iustin Pop
    """Request rename of the given block devices.
503 f3e513ad Iustin Pop

504 72737a7f Iustin Pop
    This is a single-node call.
505 a8083063 Iustin Pop

506 72737a7f Iustin Pop
    """
507 72737a7f Iustin Pop
    params = [(d.ToDict(), uid) for d, uid in devlist]
508 72737a7f Iustin Pop
    c = Client("blockdev_rename", params)
509 72737a7f Iustin Pop
    c.connect(node)
510 72737a7f Iustin Pop
    c.run()
511 72737a7f Iustin Pop
    return c.getresult().get(node, False)
512 a8083063 Iustin Pop
513 72737a7f Iustin Pop
  def call_blockdev_assemble(self, node, disk, owner, on_primary):
514 72737a7f Iustin Pop
    """Request assembling of a given block device.
515 a8083063 Iustin Pop

516 72737a7f Iustin Pop
    This is a single-node call.
517 a8083063 Iustin Pop

518 72737a7f Iustin Pop
    """
519 72737a7f Iustin Pop
    params = [disk.ToDict(), owner, on_primary]
520 72737a7f Iustin Pop
    c = Client("blockdev_assemble", params)
521 72737a7f Iustin Pop
    c.connect(node)
522 72737a7f Iustin Pop
    c.run()
523 72737a7f Iustin Pop
    return c.getresult().get(node, False)
524 a8083063 Iustin Pop
525 72737a7f Iustin Pop
  def call_blockdev_shutdown(self, node, disk):
526 72737a7f Iustin Pop
    """Request shutdown of a given block device.
527 a8083063 Iustin Pop

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

530 72737a7f Iustin Pop
    """
531 72737a7f Iustin Pop
    c = Client("blockdev_shutdown", [disk.ToDict()])
532 72737a7f Iustin Pop
    c.connect(node)
533 72737a7f Iustin Pop
    c.run()
534 72737a7f Iustin Pop
    return c.getresult().get(node, False)
535 a8083063 Iustin Pop
536 72737a7f Iustin Pop
  def call_blockdev_addchildren(self, node, bdev, ndevs):
537 72737a7f Iustin Pop
    """Request adding a list of children to a (mirroring) device.
538 a8083063 Iustin Pop

539 72737a7f Iustin Pop
    This is a single-node call.
540 a8083063 Iustin Pop

541 72737a7f Iustin Pop
    """
542 72737a7f Iustin Pop
    params = [bdev.ToDict(), [disk.ToDict() for disk in ndevs]]
543 72737a7f Iustin Pop
    c = Client("blockdev_addchildren", params)
544 72737a7f Iustin Pop
    c.connect(node)
545 72737a7f Iustin Pop
    c.run()
546 72737a7f Iustin Pop
    return c.getresult().get(node, False)
547 a8083063 Iustin Pop
548 72737a7f Iustin Pop
  def call_blockdev_removechildren(self, node, bdev, ndevs):
549 72737a7f Iustin Pop
    """Request removing a list of children from a (mirroring) device.
550 a8083063 Iustin Pop

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

553 72737a7f Iustin Pop
    """
554 72737a7f Iustin Pop
    params = [bdev.ToDict(), [disk.ToDict() for disk in ndevs]]
555 72737a7f Iustin Pop
    c = Client("blockdev_removechildren", params)
556 72737a7f Iustin Pop
    c.connect(node)
557 72737a7f Iustin Pop
    c.run()
558 72737a7f Iustin Pop
    return c.getresult().get(node, False)
559 a8083063 Iustin Pop
560 72737a7f Iustin Pop
  def call_blockdev_getmirrorstatus(self, node, disks):
561 72737a7f Iustin Pop
    """Request status of a (mirroring) device.
562 a8083063 Iustin Pop

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

565 72737a7f Iustin Pop
    """
566 72737a7f Iustin Pop
    params = [dsk.ToDict() for dsk in disks]
567 72737a7f Iustin Pop
    c = Client("blockdev_getmirrorstatus", params)
568 72737a7f Iustin Pop
    c.connect(node)
569 72737a7f Iustin Pop
    c.run()
570 72737a7f Iustin Pop
    return c.getresult().get(node, False)
571 a8083063 Iustin Pop
572 72737a7f Iustin Pop
  def call_blockdev_find(self, node, disk):
573 72737a7f Iustin Pop
    """Request identification of a given block device.
574 72737a7f Iustin Pop

575 72737a7f Iustin Pop
    This is a single-node call.
576 a8083063 Iustin Pop

577 72737a7f Iustin Pop
    """
578 72737a7f Iustin Pop
    c = Client("blockdev_find", [disk.ToDict()])
579 72737a7f Iustin Pop
    c.connect(node)
580 72737a7f Iustin Pop
    c.run()
581 72737a7f Iustin Pop
    return c.getresult().get(node, False)
582 d61cbe76 Iustin Pop
583 72737a7f Iustin Pop
  def call_blockdev_close(self, node, disks):
584 72737a7f Iustin Pop
    """Closes the given block devices.
585 d61cbe76 Iustin Pop

586 72737a7f Iustin Pop
    This is a single-node call.
587 d61cbe76 Iustin Pop

588 72737a7f Iustin Pop
    """
589 72737a7f Iustin Pop
    params = [cf.ToDict() for cf in disks]
590 72737a7f Iustin Pop
    c = Client("blockdev_close", params)
591 72737a7f Iustin Pop
    c.connect(node)
592 72737a7f Iustin Pop
    c.run()
593 72737a7f Iustin Pop
    return c.getresult().get(node, False)
594 a8083063 Iustin Pop
595 72737a7f Iustin Pop
  @staticmethod
596 72737a7f Iustin Pop
  def call_upload_file(node_list, file_name):
597 72737a7f Iustin Pop
    """Upload a file.
598 72737a7f Iustin Pop

599 72737a7f Iustin Pop
    The node will refuse the operation in case the file is not on the
600 72737a7f Iustin Pop
    approved file list.
601 72737a7f Iustin Pop

602 72737a7f Iustin Pop
    This is a multi-node call.
603 a8083063 Iustin Pop

604 72737a7f Iustin Pop
    """
605 72737a7f Iustin Pop
    fh = file(file_name)
606 72737a7f Iustin Pop
    try:
607 72737a7f Iustin Pop
      data = fh.read()
608 72737a7f Iustin Pop
    finally:
609 72737a7f Iustin Pop
      fh.close()
610 72737a7f Iustin Pop
    st = os.stat(file_name)
611 72737a7f Iustin Pop
    params = [file_name, data, st.st_mode, st.st_uid, st.st_gid,
612 72737a7f Iustin Pop
              st.st_atime, st.st_mtime]
613 72737a7f Iustin Pop
    c = Client("upload_file", params)
614 72737a7f Iustin Pop
    c.connect_list(node_list)
615 72737a7f Iustin Pop
    c.run()
616 72737a7f Iustin Pop
    return c.getresult()
617 72737a7f Iustin Pop
618 72737a7f Iustin Pop
  def call_os_diagnose(self, node_list):
619 72737a7f Iustin Pop
    """Request a diagnose of OS definitions.
620 72737a7f Iustin Pop

621 72737a7f Iustin Pop
    This is a multi-node call.
622 a8083063 Iustin Pop

623 72737a7f Iustin Pop
    """
624 72737a7f Iustin Pop
    c = Client("os_diagnose", [])
625 72737a7f Iustin Pop
    c.connect_list(node_list)
626 72737a7f Iustin Pop
    c.run()
627 72737a7f Iustin Pop
    result = c.getresult()
628 72737a7f Iustin Pop
    new_result = {}
629 72737a7f Iustin Pop
    for node_name in result:
630 72737a7f Iustin Pop
      if result[node_name]:
631 72737a7f Iustin Pop
        nr = [objects.OS.FromDict(oss) for oss in result[node_name]]
632 72737a7f Iustin Pop
      else:
633 72737a7f Iustin Pop
        nr = []
634 72737a7f Iustin Pop
      new_result[node_name] = nr
635 72737a7f Iustin Pop
    return new_result
636 a8083063 Iustin Pop
637 72737a7f Iustin Pop
  def call_os_get(self, node, name):
638 72737a7f Iustin Pop
    """Returns an OS definition.
639 a8083063 Iustin Pop

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

642 72737a7f Iustin Pop
    """
643 72737a7f Iustin Pop
    c = Client("os_get", [name])
644 72737a7f Iustin Pop
    c.connect(node)
645 72737a7f Iustin Pop
    c.run()
646 72737a7f Iustin Pop
    result = c.getresult().get(node, False)
647 72737a7f Iustin Pop
    if isinstance(result, dict):
648 72737a7f Iustin Pop
      return objects.OS.FromDict(result)
649 72737a7f Iustin Pop
    else:
650 72737a7f Iustin Pop
      return result
651 a8083063 Iustin Pop
652 72737a7f Iustin Pop
  def call_hooks_runner(self, node_list, hpath, phase, env):
653 72737a7f Iustin Pop
    """Call the hooks runner.
654 a8083063 Iustin Pop

655 72737a7f Iustin Pop
    Args:
656 72737a7f Iustin Pop
      - op: the OpCode instance
657 72737a7f Iustin Pop
      - env: a dictionary with the environment
658 a8083063 Iustin Pop

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

661 72737a7f Iustin Pop
    """
662 72737a7f Iustin Pop
    params = [hpath, phase, env]
663 72737a7f Iustin Pop
    c = Client("hooks_runner", params)
664 72737a7f Iustin Pop
    c.connect_list(node_list)
665 72737a7f Iustin Pop
    c.run()
666 72737a7f Iustin Pop
    result = c.getresult()
667 72737a7f Iustin Pop
    return result
668 a8083063 Iustin Pop
669 72737a7f Iustin Pop
  def call_iallocator_runner(self, node, name, idata):
670 72737a7f Iustin Pop
    """Call an iallocator on a remote node
671 8d528b7c Iustin Pop

672 72737a7f Iustin Pop
    Args:
673 72737a7f Iustin Pop
      - name: the iallocator name
674 72737a7f Iustin Pop
      - input: the json-encoded input string
675 8d528b7c Iustin Pop

676 72737a7f Iustin Pop
    This is a single-node call.
677 8d528b7c Iustin Pop

678 72737a7f Iustin Pop
    """
679 72737a7f Iustin Pop
    params = [name, idata]
680 72737a7f Iustin Pop
    c = Client("iallocator_runner", params)
681 72737a7f Iustin Pop
    c.connect(node)
682 72737a7f Iustin Pop
    c.run()
683 72737a7f Iustin Pop
    result = c.getresult().get(node, False)
684 72737a7f Iustin Pop
    return result
685 8d528b7c Iustin Pop
686 72737a7f Iustin Pop
  def call_blockdev_grow(self, node, cf_bdev, amount):
687 72737a7f Iustin Pop
    """Request a snapshot of the given block device.
688 4c8ba8b3 Iustin Pop

689 72737a7f Iustin Pop
    This is a single-node call.
690 4c8ba8b3 Iustin Pop

691 72737a7f Iustin Pop
    """
692 72737a7f Iustin Pop
    c = Client("blockdev_grow", [cf_bdev.ToDict(), amount])
693 72737a7f Iustin Pop
    c.connect(node)
694 72737a7f Iustin Pop
    c.run()
695 72737a7f Iustin Pop
    return c.getresult().get(node, False)
696 4c8ba8b3 Iustin Pop
697 72737a7f Iustin Pop
  def call_blockdev_snapshot(self, node, cf_bdev):
698 72737a7f Iustin Pop
    """Request a snapshot of the given block device.
699 a8083063 Iustin Pop

700 72737a7f Iustin Pop
    This is a single-node call.
701 a8083063 Iustin Pop

702 72737a7f Iustin Pop
    """
703 72737a7f Iustin Pop
    c = Client("blockdev_snapshot", [cf_bdev.ToDict()])
704 72737a7f Iustin Pop
    c.connect(node)
705 72737a7f Iustin Pop
    c.run()
706 72737a7f Iustin Pop
    return c.getresult().get(node, False)
707 a8083063 Iustin Pop
708 72737a7f Iustin Pop
  def call_snapshot_export(self, node, snap_bdev, dest_node, instance,
709 72737a7f Iustin Pop
                           cluster_name):
710 72737a7f Iustin Pop
    """Request the export of a given snapshot.
711 a8083063 Iustin Pop

712 72737a7f Iustin Pop
    This is a single-node call.
713 a8083063 Iustin Pop

714 72737a7f Iustin Pop
    """
715 26ba2bd8 Iustin Pop
    params = [snap_bdev.ToDict(), dest_node,
716 26ba2bd8 Iustin Pop
              self._InstDict(instance), cluster_name]
717 72737a7f Iustin Pop
    c = Client("snapshot_export", params)
718 72737a7f Iustin Pop
    c.connect(node)
719 72737a7f Iustin Pop
    c.run()
720 72737a7f Iustin Pop
    return c.getresult().get(node, False)
721 a8083063 Iustin Pop
722 72737a7f Iustin Pop
  def call_finalize_export(self, node, instance, snap_disks):
723 72737a7f Iustin Pop
    """Request the completion of an export operation.
724 a8083063 Iustin Pop

725 72737a7f Iustin Pop
    This writes the export config file, etc.
726 a8083063 Iustin Pop

727 72737a7f Iustin Pop
    This is a single-node call.
728 a8083063 Iustin Pop

729 72737a7f Iustin Pop
    """
730 72737a7f Iustin Pop
    flat_disks = []
731 72737a7f Iustin Pop
    for disk in snap_disks:
732 72737a7f Iustin Pop
      flat_disks.append(disk.ToDict())
733 26ba2bd8 Iustin Pop
    params = [self._InstDict(instance), flat_disks]
734 72737a7f Iustin Pop
    c = Client("finalize_export", params)
735 72737a7f Iustin Pop
    c.connect(node)
736 72737a7f Iustin Pop
    c.run()
737 72737a7f Iustin Pop
    return c.getresult().get(node, False)
738 a8083063 Iustin Pop
739 72737a7f Iustin Pop
  def call_export_info(self, node, path):
740 72737a7f Iustin Pop
    """Queries the export information in a given path.
741 a8083063 Iustin Pop

742 72737a7f Iustin Pop
    This is a single-node call.
743 a8083063 Iustin Pop

744 72737a7f Iustin Pop
    """
745 72737a7f Iustin Pop
    c = Client("export_info", [path])
746 72737a7f Iustin Pop
    c.connect(node)
747 72737a7f Iustin Pop
    c.run()
748 72737a7f Iustin Pop
    result = c.getresult().get(node, False)
749 72737a7f Iustin Pop
    if not result:
750 72737a7f Iustin Pop
      return result
751 72737a7f Iustin Pop
    return objects.SerializableConfigParser.Loads(str(result))
752 a8083063 Iustin Pop
753 72737a7f Iustin Pop
  def call_instance_os_import(self, node, inst, osdev, swapdev,
754 72737a7f Iustin Pop
                              src_node, src_image, cluster_name):
755 72737a7f Iustin Pop
    """Request the import of a backup into an instance.
756 a8083063 Iustin Pop

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

759 72737a7f Iustin Pop
    """
760 26ba2bd8 Iustin Pop
    params = [self._InstDict(inst), osdev, swapdev,
761 26ba2bd8 Iustin Pop
              src_node, src_image, cluster_name]
762 72737a7f Iustin Pop
    c = Client("instance_os_import", params)
763 72737a7f Iustin Pop
    c.connect(node)
764 72737a7f Iustin Pop
    c.run()
765 72737a7f Iustin Pop
    return c.getresult().get(node, False)
766 a8083063 Iustin Pop
767 72737a7f Iustin Pop
  def call_export_list(self, node_list):
768 72737a7f Iustin Pop
    """Gets the stored exports list.
769 a8083063 Iustin Pop

770 72737a7f Iustin Pop
    This is a multi-node call.
771 a8083063 Iustin Pop

772 72737a7f Iustin Pop
    """
773 72737a7f Iustin Pop
    c = Client("export_list", [])
774 72737a7f Iustin Pop
    c.connect_list(node_list)
775 72737a7f Iustin Pop
    c.run()
776 72737a7f Iustin Pop
    result = c.getresult()
777 72737a7f Iustin Pop
    return result
778 a8083063 Iustin Pop
779 72737a7f Iustin Pop
  def call_export_remove(self, node, export):
780 72737a7f Iustin Pop
    """Requests removal of a given export.
781 a8083063 Iustin Pop

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

784 72737a7f Iustin Pop
    """
785 72737a7f Iustin Pop
    c = Client("export_remove", [export])
786 72737a7f Iustin Pop
    c.connect(node)
787 72737a7f Iustin Pop
    c.run()
788 72737a7f Iustin Pop
    return c.getresult().get(node, False)
789 a8083063 Iustin Pop
790 15396f60 Michael Hanselmann
  @staticmethod
791 15396f60 Michael Hanselmann
  def call_node_leave_cluster(node):
792 72737a7f Iustin Pop
    """Requests a node to clean the cluster information it has.
793 a8083063 Iustin Pop

794 72737a7f Iustin Pop
    This will remove the configuration information from the ganeti data
795 72737a7f Iustin Pop
    dir.
796 a8083063 Iustin Pop

797 72737a7f Iustin Pop
    This is a single-node call.
798 a8083063 Iustin Pop

799 72737a7f Iustin Pop
    """
800 72737a7f Iustin Pop
    c = Client("node_leave_cluster", [])
801 72737a7f Iustin Pop
    c.connect(node)
802 72737a7f Iustin Pop
    c.run()
803 72737a7f Iustin Pop
    return c.getresult().get(node, False)
804 dcb93971 Michael Hanselmann
805 72737a7f Iustin Pop
  def call_node_volumes(self, node_list):
806 72737a7f Iustin Pop
    """Gets all volumes on node(s).
807 dcb93971 Michael Hanselmann

808 72737a7f Iustin Pop
    This is a multi-node call.
809 dcb93971 Michael Hanselmann

810 72737a7f Iustin Pop
    """
811 72737a7f Iustin Pop
    c = Client("node_volumes", [])
812 72737a7f Iustin Pop
    c.connect_list(node_list)
813 72737a7f Iustin Pop
    c.run()
814 72737a7f Iustin Pop
    return c.getresult()
815 06009e27 Iustin Pop
816 72737a7f Iustin Pop
  def call_test_delay(self, node_list, duration):
817 72737a7f Iustin Pop
    """Sleep for a fixed time on given node(s).
818 06009e27 Iustin Pop

819 72737a7f Iustin Pop
    This is a multi-node call.
820 06009e27 Iustin Pop

821 72737a7f Iustin Pop
    """
822 72737a7f Iustin Pop
    c = Client("test_delay", [duration])
823 72737a7f Iustin Pop
    c.connect_list(node_list)
824 72737a7f Iustin Pop
    c.run()
825 72737a7f Iustin Pop
    return c.getresult()
826 5e04ed8b Manuel Franceschini
827 72737a7f Iustin Pop
  def call_file_storage_dir_create(self, node, file_storage_dir):
828 72737a7f Iustin Pop
    """Create the given file storage directory.
829 5e04ed8b Manuel Franceschini

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

832 72737a7f Iustin Pop
    """
833 72737a7f Iustin Pop
    c = Client("file_storage_dir_create", [file_storage_dir])
834 72737a7f Iustin Pop
    c.connect(node)
835 72737a7f Iustin Pop
    c.run()
836 72737a7f Iustin Pop
    return c.getresult().get(node, False)
837 5e04ed8b Manuel Franceschini
838 72737a7f Iustin Pop
  def call_file_storage_dir_remove(self, node, file_storage_dir):
839 72737a7f Iustin Pop
    """Remove the given file storage directory.
840 5e04ed8b Manuel Franceschini

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

843 72737a7f Iustin Pop
    """
844 72737a7f Iustin Pop
    c = Client("file_storage_dir_remove", [file_storage_dir])
845 72737a7f Iustin Pop
    c.connect(node)
846 72737a7f Iustin Pop
    c.run()
847 72737a7f Iustin Pop
    return c.getresult().get(node, False)
848 5e04ed8b Manuel Franceschini
849 72737a7f Iustin Pop
  def call_file_storage_dir_rename(self, node, old_file_storage_dir,
850 72737a7f Iustin Pop
                                   new_file_storage_dir):
851 72737a7f Iustin Pop
    """Rename file storage directory.
852 5e04ed8b Manuel Franceschini

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

855 72737a7f Iustin Pop
    """
856 72737a7f Iustin Pop
    c = Client("file_storage_dir_rename",
857 72737a7f Iustin Pop
               [old_file_storage_dir, new_file_storage_dir])
858 72737a7f Iustin Pop
    c.connect(node)
859 72737a7f Iustin Pop
    c.run()
860 72737a7f Iustin Pop
    return c.getresult().get(node, False)
861 ca52cdeb Michael Hanselmann
862 72737a7f Iustin Pop
  @staticmethod
863 72737a7f Iustin Pop
  def call_jobqueue_update(node_list, file_name, content):
864 72737a7f Iustin Pop
    """Update job queue.
865 ca52cdeb Michael Hanselmann

866 72737a7f Iustin Pop
    This is a multi-node call.
867 ca52cdeb Michael Hanselmann

868 72737a7f Iustin Pop
    """
869 72737a7f Iustin Pop
    c = Client("jobqueue_update", [file_name, content])
870 72737a7f Iustin Pop
    c.connect_list(node_list)
871 72737a7f Iustin Pop
    c.run()
872 72737a7f Iustin Pop
    result = c.getresult()
873 72737a7f Iustin Pop
    return result
874 ca52cdeb Michael Hanselmann
875 72737a7f Iustin Pop
  @staticmethod
876 72737a7f Iustin Pop
  def call_jobqueue_purge(node):
877 72737a7f Iustin Pop
    """Purge job queue.
878 ca52cdeb Michael Hanselmann

879 72737a7f Iustin Pop
    This is a single-node call.
880 ca52cdeb Michael Hanselmann

881 72737a7f Iustin Pop
    """
882 72737a7f Iustin Pop
    c = Client("jobqueue_purge", [])
883 72737a7f Iustin Pop
    c.connect(node)
884 72737a7f Iustin Pop
    c.run()
885 72737a7f Iustin Pop
    return c.getresult().get(node, False)
886 af5ebcb1 Michael Hanselmann
887 72737a7f Iustin Pop
  @staticmethod
888 72737a7f Iustin Pop
  def call_jobqueue_rename(node_list, old, new):
889 72737a7f Iustin Pop
    """Rename a job queue file.
890 af5ebcb1 Michael Hanselmann

891 72737a7f Iustin Pop
    This is a multi-node call.
892 af5ebcb1 Michael Hanselmann

893 72737a7f Iustin Pop
    """
894 72737a7f Iustin Pop
    c = Client("jobqueue_rename", [old, new])
895 72737a7f Iustin Pop
    c.connect_list(node_list)
896 72737a7f Iustin Pop
    c.run()
897 72737a7f Iustin Pop
    result = c.getresult()
898 72737a7f Iustin Pop
    return result
899 6217e295 Iustin Pop
900 6217e295 Iustin Pop
901 6217e295 Iustin Pop
  def call_hypervisor_validate_params(self, node_list, hvname, hvparams):
902 6217e295 Iustin Pop
    """Validate the hypervisor params.
903 6217e295 Iustin Pop

904 6217e295 Iustin Pop
    This is a multi-node call.
905 6217e295 Iustin Pop

906 6217e295 Iustin Pop
    @type node_list: list
907 6217e295 Iustin Pop
    @param node_list: the list of nodes to query
908 6217e295 Iustin Pop
    @type hvname: string
909 6217e295 Iustin Pop
    @param hvname: the hypervisor name
910 6217e295 Iustin Pop
    @type hvparams: dict
911 6217e295 Iustin Pop
    @param hvparams: the hypervisor parameters to be validated
912 6217e295 Iustin Pop

913 6217e295 Iustin Pop
    """
914 6217e295 Iustin Pop
    cluster = self._cfg.GetClusterInfo()
915 6217e295 Iustin Pop
    hv_full = cluster.FillDict(cluster.hvparams.get(hvname, {}), hvparams)
916 6217e295 Iustin Pop
    c = Client("hypervisor_validate_params", [hvname, hv_full])
917 6217e295 Iustin Pop
    c.connect_list(node_list)
918 6217e295 Iustin Pop
    c.run()
919 6217e295 Iustin Pop
    result = c.getresult()
920 6217e295 Iustin Pop
    return result