Statistics
| Branch: | Tag: | Revision:

root / lib / rpc.py @ 686d7433

History | View | Annotate | Download (23.5 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 5b442704 Iustin Pop
    cluster = self._cfg.GetClusterInfo()
176 5b442704 Iustin Pop
    idict["hvparams"] = cluster.FillHV(instance)
177 5b442704 Iustin Pop
    idict["beparams"] = cluster.FillBE(instance)
178 26ba2bd8 Iustin Pop
    return idict
179 26ba2bd8 Iustin Pop
180 72737a7f Iustin Pop
  def call_volume_list(self, node_list, vg_name):
181 72737a7f Iustin Pop
    """Gets the logical volumes present in a given volume group.
182 a8083063 Iustin Pop

183 72737a7f Iustin Pop
    This is a multi-node call.
184 a8083063 Iustin Pop

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

194 72737a7f Iustin Pop
    This is a multi-node call.
195 a8083063 Iustin Pop

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

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

209 72737a7f Iustin Pop
    This is a single-node call.
210 a8083063 Iustin Pop

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

220 72737a7f Iustin Pop
    This is a single-node call.
221 a8083063 Iustin Pop

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

231 72737a7f Iustin Pop
    This is a single-node call.
232 2a10865c Iustin Pop

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

242 72737a7f Iustin Pop
    This is a single-node call.
243 2a10865c Iustin Pop

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

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

263 72737a7f Iustin Pop
    This is a single-node call.
264 a8083063 Iustin Pop

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

275 72737a7f Iustin Pop
    This is a single-node call.
276 decd5f45 Iustin Pop

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

287 72737a7f Iustin Pop
    This is a single-node call.
288 a8083063 Iustin Pop

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

299 72737a7f Iustin Pop
    This is a single-node call.
300 a8083063 Iustin Pop

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

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

317 72737a7f Iustin Pop
    This is a multi-node call.
318 a8083063 Iustin Pop

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

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

333 72737a7f Iustin Pop
    This is a multi-node call.
334 a8083063 Iustin Pop

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

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

350 72737a7f Iustin Pop
    This is a single-node call.
351 caad16e2 Iustin Pop

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

362 caad16e2 Iustin Pop
    This is a single-node call.
363 caad16e2 Iustin Pop

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

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

376 72737a7f Iustin Pop
    This is a multi-node call.
377 a8083063 Iustin Pop

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

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

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

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

424 72737a7f Iustin Pop
    This is a multi-node call.
425 a8083063 Iustin Pop

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

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

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

448 72737a7f Iustin Pop
    This is a single-node call.
449 4e071d3b Iustin Pop

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

460 72737a7f Iustin Pop
    This is a multi-node call.
461 a8083063 Iustin Pop

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

472 72737a7f Iustin Pop
    This is a multi-node call.
473 a8083063 Iustin Pop

474 72737a7f Iustin Pop
    """
475 72737a7f Iustin Pop
    c = Client("version", [])
476 72737a7f Iustin Pop
    c.connect_list(node_list)
477 72737a7f Iustin Pop
    c.run()
478 72737a7f Iustin Pop
    return c.getresult()
479 a8083063 Iustin Pop
480 72737a7f Iustin Pop
  def call_blockdev_create(self, node, bdev, size, owner, on_primary, info):
481 72737a7f Iustin Pop
    """Request creation of a given block device.
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 = [bdev.ToDict(), size, owner, on_primary, info]
487 72737a7f Iustin Pop
    c = Client("blockdev_create", params)
488 72737a7f Iustin Pop
    c.connect(node)
489 72737a7f Iustin Pop
    c.run()
490 72737a7f Iustin Pop
    return c.getresult().get(node, False)
491 a8083063 Iustin Pop
492 72737a7f Iustin Pop
  def call_blockdev_remove(self, node, bdev):
493 72737a7f Iustin Pop
    """Request removal of a given block device.
494 a8083063 Iustin Pop

495 72737a7f Iustin Pop
    This is a single-node call.
496 f3e513ad Iustin Pop

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

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

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

518 72737a7f Iustin Pop
    This is a single-node call.
519 a8083063 Iustin Pop

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

530 72737a7f Iustin Pop
    This is a single-node call.
531 a8083063 Iustin Pop

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

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

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

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

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

565 72737a7f Iustin Pop
    This is a single-node call.
566 a8083063 Iustin Pop

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

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

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

588 72737a7f Iustin Pop
    This is a single-node call.
589 d61cbe76 Iustin Pop

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

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

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

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

623 72737a7f Iustin Pop
    This is a multi-node call.
624 a8083063 Iustin Pop

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

642 72737a7f Iustin Pop
    This is a single-node call.
643 a8083063 Iustin Pop

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

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

661 72737a7f Iustin Pop
    This is a multi-node call.
662 a8083063 Iustin Pop

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

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

678 72737a7f Iustin Pop
    This is a single-node call.
679 8d528b7c Iustin Pop

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

691 72737a7f Iustin Pop
    This is a single-node call.
692 4c8ba8b3 Iustin Pop

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

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

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

714 72737a7f Iustin Pop
    This is a single-node call.
715 a8083063 Iustin Pop

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

727 72737a7f Iustin Pop
    This writes the export config file, etc.
728 a8083063 Iustin Pop

729 72737a7f Iustin Pop
    This is a single-node call.
730 a8083063 Iustin Pop

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

744 72737a7f Iustin Pop
    This is a single-node call.
745 a8083063 Iustin Pop

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

759 72737a7f Iustin Pop
    This is a single-node call.
760 a8083063 Iustin Pop

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

772 72737a7f Iustin Pop
    This is a multi-node call.
773 a8083063 Iustin Pop

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

784 72737a7f Iustin Pop
    This is a single-node call.
785 a8083063 Iustin Pop

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

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

799 72737a7f Iustin Pop
    This is a single-node call.
800 a8083063 Iustin Pop

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

810 72737a7f Iustin Pop
    This is a multi-node call.
811 dcb93971 Michael Hanselmann

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

821 72737a7f Iustin Pop
    This is a multi-node call.
822 06009e27 Iustin Pop

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

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

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

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

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

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

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

868 72737a7f Iustin Pop
    This is a multi-node call.
869 ca52cdeb Michael Hanselmann

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

881 72737a7f Iustin Pop
    This is a single-node call.
882 ca52cdeb Michael Hanselmann

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

893 72737a7f Iustin Pop
    This is a multi-node call.
894 af5ebcb1 Michael Hanselmann

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

906 6217e295 Iustin Pop
    This is a multi-node call.
907 6217e295 Iustin Pop

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

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