Statistics
| Branch: | Tag: | Revision:

root / lib / rpc.py @ c8a0948f

History | View | Annotate | Download (18.8 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 a8083063 Iustin Pop
# pylint: disable-msg=C0103
27 a8083063 Iustin Pop
28 a8083063 Iustin Pop
import os
29 a8083063 Iustin Pop
30 a8083063 Iustin Pop
from twisted.internet.pollreactor import PollReactor
31 a8083063 Iustin Pop
32 a8083063 Iustin Pop
class ReReactor(PollReactor):
33 098c0958 Michael Hanselmann
  """A re-startable Reactor implementation.
34 a8083063 Iustin Pop

35 098c0958 Michael Hanselmann
  """
36 a8083063 Iustin Pop
  def run(self, installSignalHandlers=1):
37 a8083063 Iustin Pop
    """Custom run method.
38 a8083063 Iustin Pop

39 a8083063 Iustin Pop
    This is customized run that, before calling Reactor.run, will
40 a8083063 Iustin Pop
    reinstall the shutdown events and re-create the threadpool in case
41 a8083063 Iustin Pop
    these are not present (as will happen on the second run of the
42 a8083063 Iustin Pop
    reactor).
43 a8083063 Iustin Pop

44 a8083063 Iustin Pop
    """
45 a8083063 Iustin Pop
    if not 'shutdown' in self._eventTriggers:
46 a8083063 Iustin Pop
      # the shutdown queue has been killed, we are most probably
47 a8083063 Iustin Pop
      # at the second run, thus recreate the queue
48 a8083063 Iustin Pop
      self.addSystemEventTrigger('during', 'shutdown', self.crash)
49 a8083063 Iustin Pop
      self.addSystemEventTrigger('during', 'shutdown', self.disconnectAll)
50 a8083063 Iustin Pop
    if self.threadpool is not None and self.threadpool.joined == 1:
51 a8083063 Iustin Pop
      # in case the threadpool has been stopped, re-start it
52 a8083063 Iustin Pop
      # and add a trigger to stop it at reactor shutdown
53 a8083063 Iustin Pop
      self.threadpool.start()
54 a8083063 Iustin Pop
      self.addSystemEventTrigger('during', 'shutdown', self.threadpool.stop)
55 a8083063 Iustin Pop
56 a8083063 Iustin Pop
    return PollReactor.run(self, installSignalHandlers)
57 a8083063 Iustin Pop
58 a8083063 Iustin Pop
59 a8083063 Iustin Pop
import twisted.internet.main
60 a8083063 Iustin Pop
twisted.internet.main.installReactor(ReReactor())
61 a8083063 Iustin Pop
62 a8083063 Iustin Pop
from twisted.spread import pb
63 a8083063 Iustin Pop
from twisted.internet import reactor
64 a8083063 Iustin Pop
from twisted.cred import credentials
65 a8083063 Iustin Pop
from OpenSSL import SSL, crypto
66 a8083063 Iustin Pop
67 a8083063 Iustin Pop
from ganeti import logger
68 a8083063 Iustin Pop
from ganeti import utils
69 a8083063 Iustin Pop
from ganeti import errors
70 a8083063 Iustin Pop
from ganeti import constants
71 a8083063 Iustin Pop
from ganeti import objects
72 a8083063 Iustin Pop
from ganeti import ssconf
73 a8083063 Iustin Pop
74 a8083063 Iustin Pop
class NodeController:
75 a8083063 Iustin Pop
  """Node-handling class.
76 a8083063 Iustin Pop

77 a8083063 Iustin Pop
  For each node that we speak with, we create an instance of this
78 a8083063 Iustin Pop
  class, so that we have a safe place to store the details of this
79 a8083063 Iustin Pop
  individual call.
80 a8083063 Iustin Pop

81 a8083063 Iustin Pop
  """
82 a8083063 Iustin Pop
  def __init__(self, parent, node):
83 a8083063 Iustin Pop
    self.parent = parent
84 a8083063 Iustin Pop
    self.node = node
85 a8083063 Iustin Pop
86 a8083063 Iustin Pop
  def _check_end(self):
87 a8083063 Iustin Pop
    """Stop the reactor if we got all the results.
88 a8083063 Iustin Pop

89 a8083063 Iustin Pop
    """
90 a8083063 Iustin Pop
    if len(self.parent.results) == len(self.parent.nc):
91 a8083063 Iustin Pop
      reactor.stop()
92 a8083063 Iustin Pop
93 a8083063 Iustin Pop
  def cb_call(self, obj):
94 31ee599c Michael Hanselmann
    """Callback for successful connect.
95 a8083063 Iustin Pop

96 a8083063 Iustin Pop
    If the connect and login sequence succeeded, we proceed with
97 a8083063 Iustin Pop
    making the actual call.
98 a8083063 Iustin Pop

99 a8083063 Iustin Pop
    """
100 a8083063 Iustin Pop
    deferred = obj.callRemote(self.parent.procedure, self.parent.args)
101 a8083063 Iustin Pop
    deferred.addCallbacks(self.cb_done, self.cb_err2)
102 a8083063 Iustin Pop
103 a8083063 Iustin Pop
  def cb_done(self, result):
104 a8083063 Iustin Pop
    """Callback for successful call.
105 a8083063 Iustin Pop

106 a8083063 Iustin Pop
    When we receive the result from a call, we check if it was an
107 a8083063 Iustin Pop
    error and if so we raise a generic RemoteError (we can't pass yet
108 a8083063 Iustin Pop
    the actual exception over). If there was no error, we store the
109 a8083063 Iustin Pop
    result.
110 a8083063 Iustin Pop

111 a8083063 Iustin Pop
    """
112 a8083063 Iustin Pop
    tb, self.parent.results[self.node] = result
113 a8083063 Iustin Pop
    self._check_end()
114 a8083063 Iustin Pop
    if tb:
115 a8083063 Iustin Pop
      raise errors.RemoteError("Remote procedure error calling %s on %s:"
116 a8083063 Iustin Pop
                               "\n%s" % (self.parent.procedure,
117 a8083063 Iustin Pop
                                         self.node,
118 a8083063 Iustin Pop
                                         tb))
119 a8083063 Iustin Pop
120 a8083063 Iustin Pop
  def cb_err1(self, reason):
121 a8083063 Iustin Pop
    """Error callback for unsuccessful connect.
122 a8083063 Iustin Pop

123 a8083063 Iustin Pop
    """
124 a8083063 Iustin Pop
    logger.Error("caller_connect: could not connect to remote host %s,"
125 a8083063 Iustin Pop
                 " reason %s" % (self.node, reason))
126 a8083063 Iustin Pop
    self.parent.results[self.node] = False
127 a8083063 Iustin Pop
    self._check_end()
128 a8083063 Iustin Pop
129 a8083063 Iustin Pop
  def cb_err2(self, reason):
130 a8083063 Iustin Pop
    """Error callback for unsuccessful call.
131 a8083063 Iustin Pop

132 a8083063 Iustin Pop
    This is when the call didn't return anything, not even an error,
133 a8083063 Iustin Pop
    or when it time out, etc.
134 a8083063 Iustin Pop

135 a8083063 Iustin Pop
    """
136 a8083063 Iustin Pop
    logger.Error("caller_call: could not call %s on node %s,"
137 a8083063 Iustin Pop
                 " reason %s" % (self.parent.procedure, self.node, reason))
138 a8083063 Iustin Pop
    self.parent.results[self.node] = False
139 a8083063 Iustin Pop
    self._check_end()
140 a8083063 Iustin Pop
141 a8083063 Iustin Pop
142 a8083063 Iustin Pop
class MirrorContextFactory:
143 a8083063 Iustin Pop
  """Certificate verifier factory.
144 a8083063 Iustin Pop

145 a8083063 Iustin Pop
  This factory creates contexts that verify if the remote end has a
146 a8083063 Iustin Pop
  specific certificate (i.e. our own certificate).
147 a8083063 Iustin Pop

148 a8083063 Iustin Pop
  The checks we do are that the PEM dump of the certificate is the
149 a8083063 Iustin Pop
  same as our own and (somewhat redundantly) that the SHA checksum is
150 a8083063 Iustin Pop
  the same.
151 a8083063 Iustin Pop

152 a8083063 Iustin Pop
  """
153 a8083063 Iustin Pop
  isClient = 1
154 a8083063 Iustin Pop
155 a8083063 Iustin Pop
  def __init__(self):
156 a8083063 Iustin Pop
    try:
157 a8083063 Iustin Pop
      fd = open(constants.SSL_CERT_FILE, 'r')
158 a8083063 Iustin Pop
      try:
159 a8083063 Iustin Pop
        data = fd.read(16384)
160 a8083063 Iustin Pop
      finally:
161 a8083063 Iustin Pop
        fd.close()
162 a8083063 Iustin Pop
    except EnvironmentError, err:
163 3ecf6786 Iustin Pop
      raise errors.ConfigurationError("missing SSL certificate: %s" %
164 3ecf6786 Iustin Pop
                                      str(err))
165 a8083063 Iustin Pop
    self.mycert = crypto.load_certificate(crypto.FILETYPE_PEM, data)
166 a8083063 Iustin Pop
    self.mypem = crypto.dump_certificate(crypto.FILETYPE_PEM, self.mycert)
167 a8083063 Iustin Pop
    self.mydigest = self.mycert.digest('SHA')
168 a8083063 Iustin Pop
169 a8083063 Iustin Pop
  def verifier(self, conn, x509, errno, err_depth, retcode):
170 a8083063 Iustin Pop
    """Certificate verify method.
171 a8083063 Iustin Pop

172 a8083063 Iustin Pop
    """
173 a8083063 Iustin Pop
    if self.mydigest != x509.digest('SHA'):
174 a8083063 Iustin Pop
      return False
175 a8083063 Iustin Pop
    if crypto.dump_certificate(crypto.FILETYPE_PEM, x509) != self.mypem:
176 a8083063 Iustin Pop
      return False
177 a8083063 Iustin Pop
    return True
178 a8083063 Iustin Pop
179 a8083063 Iustin Pop
  def getContext(self):
180 a8083063 Iustin Pop
    """Context generator.
181 a8083063 Iustin Pop

182 a8083063 Iustin Pop
    """
183 a8083063 Iustin Pop
    context = SSL.Context(SSL.TLSv1_METHOD)
184 a8083063 Iustin Pop
    context.set_verify(SSL.VERIFY_PEER, self.verifier)
185 a8083063 Iustin Pop
    return context
186 a8083063 Iustin Pop
187 a8083063 Iustin Pop
class Client:
188 a8083063 Iustin Pop
  """RPC Client class.
189 a8083063 Iustin Pop

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

194 a8083063 Iustin Pop
  One current bug is that generic failure is still signalled by
195 a8083063 Iustin Pop
  'False' result, which is not good. This overloading of values can
196 a8083063 Iustin Pop
  cause bugs.
197 a8083063 Iustin Pop

198 a8083063 Iustin Pop
  """
199 a8083063 Iustin Pop
  result_set = False
200 a8083063 Iustin Pop
  result = False
201 a8083063 Iustin Pop
  allresult = []
202 a8083063 Iustin Pop
203 a8083063 Iustin Pop
  def __init__(self, procedure, args):
204 a8083063 Iustin Pop
    ss = ssconf.SimpleStore()
205 a8083063 Iustin Pop
    self.port = ss.GetNodeDaemonPort()
206 a8083063 Iustin Pop
    self.nodepw = ss.GetNodeDaemonPassword()
207 a8083063 Iustin Pop
    self.nc = {}
208 a8083063 Iustin Pop
    self.results = {}
209 a8083063 Iustin Pop
    self.procedure = procedure
210 a8083063 Iustin Pop
    self.args = args
211 a8083063 Iustin Pop
212 a8083063 Iustin Pop
  #--- generic connector -------------
213 a8083063 Iustin Pop
214 a8083063 Iustin Pop
  def connect_list(self, node_list):
215 a8083063 Iustin Pop
    """Add a list of nodes to the target nodes.
216 a8083063 Iustin Pop

217 a8083063 Iustin Pop
    """
218 a8083063 Iustin Pop
    for node in node_list:
219 a8083063 Iustin Pop
      self.connect(node)
220 a8083063 Iustin Pop
221 a8083063 Iustin Pop
  def connect(self, connect_node):
222 a8083063 Iustin Pop
    """Add a node to the target list.
223 a8083063 Iustin Pop

224 a8083063 Iustin Pop
    """
225 a8083063 Iustin Pop
    factory = pb.PBClientFactory()
226 a8083063 Iustin Pop
    self.nc[connect_node] = nc = NodeController(self, connect_node)
227 a8083063 Iustin Pop
    reactor.connectSSL(connect_node, self.port, factory,
228 a8083063 Iustin Pop
                       MirrorContextFactory())
229 a8083063 Iustin Pop
    #d = factory.getRootObject()
230 a8083063 Iustin Pop
    d = factory.login(credentials.UsernamePassword("master_node", self.nodepw))
231 a8083063 Iustin Pop
    d.addCallbacks(nc.cb_call, nc.cb_err1)
232 a8083063 Iustin Pop
233 a8083063 Iustin Pop
  def getresult(self):
234 a8083063 Iustin Pop
    """Return the results of the call.
235 a8083063 Iustin Pop

236 a8083063 Iustin Pop
    """
237 a8083063 Iustin Pop
    return self.results
238 a8083063 Iustin Pop
239 a8083063 Iustin Pop
  def run(self):
240 a8083063 Iustin Pop
    """Wrapper over reactor.run().
241 a8083063 Iustin Pop

242 a8083063 Iustin Pop
    This function simply calls reactor.run() if we have any requests
243 a8083063 Iustin Pop
    queued, otherwise it does nothing.
244 a8083063 Iustin Pop

245 a8083063 Iustin Pop
    """
246 a8083063 Iustin Pop
    if self.nc:
247 a8083063 Iustin Pop
      reactor.run()
248 a8083063 Iustin Pop
249 a8083063 Iustin Pop
250 a8083063 Iustin Pop
def call_volume_list(node_list, vg_name):
251 a8083063 Iustin Pop
  """Gets the logical volumes present in a given volume group.
252 a8083063 Iustin Pop

253 a8083063 Iustin Pop
  This is a multi-node call.
254 a8083063 Iustin Pop

255 a8083063 Iustin Pop
  """
256 a8083063 Iustin Pop
  c = Client("volume_list", [vg_name])
257 a8083063 Iustin Pop
  c.connect_list(node_list)
258 a8083063 Iustin Pop
  c.run()
259 a8083063 Iustin Pop
  return c.getresult()
260 a8083063 Iustin Pop
261 a8083063 Iustin Pop
262 a8083063 Iustin Pop
def call_vg_list(node_list):
263 a8083063 Iustin Pop
  """Gets the volume group list.
264 a8083063 Iustin Pop

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

267 a8083063 Iustin Pop
  """
268 a8083063 Iustin Pop
  c = Client("vg_list", [])
269 a8083063 Iustin Pop
  c.connect_list(node_list)
270 a8083063 Iustin Pop
  c.run()
271 a8083063 Iustin Pop
  return c.getresult()
272 a8083063 Iustin Pop
273 a8083063 Iustin Pop
274 a8083063 Iustin Pop
def call_bridges_exist(node, bridges_list):
275 a8083063 Iustin Pop
  """Checks if a node has all the bridges given.
276 a8083063 Iustin Pop

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

281 a8083063 Iustin Pop
  This is a single-node call.
282 a8083063 Iustin Pop

283 a8083063 Iustin Pop
  """
284 a8083063 Iustin Pop
  c = Client("bridges_exist", [bridges_list])
285 a8083063 Iustin Pop
  c.connect(node)
286 a8083063 Iustin Pop
  c.run()
287 a8083063 Iustin Pop
  return c.getresult().get(node, False)
288 a8083063 Iustin Pop
289 a8083063 Iustin Pop
290 a8083063 Iustin Pop
def call_instance_start(node, instance, extra_args):
291 2f8598a5 Alexander Schreiber
  """Starts an instance.
292 a8083063 Iustin Pop

293 a8083063 Iustin Pop
  This is a single-node call.
294 a8083063 Iustin Pop

295 a8083063 Iustin Pop
  """
296 319856a9 Michael Hanselmann
  c = Client("instance_start", [instance.ToDict(), extra_args])
297 a8083063 Iustin Pop
  c.connect(node)
298 a8083063 Iustin Pop
  c.run()
299 a8083063 Iustin Pop
  return c.getresult().get(node, False)
300 a8083063 Iustin Pop
301 a8083063 Iustin Pop
302 a8083063 Iustin Pop
def call_instance_shutdown(node, instance):
303 a8083063 Iustin Pop
  """Stops an instance.
304 a8083063 Iustin Pop

305 a8083063 Iustin Pop
  This is a single-node call.
306 a8083063 Iustin Pop

307 a8083063 Iustin Pop
  """
308 319856a9 Michael Hanselmann
  c = Client("instance_shutdown", [instance.ToDict()])
309 a8083063 Iustin Pop
  c.connect(node)
310 a8083063 Iustin Pop
  c.run()
311 a8083063 Iustin Pop
  return c.getresult().get(node, False)
312 a8083063 Iustin Pop
313 a8083063 Iustin Pop
314 007a2f3e Alexander Schreiber
def call_instance_reboot(node, instance, reboot_type, extra_args):
315 007a2f3e Alexander Schreiber
  """Reboots an instance.
316 007a2f3e Alexander Schreiber

317 007a2f3e Alexander Schreiber
  This is a single-node call.
318 007a2f3e Alexander Schreiber

319 007a2f3e Alexander Schreiber
  """
320 007a2f3e Alexander Schreiber
  c = Client("instance_reboot", [instance.ToDict(), reboot_type, extra_args])
321 007a2f3e Alexander Schreiber
  c.connect(node)
322 007a2f3e Alexander Schreiber
  c.run()
323 007a2f3e Alexander Schreiber
  return c.getresult().get(node, False)
324 007a2f3e Alexander Schreiber
325 007a2f3e Alexander Schreiber
326 a8083063 Iustin Pop
def call_instance_os_add(node, inst, osdev, swapdev):
327 a8083063 Iustin Pop
  """Installs an OS on the given instance.
328 a8083063 Iustin Pop

329 a8083063 Iustin Pop
  This is a single-node call.
330 a8083063 Iustin Pop

331 a8083063 Iustin Pop
  """
332 319856a9 Michael Hanselmann
  params = [inst.ToDict(), osdev, swapdev]
333 a8083063 Iustin Pop
  c = Client("instance_os_add", params)
334 a8083063 Iustin Pop
  c.connect(node)
335 a8083063 Iustin Pop
  c.run()
336 a8083063 Iustin Pop
  return c.getresult().get(node, False)
337 a8083063 Iustin Pop
338 a8083063 Iustin Pop
339 decd5f45 Iustin Pop
def call_instance_run_rename(node, inst, old_name, osdev, swapdev):
340 decd5f45 Iustin Pop
  """Run the OS rename script for an instance.
341 decd5f45 Iustin Pop

342 decd5f45 Iustin Pop
  This is a single-node call.
343 decd5f45 Iustin Pop

344 decd5f45 Iustin Pop
  """
345 319856a9 Michael Hanselmann
  params = [inst.ToDict(), old_name, osdev, swapdev]
346 decd5f45 Iustin Pop
  c = Client("instance_run_rename", params)
347 decd5f45 Iustin Pop
  c.connect(node)
348 decd5f45 Iustin Pop
  c.run()
349 decd5f45 Iustin Pop
  return c.getresult().get(node, False)
350 decd5f45 Iustin Pop
351 decd5f45 Iustin Pop
352 a8083063 Iustin Pop
def call_instance_info(node, instance):
353 a8083063 Iustin Pop
  """Returns information about a single instance.
354 a8083063 Iustin Pop

355 a8083063 Iustin Pop
  This is a single-node call.
356 a8083063 Iustin Pop

357 a8083063 Iustin Pop
  """
358 a8083063 Iustin Pop
  c = Client("instance_info", [instance])
359 a8083063 Iustin Pop
  c.connect(node)
360 a8083063 Iustin Pop
  c.run()
361 a8083063 Iustin Pop
  return c.getresult().get(node, False)
362 a8083063 Iustin Pop
363 a8083063 Iustin Pop
364 a8083063 Iustin Pop
def call_all_instances_info(node_list):
365 a8083063 Iustin Pop
  """Returns information about all instances on a given node.
366 a8083063 Iustin Pop

367 a8083063 Iustin Pop
  This is a single-node call.
368 a8083063 Iustin Pop

369 a8083063 Iustin Pop
  """
370 a8083063 Iustin Pop
  c = Client("all_instances_info", [])
371 a8083063 Iustin Pop
  c.connect_list(node_list)
372 a8083063 Iustin Pop
  c.run()
373 a8083063 Iustin Pop
  return c.getresult()
374 a8083063 Iustin Pop
375 a8083063 Iustin Pop
376 a8083063 Iustin Pop
def call_instance_list(node_list):
377 a8083063 Iustin Pop
  """Returns the list of running instances on a given node.
378 a8083063 Iustin Pop

379 a8083063 Iustin Pop
  This is a single-node call.
380 a8083063 Iustin Pop

381 a8083063 Iustin Pop
  """
382 a8083063 Iustin Pop
  c = Client("instance_list", [])
383 a8083063 Iustin Pop
  c.connect_list(node_list)
384 a8083063 Iustin Pop
  c.run()
385 a8083063 Iustin Pop
  return c.getresult()
386 a8083063 Iustin Pop
387 a8083063 Iustin Pop
388 16abfbc2 Alexander Schreiber
def call_node_tcp_ping(node, source, target, port, timeout, live_port_needed):
389 16abfbc2 Alexander Schreiber
  """Do a TcpPing on the remote node
390 16abfbc2 Alexander Schreiber

391 16abfbc2 Alexander Schreiber
  This is a single-node call.
392 16abfbc2 Alexander Schreiber
  """
393 16abfbc2 Alexander Schreiber
  c = Client("node_tcp_ping", [source, target, port, timeout,
394 16abfbc2 Alexander Schreiber
                               live_port_needed])
395 16abfbc2 Alexander Schreiber
  c.connect(node)
396 16abfbc2 Alexander Schreiber
  c.run()
397 16abfbc2 Alexander Schreiber
  return c.getresult().get(node, False)
398 16abfbc2 Alexander Schreiber
399 16abfbc2 Alexander Schreiber
400 a8083063 Iustin Pop
def call_node_info(node_list, vg_name):
401 a8083063 Iustin Pop
  """Return node information.
402 a8083063 Iustin Pop

403 a8083063 Iustin Pop
  This will return memory information and volume group size and free
404 a8083063 Iustin Pop
  space.
405 a8083063 Iustin Pop

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

408 a8083063 Iustin Pop
  """
409 a8083063 Iustin Pop
  c = Client("node_info", [vg_name])
410 a8083063 Iustin Pop
  c.connect_list(node_list)
411 a8083063 Iustin Pop
  c.run()
412 a8083063 Iustin Pop
  retux = c.getresult()
413 a8083063 Iustin Pop
414 a8083063 Iustin Pop
  for node_name in retux:
415 a8083063 Iustin Pop
    ret = retux.get(node_name, False)
416 a8083063 Iustin Pop
    if type(ret) != dict:
417 a8083063 Iustin Pop
      logger.Error("could not connect to node %s" % (node_name))
418 a8083063 Iustin Pop
      ret = {}
419 a8083063 Iustin Pop
420 a8083063 Iustin Pop
    utils.CheckDict(ret,
421 a8083063 Iustin Pop
                    { 'memory_total' : '-',
422 a8083063 Iustin Pop
                      'memory_dom0' : '-',
423 a8083063 Iustin Pop
                      'memory_free' : '-',
424 a8083063 Iustin Pop
                      'vg_size' : 'node_unreachable',
425 a8083063 Iustin Pop
                      'vg_free' : '-' },
426 a8083063 Iustin Pop
                    "call_node_info",
427 a8083063 Iustin Pop
                    )
428 a8083063 Iustin Pop
  return retux
429 a8083063 Iustin Pop
430 a8083063 Iustin Pop
431 a8083063 Iustin Pop
def call_node_add(node, dsa, dsapub, rsa, rsapub, ssh, sshpub):
432 a8083063 Iustin Pop
  """Add a node to the cluster.
433 a8083063 Iustin Pop

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

436 a8083063 Iustin Pop
  """
437 a8083063 Iustin Pop
  params = [dsa, dsapub, rsa, rsapub, ssh, sshpub]
438 a8083063 Iustin Pop
  c = Client("node_add", params)
439 a8083063 Iustin Pop
  c.connect(node)
440 a8083063 Iustin Pop
  c.run()
441 a8083063 Iustin Pop
  return c.getresult().get(node, False)
442 a8083063 Iustin Pop
443 a8083063 Iustin Pop
444 a8083063 Iustin Pop
def call_node_verify(node_list, checkdict):
445 a8083063 Iustin Pop
  """Request verification of given parameters.
446 a8083063 Iustin Pop

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

449 a8083063 Iustin Pop
  """
450 a8083063 Iustin Pop
  c = Client("node_verify", [checkdict])
451 a8083063 Iustin Pop
  c.connect_list(node_list)
452 a8083063 Iustin Pop
  c.run()
453 a8083063 Iustin Pop
  return c.getresult()
454 a8083063 Iustin Pop
455 a8083063 Iustin Pop
456 a8083063 Iustin Pop
def call_node_start_master(node):
457 a8083063 Iustin Pop
  """Tells a node to activate itself as a master.
458 a8083063 Iustin Pop

459 a8083063 Iustin Pop
  This is a single-node call.
460 a8083063 Iustin Pop

461 a8083063 Iustin Pop
  """
462 a8083063 Iustin Pop
  c = Client("node_start_master", [])
463 a8083063 Iustin Pop
  c.connect(node)
464 a8083063 Iustin Pop
  c.run()
465 a8083063 Iustin Pop
  return c.getresult().get(node, False)
466 a8083063 Iustin Pop
467 a8083063 Iustin Pop
468 a8083063 Iustin Pop
def call_node_stop_master(node):
469 a8083063 Iustin Pop
  """Tells a node to demote itself from master status.
470 a8083063 Iustin Pop

471 a8083063 Iustin Pop
  This is a single-node call.
472 a8083063 Iustin Pop

473 a8083063 Iustin Pop
  """
474 a8083063 Iustin Pop
  c = Client("node_stop_master", [])
475 a8083063 Iustin Pop
  c.connect(node)
476 a8083063 Iustin Pop
  c.run()
477 a8083063 Iustin Pop
  return c.getresult().get(node, False)
478 a8083063 Iustin Pop
479 a8083063 Iustin Pop
480 a8083063 Iustin Pop
def call_version(node_list):
481 a8083063 Iustin Pop
  """Query node version.
482 a8083063 Iustin Pop

483 a8083063 Iustin Pop
  This is a multi-node call.
484 a8083063 Iustin Pop

485 a8083063 Iustin Pop
  """
486 a8083063 Iustin Pop
  c = Client("version", [])
487 a8083063 Iustin Pop
  c.connect_list(node_list)
488 a8083063 Iustin Pop
  c.run()
489 a8083063 Iustin Pop
  return c.getresult()
490 a8083063 Iustin Pop
491 a8083063 Iustin Pop
492 3f78eef2 Iustin Pop
def call_blockdev_create(node, bdev, size, owner, on_primary, info):
493 a8083063 Iustin Pop
  """Request creation of a given block device.
494 a8083063 Iustin Pop

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

497 a8083063 Iustin Pop
  """
498 3f78eef2 Iustin Pop
  params = [bdev.ToDict(), size, owner, on_primary, info]
499 a8083063 Iustin Pop
  c = Client("blockdev_create", params)
500 a8083063 Iustin Pop
  c.connect(node)
501 a8083063 Iustin Pop
  c.run()
502 a8083063 Iustin Pop
  return c.getresult().get(node, False)
503 a8083063 Iustin Pop
504 a8083063 Iustin Pop
505 a8083063 Iustin Pop
def call_blockdev_remove(node, bdev):
506 a8083063 Iustin Pop
  """Request removal of a given block device.
507 a8083063 Iustin Pop

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

510 a8083063 Iustin Pop
  """
511 319856a9 Michael Hanselmann
  c = Client("blockdev_remove", [bdev.ToDict()])
512 a8083063 Iustin Pop
  c.connect(node)
513 a8083063 Iustin Pop
  c.run()
514 a8083063 Iustin Pop
  return c.getresult().get(node, False)
515 a8083063 Iustin Pop
516 a8083063 Iustin Pop
517 f3e513ad Iustin Pop
def call_blockdev_rename(node, devlist):
518 f3e513ad Iustin Pop
  """Request rename of the given block devices.
519 f3e513ad Iustin Pop

520 f3e513ad Iustin Pop
  This is a single-node call.
521 f3e513ad Iustin Pop

522 f3e513ad Iustin Pop
  """
523 f3e513ad Iustin Pop
  params = [(d.ToDict(), uid) for d, uid in devlist]
524 f3e513ad Iustin Pop
  c = Client("blockdev_rename", params)
525 f3e513ad Iustin Pop
  c.connect(node)
526 f3e513ad Iustin Pop
  c.run()
527 f3e513ad Iustin Pop
  return c.getresult().get(node, False)
528 f3e513ad Iustin Pop
529 f3e513ad Iustin Pop
530 3f78eef2 Iustin Pop
def call_blockdev_assemble(node, disk, owner, on_primary):
531 a8083063 Iustin Pop
  """Request assembling of a given block device.
532 a8083063 Iustin Pop

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

535 a8083063 Iustin Pop
  """
536 3f78eef2 Iustin Pop
  params = [disk.ToDict(), owner, on_primary]
537 a8083063 Iustin Pop
  c = Client("blockdev_assemble", params)
538 a8083063 Iustin Pop
  c.connect(node)
539 a8083063 Iustin Pop
  c.run()
540 a8083063 Iustin Pop
  return c.getresult().get(node, False)
541 a8083063 Iustin Pop
542 a8083063 Iustin Pop
543 a8083063 Iustin Pop
def call_blockdev_shutdown(node, disk):
544 a8083063 Iustin Pop
  """Request shutdown of a given block device.
545 a8083063 Iustin Pop

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

548 a8083063 Iustin Pop
  """
549 319856a9 Michael Hanselmann
  c = Client("blockdev_shutdown", [disk.ToDict()])
550 a8083063 Iustin Pop
  c.connect(node)
551 a8083063 Iustin Pop
  c.run()
552 a8083063 Iustin Pop
  return c.getresult().get(node, False)
553 a8083063 Iustin Pop
554 a8083063 Iustin Pop
555 153d9724 Iustin Pop
def call_blockdev_addchildren(node, bdev, ndevs):
556 153d9724 Iustin Pop
  """Request adding a list of children to a (mirroring) device.
557 a8083063 Iustin Pop

558 a8083063 Iustin Pop
  This is a single-node call.
559 a8083063 Iustin Pop

560 a8083063 Iustin Pop
  """
561 153d9724 Iustin Pop
  params = [bdev.ToDict(), [disk.ToDict() for disk in ndevs]]
562 153d9724 Iustin Pop
  c = Client("blockdev_addchildren", params)
563 a8083063 Iustin Pop
  c.connect(node)
564 a8083063 Iustin Pop
  c.run()
565 a8083063 Iustin Pop
  return c.getresult().get(node, False)
566 a8083063 Iustin Pop
567 a8083063 Iustin Pop
568 153d9724 Iustin Pop
def call_blockdev_removechildren(node, bdev, ndevs):
569 153d9724 Iustin Pop
  """Request removing a list of children from a (mirroring) device.
570 a8083063 Iustin Pop

571 a8083063 Iustin Pop
  This is a single-node call.
572 a8083063 Iustin Pop

573 a8083063 Iustin Pop
  """
574 153d9724 Iustin Pop
  params = [bdev.ToDict(), [disk.ToDict() for disk in ndevs]]
575 153d9724 Iustin Pop
  c = Client("blockdev_removechildren", params)
576 a8083063 Iustin Pop
  c.connect(node)
577 a8083063 Iustin Pop
  c.run()
578 a8083063 Iustin Pop
  return c.getresult().get(node, False)
579 a8083063 Iustin Pop
580 a8083063 Iustin Pop
581 a8083063 Iustin Pop
def call_blockdev_getmirrorstatus(node, disks):
582 a8083063 Iustin Pop
  """Request status of a (mirroring) device.
583 a8083063 Iustin Pop

584 a8083063 Iustin Pop
  This is a single-node call.
585 a8083063 Iustin Pop

586 a8083063 Iustin Pop
  """
587 319856a9 Michael Hanselmann
  params = [dsk.ToDict() for dsk in disks]
588 a8083063 Iustin Pop
  c = Client("blockdev_getmirrorstatus", params)
589 a8083063 Iustin Pop
  c.connect(node)
590 a8083063 Iustin Pop
  c.run()
591 a8083063 Iustin Pop
  return c.getresult().get(node, False)
592 a8083063 Iustin Pop
593 a8083063 Iustin Pop
594 a8083063 Iustin Pop
def call_blockdev_find(node, disk):
595 a8083063 Iustin Pop
  """Request identification of a given block device.
596 a8083063 Iustin Pop

597 a8083063 Iustin Pop
  This is a single-node call.
598 a8083063 Iustin Pop

599 a8083063 Iustin Pop
  """
600 319856a9 Michael Hanselmann
  c = Client("blockdev_find", [disk.ToDict()])
601 a8083063 Iustin Pop
  c.connect(node)
602 a8083063 Iustin Pop
  c.run()
603 a8083063 Iustin Pop
  return c.getresult().get(node, False)
604 a8083063 Iustin Pop
605 a8083063 Iustin Pop
606 a8083063 Iustin Pop
def call_upload_file(node_list, file_name):
607 a8083063 Iustin Pop
  """Upload a file.
608 a8083063 Iustin Pop

609 a8083063 Iustin Pop
  The node will refuse the operation in case the file is not on the
610 a8083063 Iustin Pop
  approved file list.
611 a8083063 Iustin Pop

612 a8083063 Iustin Pop
  This is a multi-node call.
613 a8083063 Iustin Pop

614 a8083063 Iustin Pop
  """
615 a8083063 Iustin Pop
  fh = file(file_name)
616 a8083063 Iustin Pop
  try:
617 a8083063 Iustin Pop
    data = fh.read()
618 a8083063 Iustin Pop
  finally:
619 a8083063 Iustin Pop
    fh.close()
620 a8083063 Iustin Pop
  st = os.stat(file_name)
621 a8083063 Iustin Pop
  params = [file_name, data, st.st_mode, st.st_uid, st.st_gid,
622 a8083063 Iustin Pop
            st.st_atime, st.st_mtime]
623 a8083063 Iustin Pop
  c = Client("upload_file", params)
624 a8083063 Iustin Pop
  c.connect_list(node_list)
625 a8083063 Iustin Pop
  c.run()
626 a8083063 Iustin Pop
  return c.getresult()
627 a8083063 Iustin Pop
628 a8083063 Iustin Pop
629 a8083063 Iustin Pop
def call_os_diagnose(node_list):
630 a8083063 Iustin Pop
  """Request a diagnose of OS definitions.
631 a8083063 Iustin Pop

632 a8083063 Iustin Pop
  This is a multi-node call.
633 a8083063 Iustin Pop

634 a8083063 Iustin Pop
  """
635 a8083063 Iustin Pop
  c = Client("os_diagnose", [])
636 a8083063 Iustin Pop
  c.connect_list(node_list)
637 a8083063 Iustin Pop
  c.run()
638 a8083063 Iustin Pop
  result = c.getresult()
639 a8083063 Iustin Pop
  new_result = {}
640 a8083063 Iustin Pop
  for node_name in result:
641 a8083063 Iustin Pop
    if result[node_name]:
642 4e679f11 Guido Trotter
      nr = [objects.OS.FromDict(oss) for oss in result[node_name]]
643 4e679f11 Guido Trotter
    else:
644 4e679f11 Guido Trotter
      nr = []
645 a8083063 Iustin Pop
    new_result[node_name] = nr
646 a8083063 Iustin Pop
  return new_result
647 a8083063 Iustin Pop
648 a8083063 Iustin Pop
649 00fe9e38 Guido Trotter
def call_os_get(node, name):
650 a8083063 Iustin Pop
  """Returns an OS definition.
651 a8083063 Iustin Pop

652 00fe9e38 Guido Trotter
  This is a single-node call.
653 a8083063 Iustin Pop

654 a8083063 Iustin Pop
  """
655 a8083063 Iustin Pop
  c = Client("os_get", [name])
656 00fe9e38 Guido Trotter
  c.connect(node)
657 a8083063 Iustin Pop
  c.run()
658 00fe9e38 Guido Trotter
  result = c.getresult().get(node, False)
659 00fe9e38 Guido Trotter
  if isinstance(result, dict):
660 dfa96ded Guido Trotter
    return objects.OS.FromDict(result)
661 00fe9e38 Guido Trotter
  else:
662 dfa96ded Guido Trotter
    return result
663 a8083063 Iustin Pop
664 a8083063 Iustin Pop
665 a8083063 Iustin Pop
def call_hooks_runner(node_list, hpath, phase, env):
666 a8083063 Iustin Pop
  """Call the hooks runner.
667 a8083063 Iustin Pop

668 a8083063 Iustin Pop
  Args:
669 a8083063 Iustin Pop
    - op: the OpCode instance
670 a8083063 Iustin Pop
    - env: a dictionary with the environment
671 a8083063 Iustin Pop

672 a8083063 Iustin Pop
  This is a multi-node call.
673 a8083063 Iustin Pop

674 a8083063 Iustin Pop
  """
675 a8083063 Iustin Pop
  params = [hpath, phase, env]
676 a8083063 Iustin Pop
  c = Client("hooks_runner", params)
677 a8083063 Iustin Pop
  c.connect_list(node_list)
678 a8083063 Iustin Pop
  c.run()
679 a8083063 Iustin Pop
  result = c.getresult()
680 a8083063 Iustin Pop
  return result
681 a8083063 Iustin Pop
682 a8083063 Iustin Pop
683 a8083063 Iustin Pop
def call_blockdev_snapshot(node, cf_bdev):
684 a8083063 Iustin Pop
  """Request a snapshot of the given block device.
685 a8083063 Iustin Pop

686 a8083063 Iustin Pop
  This is a single-node call.
687 a8083063 Iustin Pop

688 a8083063 Iustin Pop
  """
689 319856a9 Michael Hanselmann
  c = Client("blockdev_snapshot", [cf_bdev.ToDict()])
690 a8083063 Iustin Pop
  c.connect(node)
691 a8083063 Iustin Pop
  c.run()
692 a8083063 Iustin Pop
  return c.getresult().get(node, False)
693 a8083063 Iustin Pop
694 a8083063 Iustin Pop
695 a8083063 Iustin Pop
def call_snapshot_export(node, snap_bdev, dest_node, instance):
696 a8083063 Iustin Pop
  """Request the export of a given snapshot.
697 a8083063 Iustin Pop

698 a8083063 Iustin Pop
  This is a single-node call.
699 a8083063 Iustin Pop

700 a8083063 Iustin Pop
  """
701 319856a9 Michael Hanselmann
  params = [snap_bdev.ToDict(), dest_node, instance.ToDict()]
702 a8083063 Iustin Pop
  c = Client("snapshot_export", params)
703 a8083063 Iustin Pop
  c.connect(node)
704 a8083063 Iustin Pop
  c.run()
705 a8083063 Iustin Pop
  return c.getresult().get(node, False)
706 a8083063 Iustin Pop
707 a8083063 Iustin Pop
708 a8083063 Iustin Pop
def call_finalize_export(node, instance, snap_disks):
709 a8083063 Iustin Pop
  """Request the completion of an export operation.
710 a8083063 Iustin Pop

711 a8083063 Iustin Pop
  This writes the export config file, etc.
712 a8083063 Iustin Pop

713 a8083063 Iustin Pop
  This is a single-node call.
714 a8083063 Iustin Pop

715 a8083063 Iustin Pop
  """
716 a8083063 Iustin Pop
  flat_disks = []
717 a8083063 Iustin Pop
  for disk in snap_disks:
718 319856a9 Michael Hanselmann
    flat_disks.append(disk.ToDict())
719 319856a9 Michael Hanselmann
  params = [instance.ToDict(), flat_disks]
720 a8083063 Iustin Pop
  c = Client("finalize_export", params)
721 a8083063 Iustin Pop
  c.connect(node)
722 a8083063 Iustin Pop
  c.run()
723 a8083063 Iustin Pop
  return c.getresult().get(node, False)
724 a8083063 Iustin Pop
725 a8083063 Iustin Pop
726 a8083063 Iustin Pop
def call_export_info(node, path):
727 a8083063 Iustin Pop
  """Queries the export information in a given path.
728 a8083063 Iustin Pop

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

731 a8083063 Iustin Pop
  """
732 a8083063 Iustin Pop
  c = Client("export_info", [path])
733 a8083063 Iustin Pop
  c.connect(node)
734 a8083063 Iustin Pop
  c.run()
735 a8083063 Iustin Pop
  result = c.getresult().get(node, False)
736 a8083063 Iustin Pop
  if not result:
737 a8083063 Iustin Pop
    return result
738 a8083063 Iustin Pop
  return objects.SerializableConfigParser.Loads(result)
739 a8083063 Iustin Pop
740 a8083063 Iustin Pop
741 a8083063 Iustin Pop
def call_instance_os_import(node, inst, osdev, swapdev, src_node, src_image):
742 a8083063 Iustin Pop
  """Request the import of a backup into an instance.
743 a8083063 Iustin Pop

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

746 a8083063 Iustin Pop
  """
747 319856a9 Michael Hanselmann
  params = [inst.ToDict(), osdev, swapdev, src_node, src_image]
748 a8083063 Iustin Pop
  c = Client("instance_os_import", params)
749 a8083063 Iustin Pop
  c.connect(node)
750 a8083063 Iustin Pop
  c.run()
751 a8083063 Iustin Pop
  return c.getresult().get(node, False)
752 a8083063 Iustin Pop
753 a8083063 Iustin Pop
754 a8083063 Iustin Pop
def call_export_list(node_list):
755 a8083063 Iustin Pop
  """Gets the stored exports list.
756 a8083063 Iustin Pop

757 a8083063 Iustin Pop
  This is a multi-node call.
758 a8083063 Iustin Pop

759 a8083063 Iustin Pop
  """
760 a8083063 Iustin Pop
  c = Client("export_list", [])
761 a8083063 Iustin Pop
  c.connect_list(node_list)
762 a8083063 Iustin Pop
  c.run()
763 a8083063 Iustin Pop
  result = c.getresult()
764 a8083063 Iustin Pop
  return result
765 a8083063 Iustin Pop
766 a8083063 Iustin Pop
767 a8083063 Iustin Pop
def call_export_remove(node, export):
768 a8083063 Iustin Pop
  """Requests removal of a given export.
769 a8083063 Iustin Pop

770 a8083063 Iustin Pop
  This is a single-node call.
771 a8083063 Iustin Pop

772 a8083063 Iustin Pop
  """
773 a8083063 Iustin Pop
  c = Client("export_remove", [export])
774 a8083063 Iustin Pop
  c.connect(node)
775 a8083063 Iustin Pop
  c.run()
776 a8083063 Iustin Pop
  return c.getresult().get(node, False)
777 a8083063 Iustin Pop
778 a8083063 Iustin Pop
779 a8083063 Iustin Pop
def call_node_leave_cluster(node):
780 a8083063 Iustin Pop
  """Requests a node to clean the cluster information it has.
781 a8083063 Iustin Pop

782 a8083063 Iustin Pop
  This will remove the configuration information from the ganeti data
783 a8083063 Iustin Pop
  dir.
784 a8083063 Iustin Pop

785 a8083063 Iustin Pop
  This is a single-node call.
786 a8083063 Iustin Pop

787 a8083063 Iustin Pop
  """
788 a8083063 Iustin Pop
  c = Client("node_leave_cluster", [])
789 a8083063 Iustin Pop
  c.connect(node)
790 a8083063 Iustin Pop
  c.run()
791 a8083063 Iustin Pop
  return c.getresult().get(node, False)
792 dcb93971 Michael Hanselmann
793 dcb93971 Michael Hanselmann
794 dcb93971 Michael Hanselmann
def call_node_volumes(node_list):
795 dcb93971 Michael Hanselmann
  """Gets all volumes on node(s).
796 dcb93971 Michael Hanselmann

797 dcb93971 Michael Hanselmann
  This is a multi-node call.
798 dcb93971 Michael Hanselmann

799 dcb93971 Michael Hanselmann
  """
800 dcb93971 Michael Hanselmann
  c = Client("node_volumes", [])
801 dcb93971 Michael Hanselmann
  c.connect_list(node_list)
802 dcb93971 Michael Hanselmann
  c.run()
803 dcb93971 Michael Hanselmann
  return c.getresult()