Statistics
| Branch: | Tag: | Revision:

root / lib / rpc.py @ 72737a7f

History | View | Annotate | Download (22.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 72737a7f Iustin Pop
  def call_volume_list(self, node_list, vg_name):
162 72737a7f Iustin Pop
    """Gets the logical volumes present in a given volume group.
163 a8083063 Iustin Pop

164 72737a7f Iustin Pop
    This is a multi-node call.
165 a8083063 Iustin Pop

166 72737a7f Iustin Pop
    """
167 72737a7f Iustin Pop
    c = Client("volume_list", [vg_name])
168 72737a7f Iustin Pop
    c.connect_list(node_list)
169 72737a7f Iustin Pop
    c.run()
170 72737a7f Iustin Pop
    return c.getresult()
171 a8083063 Iustin Pop
172 72737a7f Iustin Pop
  def call_vg_list(self, node_list):
173 72737a7f Iustin Pop
    """Gets the volume group list.
174 a8083063 Iustin Pop

175 72737a7f Iustin Pop
    This is a multi-node call.
176 a8083063 Iustin Pop

177 72737a7f Iustin Pop
    """
178 72737a7f Iustin Pop
    c = Client("vg_list", [])
179 72737a7f Iustin Pop
    c.connect_list(node_list)
180 72737a7f Iustin Pop
    c.run()
181 72737a7f Iustin Pop
    return c.getresult()
182 a8083063 Iustin Pop
183 a8083063 Iustin Pop
184 72737a7f Iustin Pop
  def call_bridges_exist(self, node, bridges_list):
185 72737a7f Iustin Pop
    """Checks if a node has all the bridges given.
186 a8083063 Iustin Pop

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

191 72737a7f Iustin Pop
    This is a single-node call.
192 a8083063 Iustin Pop

193 72737a7f Iustin Pop
    """
194 72737a7f Iustin Pop
    c = Client("bridges_exist", [bridges_list])
195 72737a7f Iustin Pop
    c.connect(node)
196 72737a7f Iustin Pop
    c.run()
197 72737a7f Iustin Pop
    return c.getresult().get(node, False)
198 a8083063 Iustin Pop
199 a8083063 Iustin Pop
200 72737a7f Iustin Pop
  def call_instance_start(self, node, instance, extra_args):
201 72737a7f Iustin Pop
    """Starts an instance.
202 a8083063 Iustin Pop

203 72737a7f Iustin Pop
    This is a single-node call.
204 a8083063 Iustin Pop

205 72737a7f Iustin Pop
    """
206 72737a7f Iustin Pop
    c = Client("instance_start", [instance.ToDict(), extra_args])
207 72737a7f Iustin Pop
    c.connect(node)
208 72737a7f Iustin Pop
    c.run()
209 72737a7f Iustin Pop
    return c.getresult().get(node, False)
210 a8083063 Iustin Pop
211 a8083063 Iustin Pop
212 72737a7f Iustin Pop
  def call_instance_shutdown(self, node, instance):
213 72737a7f Iustin Pop
    """Stops an instance.
214 a8083063 Iustin Pop

215 72737a7f Iustin Pop
    This is a single-node call.
216 2a10865c Iustin Pop

217 72737a7f Iustin Pop
    """
218 72737a7f Iustin Pop
    c = Client("instance_shutdown", [instance.ToDict()])
219 72737a7f Iustin Pop
    c.connect(node)
220 72737a7f Iustin Pop
    c.run()
221 72737a7f Iustin Pop
    return c.getresult().get(node, False)
222 2a10865c Iustin Pop
223 9f0e6b37 Iustin Pop
224 72737a7f Iustin Pop
  def call_instance_migrate(self, node, instance, target, live):
225 72737a7f Iustin Pop
    """Migrate an instance.
226 2a10865c Iustin Pop

227 72737a7f Iustin Pop
    This is a single-node call.
228 2a10865c Iustin Pop

229 72737a7f Iustin Pop
    @type node: string
230 72737a7f Iustin Pop
    @param node: the node on which the instance is currently running
231 72737a7f Iustin Pop
    @type instance: C{objects.Instance}
232 72737a7f Iustin Pop
    @param instance: the instance definition
233 72737a7f Iustin Pop
    @type target: string
234 72737a7f Iustin Pop
    @param target: the target node name
235 72737a7f Iustin Pop
    @type live: boolean
236 72737a7f Iustin Pop
    @param live: whether the migration should be done live or not (the
237 72737a7f Iustin Pop
        interpretation of this parameter is left to the hypervisor)
238 007a2f3e Alexander Schreiber

239 72737a7f Iustin Pop
    """
240 72737a7f Iustin Pop
    c = Client("instance_migrate", [instance.ToDict(), target, live])
241 72737a7f Iustin Pop
    c.connect(node)
242 72737a7f Iustin Pop
    c.run()
243 72737a7f Iustin Pop
    return c.getresult().get(node, False)
244 007a2f3e Alexander Schreiber
245 007a2f3e Alexander Schreiber
246 72737a7f Iustin Pop
  def call_instance_reboot(self, node, instance, reboot_type, extra_args):
247 72737a7f Iustin Pop
    """Reboots an instance.
248 007a2f3e Alexander Schreiber

249 72737a7f Iustin Pop
    This is a single-node call.
250 a8083063 Iustin Pop

251 72737a7f Iustin Pop
    """
252 72737a7f Iustin Pop
    c = Client("instance_reboot", [instance.ToDict(), reboot_type, extra_args])
253 72737a7f Iustin Pop
    c.connect(node)
254 72737a7f Iustin Pop
    c.run()
255 72737a7f Iustin Pop
    return c.getresult().get(node, False)
256 a8083063 Iustin Pop
257 a8083063 Iustin Pop
258 72737a7f Iustin Pop
  def call_instance_os_add(self, node, inst, osdev, swapdev):
259 72737a7f Iustin Pop
    """Installs an OS on the given instance.
260 a8083063 Iustin Pop

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

263 72737a7f Iustin Pop
    """
264 72737a7f Iustin Pop
    params = [inst.ToDict(), osdev, swapdev]
265 72737a7f Iustin Pop
    c = Client("instance_os_add", params)
266 72737a7f Iustin Pop
    c.connect(node)
267 72737a7f Iustin Pop
    c.run()
268 72737a7f Iustin Pop
    return c.getresult().get(node, False)
269 decd5f45 Iustin Pop
270 decd5f45 Iustin Pop
271 72737a7f Iustin Pop
  def call_instance_run_rename(self, node, inst, old_name, osdev, swapdev):
272 72737a7f Iustin Pop
    """Run the OS rename script for an instance.
273 decd5f45 Iustin Pop

274 72737a7f Iustin Pop
    This is a single-node call.
275 a8083063 Iustin Pop

276 72737a7f Iustin Pop
    """
277 72737a7f Iustin Pop
    params = [inst.ToDict(), old_name, osdev, swapdev]
278 72737a7f Iustin Pop
    c = Client("instance_run_rename", params)
279 72737a7f Iustin Pop
    c.connect(node)
280 72737a7f Iustin Pop
    c.run()
281 72737a7f Iustin Pop
    return c.getresult().get(node, False)
282 a8083063 Iustin Pop
283 e69d05fd Iustin Pop
284 72737a7f Iustin Pop
  def call_instance_info(self, node, instance, hname):
285 72737a7f Iustin Pop
    """Returns information about a single instance.
286 a8083063 Iustin Pop

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

289 72737a7f Iustin Pop
    @type node_list: list
290 72737a7f Iustin Pop
    @param node_list: the list of nodes to query
291 72737a7f Iustin Pop
    @type instance: string
292 72737a7f Iustin Pop
    @param instance: the instance name
293 72737a7f Iustin Pop
    @type hname: string
294 72737a7f Iustin Pop
    @param hname: the hypervisor type of the instance
295 a8083063 Iustin Pop

296 72737a7f Iustin Pop
    """
297 72737a7f Iustin Pop
    c = Client("instance_info", [instance])
298 72737a7f Iustin Pop
    c.connect(node)
299 72737a7f Iustin Pop
    c.run()
300 72737a7f Iustin Pop
    return c.getresult().get(node, False)
301 e69d05fd Iustin Pop
302 a8083063 Iustin Pop
303 72737a7f Iustin Pop
  def call_all_instances_info(self, node_list, hypervisor_list):
304 72737a7f Iustin Pop
    """Returns information about all instances on the given nodes.
305 a8083063 Iustin Pop

306 72737a7f Iustin Pop
    This is a multi-node call.
307 a8083063 Iustin Pop

308 72737a7f Iustin Pop
    @type node_list: list
309 72737a7f Iustin Pop
    @param node_list: the list of nodes to query
310 72737a7f Iustin Pop
    @type hypervisor_list: list
311 72737a7f Iustin Pop
    @param hypervisor_list: the hypervisors to query for instances
312 a8083063 Iustin Pop

313 72737a7f Iustin Pop
    """
314 72737a7f Iustin Pop
    c = Client("all_instances_info", [hypervisor_list])
315 72737a7f Iustin Pop
    c.connect_list(node_list)
316 72737a7f Iustin Pop
    c.run()
317 72737a7f Iustin Pop
    return c.getresult()
318 e69d05fd Iustin Pop
319 a8083063 Iustin Pop
320 72737a7f Iustin Pop
  def call_instance_list(self, node_list, hypervisor_list):
321 72737a7f Iustin Pop
    """Returns the list of running instances on a given node.
322 a8083063 Iustin Pop

323 72737a7f Iustin Pop
    This is a multi-node call.
324 a8083063 Iustin Pop

325 72737a7f Iustin Pop
    @type node_list: list
326 72737a7f Iustin Pop
    @param node_list: the list of nodes to query
327 72737a7f Iustin Pop
    @type hypervisor_list: list
328 72737a7f Iustin Pop
    @param hypervisor_list: the hypervisors to query for instances
329 16abfbc2 Alexander Schreiber

330 72737a7f Iustin Pop
    """
331 72737a7f Iustin Pop
    c = Client("instance_list", [hypervisor_list])
332 72737a7f Iustin Pop
    c.connect_list(node_list)
333 72737a7f Iustin Pop
    c.run()
334 72737a7f Iustin Pop
    return c.getresult()
335 16abfbc2 Alexander Schreiber
336 16abfbc2 Alexander Schreiber
337 72737a7f Iustin Pop
  def call_node_tcp_ping(self, node, source, target, port, timeout,
338 72737a7f Iustin Pop
                         live_port_needed):
339 72737a7f Iustin Pop
    """Do a TcpPing on the remote node
340 a8083063 Iustin Pop

341 72737a7f Iustin Pop
    This is a single-node call.
342 72737a7f Iustin Pop
    """
343 72737a7f Iustin Pop
    c = Client("node_tcp_ping", [source, target, port, timeout,
344 72737a7f Iustin Pop
                                 live_port_needed])
345 72737a7f Iustin Pop
    c.connect(node)
346 72737a7f Iustin Pop
    c.run()
347 72737a7f Iustin Pop
    return c.getresult().get(node, False)
348 a8083063 Iustin Pop
349 a8083063 Iustin Pop
350 72737a7f Iustin Pop
  def call_node_info(self, node_list, vg_name, hypervisor_type):
351 72737a7f Iustin Pop
    """Return node information.
352 e69d05fd Iustin Pop

353 72737a7f Iustin Pop
    This will return memory information and volume group size and free
354 72737a7f Iustin Pop
    space.
355 a8083063 Iustin Pop

356 72737a7f Iustin Pop
    This is a multi-node call.
357 a8083063 Iustin Pop

358 72737a7f Iustin Pop
    @type node_list: list
359 72737a7f Iustin Pop
    @param node_list: the list of nodes to query
360 72737a7f Iustin Pop
    @type vgname: C{string}
361 72737a7f Iustin Pop
    @param vgname: the name of the volume group to ask for disk space
362 72737a7f Iustin Pop
        information
363 72737a7f Iustin Pop
    @type hypervisor_type: C{str}
364 72737a7f Iustin Pop
    @param hypervisor_type: the name of the hypervisor to ask for
365 72737a7f Iustin Pop
        memory information
366 a8083063 Iustin Pop

367 72737a7f Iustin Pop
    """
368 72737a7f Iustin Pop
    c = Client("node_info", [vg_name, hypervisor_type])
369 72737a7f Iustin Pop
    c.connect_list(node_list)
370 72737a7f Iustin Pop
    c.run()
371 72737a7f Iustin Pop
    retux = c.getresult()
372 a8083063 Iustin Pop
373 72737a7f Iustin Pop
    for node_name in retux:
374 72737a7f Iustin Pop
      ret = retux.get(node_name, False)
375 72737a7f Iustin Pop
      if type(ret) != dict:
376 72737a7f Iustin Pop
        logger.Error("could not connect to node %s" % (node_name))
377 72737a7f Iustin Pop
        ret = {}
378 a8083063 Iustin Pop
379 72737a7f Iustin Pop
      utils.CheckDict(ret,
380 72737a7f Iustin Pop
                      { 'memory_total' : '-',
381 72737a7f Iustin Pop
                        'memory_dom0' : '-',
382 72737a7f Iustin Pop
                        'memory_free' : '-',
383 72737a7f Iustin Pop
                        'vg_size' : 'node_unreachable',
384 72737a7f Iustin Pop
                        'vg_free' : '-' },
385 72737a7f Iustin Pop
                      "call_node_info",
386 72737a7f Iustin Pop
                      )
387 72737a7f Iustin Pop
    return retux
388 a8083063 Iustin Pop
389 a8083063 Iustin Pop
390 72737a7f Iustin Pop
  def call_node_add(self, node, dsa, dsapub, rsa, rsapub, ssh, sshpub):
391 72737a7f Iustin Pop
    """Add a node to the cluster.
392 a8083063 Iustin Pop

393 72737a7f Iustin Pop
    This is a single-node call.
394 a8083063 Iustin Pop

395 72737a7f Iustin Pop
    """
396 72737a7f Iustin Pop
    params = [dsa, dsapub, rsa, rsapub, ssh, sshpub]
397 72737a7f Iustin Pop
    c = Client("node_add", params)
398 72737a7f Iustin Pop
    c.connect(node)
399 72737a7f Iustin Pop
    c.run()
400 72737a7f Iustin Pop
    return c.getresult().get(node, False)
401 a8083063 Iustin Pop
402 a8083063 Iustin Pop
403 72737a7f Iustin Pop
  def call_node_verify(self, node_list, checkdict, cluster_name):
404 72737a7f Iustin Pop
    """Request verification of given parameters.
405 a8083063 Iustin Pop

406 72737a7f Iustin Pop
    This is a multi-node call.
407 a8083063 Iustin Pop

408 72737a7f Iustin Pop
    """
409 72737a7f Iustin Pop
    c = Client("node_verify", [checkdict, cluster_name])
410 72737a7f Iustin Pop
    c.connect_list(node_list)
411 72737a7f Iustin Pop
    c.run()
412 72737a7f Iustin Pop
    return c.getresult()
413 a8083063 Iustin Pop
414 a8083063 Iustin Pop
415 72737a7f Iustin Pop
  @staticmethod
416 72737a7f Iustin Pop
  def call_node_start_master(node, start_daemons):
417 72737a7f Iustin Pop
    """Tells a node to activate itself as a master.
418 a8083063 Iustin Pop

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

421 72737a7f Iustin Pop
    """
422 72737a7f Iustin Pop
    c = Client("node_start_master", [start_daemons])
423 72737a7f Iustin Pop
    c.connect(node)
424 72737a7f Iustin Pop
    c.run()
425 72737a7f Iustin Pop
    return c.getresult().get(node, False)
426 a8083063 Iustin Pop
427 a8083063 Iustin Pop
428 72737a7f Iustin Pop
  @staticmethod
429 72737a7f Iustin Pop
  def call_node_stop_master(node, stop_daemons):
430 72737a7f Iustin Pop
    """Tells a node to demote itself from master status.
431 a8083063 Iustin Pop

432 72737a7f Iustin Pop
    This is a single-node call.
433 4e071d3b Iustin Pop

434 72737a7f Iustin Pop
    """
435 72737a7f Iustin Pop
    c = Client("node_stop_master", [stop_daemons])
436 72737a7f Iustin Pop
    c.connect(node)
437 72737a7f Iustin Pop
    c.run()
438 72737a7f Iustin Pop
    return c.getresult().get(node, False)
439 4e071d3b Iustin Pop
440 4e071d3b Iustin Pop
441 72737a7f Iustin Pop
  @staticmethod
442 72737a7f Iustin Pop
  def call_master_info(node_list):
443 72737a7f Iustin Pop
    """Query master info.
444 4e071d3b Iustin Pop

445 72737a7f Iustin Pop
    This is a multi-node call.
446 a8083063 Iustin Pop

447 72737a7f Iustin Pop
    """
448 72737a7f Iustin Pop
    # TODO: should this method query down nodes?
449 72737a7f Iustin Pop
    c = Client("master_info", [])
450 72737a7f Iustin Pop
    c.connect_list(node_list)
451 72737a7f Iustin Pop
    c.run()
452 72737a7f Iustin Pop
    return c.getresult()
453 a8083063 Iustin Pop
454 a8083063 Iustin Pop
455 72737a7f Iustin Pop
  def call_version(self, node_list):
456 72737a7f Iustin Pop
    """Query node version.
457 a8083063 Iustin Pop

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

460 72737a7f Iustin Pop
    """
461 72737a7f Iustin Pop
    c = Client("version", [])
462 72737a7f Iustin Pop
    c.connect_list(node_list)
463 72737a7f Iustin Pop
    c.run()
464 72737a7f Iustin Pop
    return c.getresult()
465 a8083063 Iustin Pop
466 a8083063 Iustin Pop
467 72737a7f Iustin Pop
  def call_blockdev_create(self, node, bdev, size, owner, on_primary, info):
468 72737a7f Iustin Pop
    """Request creation of a given block device.
469 a8083063 Iustin Pop

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

472 72737a7f Iustin Pop
    """
473 72737a7f Iustin Pop
    params = [bdev.ToDict(), size, owner, on_primary, info]
474 72737a7f Iustin Pop
    c = Client("blockdev_create", params)
475 72737a7f Iustin Pop
    c.connect(node)
476 72737a7f Iustin Pop
    c.run()
477 72737a7f Iustin Pop
    return c.getresult().get(node, False)
478 a8083063 Iustin Pop
479 a8083063 Iustin Pop
480 72737a7f Iustin Pop
  def call_blockdev_remove(self, node, bdev):
481 72737a7f Iustin Pop
    """Request removal of a given block device.
482 a8083063 Iustin Pop

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

485 72737a7f Iustin Pop
    """
486 72737a7f Iustin Pop
    c = Client("blockdev_remove", [bdev.ToDict()])
487 72737a7f Iustin Pop
    c.connect(node)
488 72737a7f Iustin Pop
    c.run()
489 72737a7f Iustin Pop
    return c.getresult().get(node, False)
490 f3e513ad Iustin Pop
491 f3e513ad Iustin Pop
492 72737a7f Iustin Pop
  def call_blockdev_rename(self, node, devlist):
493 72737a7f Iustin Pop
    """Request rename of the given block devices.
494 f3e513ad Iustin Pop

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

497 72737a7f Iustin Pop
    """
498 72737a7f Iustin Pop
    params = [(d.ToDict(), uid) for d, uid in devlist]
499 72737a7f Iustin Pop
    c = Client("blockdev_rename", params)
500 72737a7f Iustin Pop
    c.connect(node)
501 72737a7f Iustin Pop
    c.run()
502 72737a7f Iustin Pop
    return c.getresult().get(node, False)
503 a8083063 Iustin Pop
504 a8083063 Iustin Pop
505 72737a7f Iustin Pop
  def call_blockdev_assemble(self, node, disk, owner, on_primary):
506 72737a7f Iustin Pop
    """Request assembling of a given block device.
507 a8083063 Iustin Pop

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

510 72737a7f Iustin Pop
    """
511 72737a7f Iustin Pop
    params = [disk.ToDict(), owner, on_primary]
512 72737a7f Iustin Pop
    c = Client("blockdev_assemble", params)
513 72737a7f Iustin Pop
    c.connect(node)
514 72737a7f Iustin Pop
    c.run()
515 72737a7f Iustin Pop
    return c.getresult().get(node, False)
516 a8083063 Iustin Pop
517 a8083063 Iustin Pop
518 72737a7f Iustin Pop
  def call_blockdev_shutdown(self, node, disk):
519 72737a7f Iustin Pop
    """Request shutdown of a given block device.
520 a8083063 Iustin Pop

521 72737a7f Iustin Pop
    This is a single-node call.
522 a8083063 Iustin Pop

523 72737a7f Iustin Pop
    """
524 72737a7f Iustin Pop
    c = Client("blockdev_shutdown", [disk.ToDict()])
525 72737a7f Iustin Pop
    c.connect(node)
526 72737a7f Iustin Pop
    c.run()
527 72737a7f Iustin Pop
    return c.getresult().get(node, False)
528 a8083063 Iustin Pop
529 a8083063 Iustin Pop
530 72737a7f Iustin Pop
  def call_blockdev_addchildren(self, node, bdev, ndevs):
531 72737a7f Iustin Pop
    """Request adding a list of children to a (mirroring) device.
532 a8083063 Iustin Pop

533 72737a7f Iustin Pop
    This is a single-node call.
534 a8083063 Iustin Pop

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

546 72737a7f Iustin Pop
    This is a single-node call.
547 a8083063 Iustin Pop

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

559 72737a7f Iustin Pop
    This is a single-node call.
560 a8083063 Iustin Pop

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

572 72737a7f Iustin Pop
    This is a single-node call.
573 a8083063 Iustin Pop

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

584 72737a7f Iustin Pop
    This is a single-node call.
585 d61cbe76 Iustin Pop

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

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

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

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

621 72737a7f Iustin Pop
    The node will refuse the operation in case the file is not on the
622 72737a7f Iustin Pop
    approved file list.
623 72737a7f Iustin Pop

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

626 72737a7f Iustin Pop
    """
627 72737a7f Iustin Pop
    fh = file(file_name)
628 72737a7f Iustin Pop
    try:
629 72737a7f Iustin Pop
      data = fh.read()
630 72737a7f Iustin Pop
    finally:
631 72737a7f Iustin Pop
      fh.close()
632 72737a7f Iustin Pop
    st = os.stat(file_name)
633 72737a7f Iustin Pop
    params = [file_name, data, st.st_mode, st.st_uid, st.st_gid,
634 72737a7f Iustin Pop
              st.st_atime, st.st_mtime]
635 72737a7f Iustin Pop
    c = Client("upload_file", params)
636 72737a7f Iustin Pop
    c.connect_list(node_list)
637 72737a7f Iustin Pop
    c.run()
638 72737a7f Iustin Pop
    return c.getresult()
639 72737a7f Iustin Pop
640 72737a7f Iustin Pop
  def call_os_diagnose(self, node_list):
641 72737a7f Iustin Pop
    """Request a diagnose of OS definitions.
642 72737a7f Iustin Pop

643 72737a7f Iustin Pop
    This is a multi-node call.
644 a8083063 Iustin Pop

645 72737a7f Iustin Pop
    """
646 72737a7f Iustin Pop
    c = Client("os_diagnose", [])
647 72737a7f Iustin Pop
    c.connect_list(node_list)
648 72737a7f Iustin Pop
    c.run()
649 72737a7f Iustin Pop
    result = c.getresult()
650 72737a7f Iustin Pop
    new_result = {}
651 72737a7f Iustin Pop
    for node_name in result:
652 72737a7f Iustin Pop
      if result[node_name]:
653 72737a7f Iustin Pop
        nr = [objects.OS.FromDict(oss) for oss in result[node_name]]
654 72737a7f Iustin Pop
      else:
655 72737a7f Iustin Pop
        nr = []
656 72737a7f Iustin Pop
      new_result[node_name] = nr
657 72737a7f Iustin Pop
    return new_result
658 a8083063 Iustin Pop
659 a8083063 Iustin Pop
660 72737a7f Iustin Pop
  def call_os_get(self, node, name):
661 72737a7f Iustin Pop
    """Returns an OS definition.
662 a8083063 Iustin Pop

663 72737a7f Iustin Pop
    This is a single-node call.
664 a8083063 Iustin Pop

665 72737a7f Iustin Pop
    """
666 72737a7f Iustin Pop
    c = Client("os_get", [name])
667 72737a7f Iustin Pop
    c.connect(node)
668 72737a7f Iustin Pop
    c.run()
669 72737a7f Iustin Pop
    result = c.getresult().get(node, False)
670 72737a7f Iustin Pop
    if isinstance(result, dict):
671 72737a7f Iustin Pop
      return objects.OS.FromDict(result)
672 72737a7f Iustin Pop
    else:
673 72737a7f Iustin Pop
      return result
674 a8083063 Iustin Pop
675 a8083063 Iustin Pop
676 72737a7f Iustin Pop
  def call_hooks_runner(self, node_list, hpath, phase, env):
677 72737a7f Iustin Pop
    """Call the hooks runner.
678 a8083063 Iustin Pop

679 72737a7f Iustin Pop
    Args:
680 72737a7f Iustin Pop
      - op: the OpCode instance
681 72737a7f Iustin Pop
      - env: a dictionary with the environment
682 a8083063 Iustin Pop

683 72737a7f Iustin Pop
    This is a multi-node call.
684 a8083063 Iustin Pop

685 72737a7f Iustin Pop
    """
686 72737a7f Iustin Pop
    params = [hpath, phase, env]
687 72737a7f Iustin Pop
    c = Client("hooks_runner", params)
688 72737a7f Iustin Pop
    c.connect_list(node_list)
689 72737a7f Iustin Pop
    c.run()
690 72737a7f Iustin Pop
    result = c.getresult()
691 72737a7f Iustin Pop
    return result
692 a8083063 Iustin Pop
693 a8083063 Iustin Pop
694 72737a7f Iustin Pop
  def call_iallocator_runner(self, node, name, idata):
695 72737a7f Iustin Pop
    """Call an iallocator on a remote node
696 8d528b7c Iustin Pop

697 72737a7f Iustin Pop
    Args:
698 72737a7f Iustin Pop
      - name: the iallocator name
699 72737a7f Iustin Pop
      - input: the json-encoded input string
700 8d528b7c Iustin Pop

701 72737a7f Iustin Pop
    This is a single-node call.
702 8d528b7c Iustin Pop

703 72737a7f Iustin Pop
    """
704 72737a7f Iustin Pop
    params = [name, idata]
705 72737a7f Iustin Pop
    c = Client("iallocator_runner", params)
706 72737a7f Iustin Pop
    c.connect(node)
707 72737a7f Iustin Pop
    c.run()
708 72737a7f Iustin Pop
    result = c.getresult().get(node, False)
709 72737a7f Iustin Pop
    return result
710 8d528b7c Iustin Pop
711 8d528b7c Iustin Pop
712 72737a7f Iustin Pop
  def call_blockdev_grow(self, node, cf_bdev, amount):
713 72737a7f Iustin Pop
    """Request a snapshot of the given block device.
714 4c8ba8b3 Iustin Pop

715 72737a7f Iustin Pop
    This is a single-node call.
716 4c8ba8b3 Iustin Pop

717 72737a7f Iustin Pop
    """
718 72737a7f Iustin Pop
    c = Client("blockdev_grow", [cf_bdev.ToDict(), amount])
719 72737a7f Iustin Pop
    c.connect(node)
720 72737a7f Iustin Pop
    c.run()
721 72737a7f Iustin Pop
    return c.getresult().get(node, False)
722 4c8ba8b3 Iustin Pop
723 4c8ba8b3 Iustin Pop
724 72737a7f Iustin Pop
  def call_blockdev_snapshot(self, node, cf_bdev):
725 72737a7f Iustin Pop
    """Request a snapshot of the given block device.
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
    c = Client("blockdev_snapshot", [cf_bdev.ToDict()])
731 72737a7f Iustin Pop
    c.connect(node)
732 72737a7f Iustin Pop
    c.run()
733 72737a7f Iustin Pop
    return c.getresult().get(node, False)
734 a8083063 Iustin Pop
735 a8083063 Iustin Pop
736 72737a7f Iustin Pop
  def call_snapshot_export(self, node, snap_bdev, dest_node, instance,
737 72737a7f Iustin Pop
                           cluster_name):
738 72737a7f Iustin Pop
    """Request the export of a given snapshot.
739 a8083063 Iustin Pop

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

742 72737a7f Iustin Pop
    """
743 72737a7f Iustin Pop
    params = [snap_bdev.ToDict(), dest_node, instance.ToDict(), cluster_name]
744 72737a7f Iustin Pop
    c = Client("snapshot_export", params)
745 72737a7f Iustin Pop
    c.connect(node)
746 72737a7f Iustin Pop
    c.run()
747 72737a7f Iustin Pop
    return c.getresult().get(node, False)
748 a8083063 Iustin Pop
749 a8083063 Iustin Pop
750 72737a7f Iustin Pop
  def call_finalize_export(self, node, instance, snap_disks):
751 72737a7f Iustin Pop
    """Request the completion of an export operation.
752 a8083063 Iustin Pop

753 72737a7f Iustin Pop
    This writes the export config file, etc.
754 a8083063 Iustin Pop

755 72737a7f Iustin Pop
    This is a single-node call.
756 a8083063 Iustin Pop

757 72737a7f Iustin Pop
    """
758 72737a7f Iustin Pop
    flat_disks = []
759 72737a7f Iustin Pop
    for disk in snap_disks:
760 72737a7f Iustin Pop
      flat_disks.append(disk.ToDict())
761 72737a7f Iustin Pop
    params = [instance.ToDict(), flat_disks]
762 72737a7f Iustin Pop
    c = Client("finalize_export", 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 a8083063 Iustin Pop
768 72737a7f Iustin Pop
  def call_export_info(self, node, path):
769 72737a7f Iustin Pop
    """Queries the export information in a given path.
770 a8083063 Iustin Pop

771 72737a7f Iustin Pop
    This is a single-node call.
772 a8083063 Iustin Pop

773 72737a7f Iustin Pop
    """
774 72737a7f Iustin Pop
    c = Client("export_info", [path])
775 72737a7f Iustin Pop
    c.connect(node)
776 72737a7f Iustin Pop
    c.run()
777 72737a7f Iustin Pop
    result = c.getresult().get(node, False)
778 72737a7f Iustin Pop
    if not result:
779 72737a7f Iustin Pop
      return result
780 72737a7f Iustin Pop
    return objects.SerializableConfigParser.Loads(str(result))
781 a8083063 Iustin Pop
782 a8083063 Iustin Pop
783 72737a7f Iustin Pop
  def call_instance_os_import(self, node, inst, osdev, swapdev,
784 72737a7f Iustin Pop
                              src_node, src_image, cluster_name):
785 72737a7f Iustin Pop
    """Request the import of a backup into an instance.
786 a8083063 Iustin Pop

787 72737a7f Iustin Pop
    This is a single-node call.
788 a8083063 Iustin Pop

789 72737a7f Iustin Pop
    """
790 72737a7f Iustin Pop
    params = [inst.ToDict(), osdev, swapdev, src_node, src_image, cluster_name]
791 72737a7f Iustin Pop
    c = Client("instance_os_import", params)
792 72737a7f Iustin Pop
    c.connect(node)
793 72737a7f Iustin Pop
    c.run()
794 72737a7f Iustin Pop
    return c.getresult().get(node, False)
795 a8083063 Iustin Pop
796 a8083063 Iustin Pop
797 72737a7f Iustin Pop
  def call_export_list(self, node_list):
798 72737a7f Iustin Pop
    """Gets the stored exports list.
799 a8083063 Iustin Pop

800 72737a7f Iustin Pop
    This is a multi-node call.
801 a8083063 Iustin Pop

802 72737a7f Iustin Pop
    """
803 72737a7f Iustin Pop
    c = Client("export_list", [])
804 72737a7f Iustin Pop
    c.connect_list(node_list)
805 72737a7f Iustin Pop
    c.run()
806 72737a7f Iustin Pop
    result = c.getresult()
807 72737a7f Iustin Pop
    return result
808 a8083063 Iustin Pop
809 a8083063 Iustin Pop
810 72737a7f Iustin Pop
  def call_export_remove(self, node, export):
811 72737a7f Iustin Pop
    """Requests removal of a given export.
812 a8083063 Iustin Pop

813 72737a7f Iustin Pop
    This is a single-node call.
814 a8083063 Iustin Pop

815 72737a7f Iustin Pop
    """
816 72737a7f Iustin Pop
    c = Client("export_remove", [export])
817 72737a7f Iustin Pop
    c.connect(node)
818 72737a7f Iustin Pop
    c.run()
819 72737a7f Iustin Pop
    return c.getresult().get(node, False)
820 a8083063 Iustin Pop
821 a8083063 Iustin Pop
822 72737a7f Iustin Pop
  def call_node_leave_cluster(self, node):
823 72737a7f Iustin Pop
    """Requests a node to clean the cluster information it has.
824 a8083063 Iustin Pop

825 72737a7f Iustin Pop
    This will remove the configuration information from the ganeti data
826 72737a7f Iustin Pop
    dir.
827 a8083063 Iustin Pop

828 72737a7f Iustin Pop
    This is a single-node call.
829 a8083063 Iustin Pop

830 72737a7f Iustin Pop
    """
831 72737a7f Iustin Pop
    c = Client("node_leave_cluster", [])
832 72737a7f Iustin Pop
    c.connect(node)
833 72737a7f Iustin Pop
    c.run()
834 72737a7f Iustin Pop
    return c.getresult().get(node, False)
835 dcb93971 Michael Hanselmann
836 dcb93971 Michael Hanselmann
837 72737a7f Iustin Pop
  def call_node_volumes(self, node_list):
838 72737a7f Iustin Pop
    """Gets all volumes on node(s).
839 dcb93971 Michael Hanselmann

840 72737a7f Iustin Pop
    This is a multi-node call.
841 dcb93971 Michael Hanselmann

842 72737a7f Iustin Pop
    """
843 72737a7f Iustin Pop
    c = Client("node_volumes", [])
844 72737a7f Iustin Pop
    c.connect_list(node_list)
845 72737a7f Iustin Pop
    c.run()
846 72737a7f Iustin Pop
    return c.getresult()
847 06009e27 Iustin Pop
848 06009e27 Iustin Pop
849 72737a7f Iustin Pop
  def call_test_delay(self, node_list, duration):
850 72737a7f Iustin Pop
    """Sleep for a fixed time on given node(s).
851 06009e27 Iustin Pop

852 72737a7f Iustin Pop
    This is a multi-node call.
853 06009e27 Iustin Pop

854 72737a7f Iustin Pop
    """
855 72737a7f Iustin Pop
    c = Client("test_delay", [duration])
856 72737a7f Iustin Pop
    c.connect_list(node_list)
857 72737a7f Iustin Pop
    c.run()
858 72737a7f Iustin Pop
    return c.getresult()
859 5e04ed8b Manuel Franceschini
860 5e04ed8b Manuel Franceschini
861 72737a7f Iustin Pop
  def call_file_storage_dir_create(self, node, file_storage_dir):
862 72737a7f Iustin Pop
    """Create the given file storage directory.
863 5e04ed8b Manuel Franceschini

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

866 72737a7f Iustin Pop
    """
867 72737a7f Iustin Pop
    c = Client("file_storage_dir_create", [file_storage_dir])
868 72737a7f Iustin Pop
    c.connect(node)
869 72737a7f Iustin Pop
    c.run()
870 72737a7f Iustin Pop
    return c.getresult().get(node, False)
871 5e04ed8b Manuel Franceschini
872 5e04ed8b Manuel Franceschini
873 72737a7f Iustin Pop
  def call_file_storage_dir_remove(self, node, file_storage_dir):
874 72737a7f Iustin Pop
    """Remove the given file storage directory.
875 5e04ed8b Manuel Franceschini

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

878 72737a7f Iustin Pop
    """
879 72737a7f Iustin Pop
    c = Client("file_storage_dir_remove", [file_storage_dir])
880 72737a7f Iustin Pop
    c.connect(node)
881 72737a7f Iustin Pop
    c.run()
882 72737a7f Iustin Pop
    return c.getresult().get(node, False)
883 5e04ed8b Manuel Franceschini
884 5e04ed8b Manuel Franceschini
885 72737a7f Iustin Pop
  def call_file_storage_dir_rename(self, node, old_file_storage_dir,
886 72737a7f Iustin Pop
                                   new_file_storage_dir):
887 72737a7f Iustin Pop
    """Rename file storage directory.
888 5e04ed8b Manuel Franceschini

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

891 72737a7f Iustin Pop
    """
892 72737a7f Iustin Pop
    c = Client("file_storage_dir_rename",
893 72737a7f Iustin Pop
               [old_file_storage_dir, new_file_storage_dir])
894 72737a7f Iustin Pop
    c.connect(node)
895 72737a7f Iustin Pop
    c.run()
896 72737a7f Iustin Pop
    return c.getresult().get(node, False)
897 ca52cdeb Michael Hanselmann
898 ca52cdeb Michael Hanselmann
899 72737a7f Iustin Pop
  @staticmethod
900 72737a7f Iustin Pop
  def call_jobqueue_update(node_list, file_name, content):
901 72737a7f Iustin Pop
    """Update job queue.
902 ca52cdeb Michael Hanselmann

903 72737a7f Iustin Pop
    This is a multi-node call.
904 ca52cdeb Michael Hanselmann

905 72737a7f Iustin Pop
    """
906 72737a7f Iustin Pop
    c = Client("jobqueue_update", [file_name, content])
907 72737a7f Iustin Pop
    c.connect_list(node_list)
908 72737a7f Iustin Pop
    c.run()
909 72737a7f Iustin Pop
    result = c.getresult()
910 72737a7f Iustin Pop
    return result
911 ca52cdeb Michael Hanselmann
912 ca52cdeb Michael Hanselmann
913 72737a7f Iustin Pop
  @staticmethod
914 72737a7f Iustin Pop
  def call_jobqueue_purge(node):
915 72737a7f Iustin Pop
    """Purge job queue.
916 ca52cdeb Michael Hanselmann

917 72737a7f Iustin Pop
    This is a single-node call.
918 ca52cdeb Michael Hanselmann

919 72737a7f Iustin Pop
    """
920 72737a7f Iustin Pop
    c = Client("jobqueue_purge", [])
921 72737a7f Iustin Pop
    c.connect(node)
922 72737a7f Iustin Pop
    c.run()
923 72737a7f Iustin Pop
    return c.getresult().get(node, False)
924 af5ebcb1 Michael Hanselmann
925 af5ebcb1 Michael Hanselmann
926 72737a7f Iustin Pop
  @staticmethod
927 72737a7f Iustin Pop
  def call_jobqueue_rename(node_list, old, new):
928 72737a7f Iustin Pop
    """Rename a job queue file.
929 af5ebcb1 Michael Hanselmann

930 72737a7f Iustin Pop
    This is a multi-node call.
931 af5ebcb1 Michael Hanselmann

932 72737a7f Iustin Pop
    """
933 72737a7f Iustin Pop
    c = Client("jobqueue_rename", [old, new])
934 72737a7f Iustin Pop
    c.connect_list(node_list)
935 72737a7f Iustin Pop
    c.run()
936 72737a7f Iustin Pop
    result = c.getresult()
937 72737a7f Iustin Pop
    return result