Statistics
| Branch: | Tag: | Revision:

root / lib / rpc.py @ dcb93971

History | View | Annotate | Download (18.3 kB)

1 a8083063 Iustin Pop
#!/usr/bin/python
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 a8083063 Iustin Pop
  """A re-startable Reactor implementation"""
34 a8083063 Iustin Pop
35 a8083063 Iustin Pop
  def run(self, installSignalHandlers=1):
36 a8083063 Iustin Pop
    """Custom run method.
37 a8083063 Iustin Pop

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

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

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

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

88 a8083063 Iustin Pop
    """
89 a8083063 Iustin Pop
    if len(self.parent.results) == len(self.parent.nc):
90 a8083063 Iustin Pop
      reactor.stop()
91 a8083063 Iustin Pop
92 a8083063 Iustin Pop
  def cb_call(self, obj):
93 a8083063 Iustin Pop
    """Callback for successfull connect.
94 a8083063 Iustin Pop

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

306 a8083063 Iustin Pop
  """
307 a8083063 Iustin Pop
  c = Client("instance_shutdown", [instance.Dumps()])
308 a8083063 Iustin Pop
  c.connect(node)
309 a8083063 Iustin Pop
  c.run()
310 a8083063 Iustin Pop
  return c.getresult().get(node, False)
311 a8083063 Iustin Pop
312 a8083063 Iustin Pop
313 a8083063 Iustin Pop
def call_instance_os_add(node, inst, osdev, swapdev):
314 a8083063 Iustin Pop
  """Installs an OS on the given instance.
315 a8083063 Iustin Pop

316 a8083063 Iustin Pop
  This is a single-node call.
317 a8083063 Iustin Pop

318 a8083063 Iustin Pop
  """
319 a8083063 Iustin Pop
  params = [inst.Dumps(), osdev, swapdev]
320 a8083063 Iustin Pop
  c = Client("instance_os_add", params)
321 a8083063 Iustin Pop
  c.connect(node)
322 a8083063 Iustin Pop
  c.run()
323 a8083063 Iustin Pop
  return c.getresult().get(node, False)
324 a8083063 Iustin Pop
325 a8083063 Iustin Pop
326 a8083063 Iustin Pop
def call_instance_info(node, instance):
327 a8083063 Iustin Pop
  """Returns information about a single instance.
328 a8083063 Iustin Pop

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

331 a8083063 Iustin Pop
  """
332 a8083063 Iustin Pop
  c = Client("instance_info", [instance])
333 a8083063 Iustin Pop
  c.connect(node)
334 a8083063 Iustin Pop
  c.run()
335 a8083063 Iustin Pop
  return c.getresult().get(node, False)
336 a8083063 Iustin Pop
337 a8083063 Iustin Pop
338 a8083063 Iustin Pop
def call_all_instances_info(node_list):
339 a8083063 Iustin Pop
  """Returns information about all instances on a given node.
340 a8083063 Iustin Pop

341 a8083063 Iustin Pop
  This is a single-node call.
342 a8083063 Iustin Pop

343 a8083063 Iustin Pop
  """
344 a8083063 Iustin Pop
  c = Client("all_instances_info", [])
345 a8083063 Iustin Pop
  c.connect_list(node_list)
346 a8083063 Iustin Pop
  c.run()
347 a8083063 Iustin Pop
  return c.getresult()
348 a8083063 Iustin Pop
349 a8083063 Iustin Pop
350 a8083063 Iustin Pop
def call_instance_list(node_list):
351 a8083063 Iustin Pop
  """Returns the list of running instances on a given node.
352 a8083063 Iustin Pop

353 a8083063 Iustin Pop
  This is a single-node call.
354 a8083063 Iustin Pop

355 a8083063 Iustin Pop
  """
356 a8083063 Iustin Pop
  c = Client("instance_list", [])
357 a8083063 Iustin Pop
  c.connect_list(node_list)
358 a8083063 Iustin Pop
  c.run()
359 a8083063 Iustin Pop
  return c.getresult()
360 a8083063 Iustin Pop
361 a8083063 Iustin Pop
362 a8083063 Iustin Pop
def call_node_info(node_list, vg_name):
363 a8083063 Iustin Pop
  """Return node information.
364 a8083063 Iustin Pop

365 a8083063 Iustin Pop
  This will return memory information and volume group size and free
366 a8083063 Iustin Pop
  space.
367 a8083063 Iustin Pop

368 a8083063 Iustin Pop
  This is a multi-node call.
369 a8083063 Iustin Pop

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

396 a8083063 Iustin Pop
  This is a single-node call.
397 a8083063 Iustin Pop

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

409 a8083063 Iustin Pop
  This is a multi-node call.
410 a8083063 Iustin Pop

411 a8083063 Iustin Pop
  """
412 a8083063 Iustin Pop
  c = Client("node_verify", [checkdict])
413 a8083063 Iustin Pop
  c.connect_list(node_list)
414 a8083063 Iustin Pop
  c.run()
415 a8083063 Iustin Pop
  return c.getresult()
416 a8083063 Iustin Pop
417 a8083063 Iustin Pop
418 a8083063 Iustin Pop
def call_node_start_master(node):
419 a8083063 Iustin Pop
  """Tells a node to activate itself as a master.
420 a8083063 Iustin Pop

421 a8083063 Iustin Pop
  This is a single-node call.
422 a8083063 Iustin Pop

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

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

435 a8083063 Iustin Pop
  """
436 a8083063 Iustin Pop
  c = Client("node_stop_master", [])
437 a8083063 Iustin Pop
  c.connect(node)
438 a8083063 Iustin Pop
  c.run()
439 a8083063 Iustin Pop
  return c.getresult().get(node, False)
440 a8083063 Iustin Pop
441 a8083063 Iustin Pop
442 a8083063 Iustin Pop
def call_version(node_list):
443 a8083063 Iustin Pop
  """Query node version.
444 a8083063 Iustin Pop

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

447 a8083063 Iustin Pop
  """
448 a8083063 Iustin Pop
  c = Client("version", [])
449 a8083063 Iustin Pop
  c.connect_list(node_list)
450 a8083063 Iustin Pop
  c.run()
451 a8083063 Iustin Pop
  return c.getresult()
452 a8083063 Iustin Pop
453 a8083063 Iustin Pop
454 a8083063 Iustin Pop
def call_configfile_list(node_list):
455 a8083063 Iustin Pop
  """Return list of existing configuration files.
456 a8083063 Iustin Pop

457 a8083063 Iustin Pop
  This is a multi-node call.
458 a8083063 Iustin Pop

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

468 a8083063 Iustin Pop
  This is a single-node call.
469 a8083063 Iustin Pop

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

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

483 a8083063 Iustin Pop
  """
484 a8083063 Iustin Pop
  c = Client("blockdev_remove", [bdev.Dumps()])
485 a8083063 Iustin Pop
  c.connect(node)
486 a8083063 Iustin Pop
  c.run()
487 a8083063 Iustin Pop
  return c.getresult().get(node, False)
488 a8083063 Iustin Pop
489 a8083063 Iustin Pop
490 a8083063 Iustin Pop
def call_blockdev_assemble(node, disk, on_primary):
491 a8083063 Iustin Pop
  """Request assembling of a given block device.
492 a8083063 Iustin Pop

493 a8083063 Iustin Pop
  This is a single-node call.
494 a8083063 Iustin Pop

495 a8083063 Iustin Pop
  """
496 a8083063 Iustin Pop
  params = [disk.Dumps(), on_primary]
497 a8083063 Iustin Pop
  c = Client("blockdev_assemble", params)
498 a8083063 Iustin Pop
  c.connect(node)
499 a8083063 Iustin Pop
  c.run()
500 a8083063 Iustin Pop
  return c.getresult().get(node, False)
501 a8083063 Iustin Pop
502 a8083063 Iustin Pop
503 a8083063 Iustin Pop
def call_blockdev_shutdown(node, disk):
504 a8083063 Iustin Pop
  """Request shutdown of a given block device.
505 a8083063 Iustin Pop

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

508 a8083063 Iustin Pop
  """
509 a8083063 Iustin Pop
  c = Client("blockdev_shutdown", [disk.Dumps()])
510 a8083063 Iustin Pop
  c.connect(node)
511 a8083063 Iustin Pop
  c.run()
512 a8083063 Iustin Pop
  return c.getresult().get(node, False)
513 a8083063 Iustin Pop
514 a8083063 Iustin Pop
515 a8083063 Iustin Pop
def call_blockdev_addchild(node, bdev, ndev):
516 a8083063 Iustin Pop
  """Request adding a new child to a (mirroring) device.
517 a8083063 Iustin Pop

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

520 a8083063 Iustin Pop
  """
521 a8083063 Iustin Pop
  params = [bdev.Dumps(), ndev.Dumps()]
522 a8083063 Iustin Pop
  c = Client("blockdev_addchild", params)
523 a8083063 Iustin Pop
  c.connect(node)
524 a8083063 Iustin Pop
  c.run()
525 a8083063 Iustin Pop
  return c.getresult().get(node, False)
526 a8083063 Iustin Pop
527 a8083063 Iustin Pop
528 a8083063 Iustin Pop
def call_blockdev_removechild(node, bdev, ndev):
529 a8083063 Iustin Pop
  """Request removing a new child from a (mirroring) device.
530 a8083063 Iustin Pop

531 a8083063 Iustin Pop
  This is a single-node call.
532 a8083063 Iustin Pop

533 a8083063 Iustin Pop
  """
534 a8083063 Iustin Pop
  params = [bdev.Dumps(), ndev.Dumps()]
535 a8083063 Iustin Pop
  c = Client("blockdev_removechild", params)
536 a8083063 Iustin Pop
  c.connect(node)
537 a8083063 Iustin Pop
  c.run()
538 a8083063 Iustin Pop
  return c.getresult().get(node, False)
539 a8083063 Iustin Pop
540 a8083063 Iustin Pop
541 a8083063 Iustin Pop
def call_blockdev_getmirrorstatus(node, disks):
542 a8083063 Iustin Pop
  """Request status of a (mirroring) device.
543 a8083063 Iustin Pop

544 a8083063 Iustin Pop
  This is a single-node call.
545 a8083063 Iustin Pop

546 a8083063 Iustin Pop
  """
547 a8083063 Iustin Pop
  params = [dsk.Dumps() for dsk in disks]
548 a8083063 Iustin Pop
  c = Client("blockdev_getmirrorstatus", params)
549 a8083063 Iustin Pop
  c.connect(node)
550 a8083063 Iustin Pop
  c.run()
551 a8083063 Iustin Pop
  return c.getresult().get(node, False)
552 a8083063 Iustin Pop
553 a8083063 Iustin Pop
554 a8083063 Iustin Pop
def call_blockdev_find(node, disk):
555 a8083063 Iustin Pop
  """Request identification of a given block device.
556 a8083063 Iustin Pop

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

559 a8083063 Iustin Pop
  """
560 a8083063 Iustin Pop
  c = Client("blockdev_find", [disk.Dumps()])
561 a8083063 Iustin Pop
  c.connect(node)
562 a8083063 Iustin Pop
  c.run()
563 a8083063 Iustin Pop
  return c.getresult().get(node, False)
564 a8083063 Iustin Pop
565 a8083063 Iustin Pop
566 a8083063 Iustin Pop
def call_upload_file(node_list, file_name):
567 a8083063 Iustin Pop
  """Upload a file.
568 a8083063 Iustin Pop

569 a8083063 Iustin Pop
  The node will refuse the operation in case the file is not on the
570 a8083063 Iustin Pop
  approved file list.
571 a8083063 Iustin Pop

572 a8083063 Iustin Pop
  This is a multi-node call.
573 a8083063 Iustin Pop

574 a8083063 Iustin Pop
  """
575 a8083063 Iustin Pop
  fh = file(file_name)
576 a8083063 Iustin Pop
  try:
577 a8083063 Iustin Pop
    data = fh.read()
578 a8083063 Iustin Pop
  finally:
579 a8083063 Iustin Pop
    fh.close()
580 a8083063 Iustin Pop
  st = os.stat(file_name)
581 a8083063 Iustin Pop
  params = [file_name, data, st.st_mode, st.st_uid, st.st_gid,
582 a8083063 Iustin Pop
            st.st_atime, st.st_mtime]
583 a8083063 Iustin Pop
  c = Client("upload_file", params)
584 a8083063 Iustin Pop
  c.connect_list(node_list)
585 a8083063 Iustin Pop
  c.run()
586 a8083063 Iustin Pop
  return c.getresult()
587 a8083063 Iustin Pop
588 a8083063 Iustin Pop
589 a8083063 Iustin Pop
def call_os_diagnose(node_list):
590 a8083063 Iustin Pop
  """Request a diagnose of OS definitions.
591 a8083063 Iustin Pop

592 a8083063 Iustin Pop
  This is a multi-node call.
593 a8083063 Iustin Pop

594 a8083063 Iustin Pop
  """
595 a8083063 Iustin Pop
  c = Client("os_diagnose", [])
596 a8083063 Iustin Pop
  c.connect_list(node_list)
597 a8083063 Iustin Pop
  c.run()
598 a8083063 Iustin Pop
  result = c.getresult()
599 a8083063 Iustin Pop
  new_result = {}
600 a8083063 Iustin Pop
  for node_name in result:
601 a8083063 Iustin Pop
    nr = []
602 a8083063 Iustin Pop
    if result[node_name]:
603 a8083063 Iustin Pop
      for data in result[node_name]:
604 a8083063 Iustin Pop
        if data:
605 a8083063 Iustin Pop
          if isinstance(data, basestring):
606 a8083063 Iustin Pop
            nr.append(objects.ConfigObject.Loads(data))
607 a8083063 Iustin Pop
          elif isinstance(data, tuple) and len(data) == 2:
608 a8083063 Iustin Pop
            nr.append(errors.InvalidOS(data[0], data[1]))
609 a8083063 Iustin Pop
          else:
610 a8083063 Iustin Pop
            raise errors.ProgrammerError, ("Invalid data from"
611 a8083063 Iustin Pop
                                           " xcserver.os_diagnose")
612 a8083063 Iustin Pop
    new_result[node_name] = nr
613 a8083063 Iustin Pop
  return new_result
614 a8083063 Iustin Pop
615 a8083063 Iustin Pop
616 a8083063 Iustin Pop
def call_os_get(node_list, name):
617 a8083063 Iustin Pop
  """Returns an OS definition.
618 a8083063 Iustin Pop

619 a8083063 Iustin Pop
  This is a multi-node call.
620 a8083063 Iustin Pop

621 a8083063 Iustin Pop
  """
622 a8083063 Iustin Pop
  c = Client("os_get", [name])
623 a8083063 Iustin Pop
  c.connect_list(node_list)
624 a8083063 Iustin Pop
  c.run()
625 a8083063 Iustin Pop
  result = c.getresult()
626 a8083063 Iustin Pop
  new_result = {}
627 a8083063 Iustin Pop
  for node_name in result:
628 a8083063 Iustin Pop
    data = result[node_name]
629 a8083063 Iustin Pop
    if isinstance(data, basestring):
630 a8083063 Iustin Pop
      new_result[node_name] = objects.ConfigObject.Loads(data)
631 a8083063 Iustin Pop
    elif isinstance(data, tuple) and len(data) == 2:
632 a8083063 Iustin Pop
      new_result[node_name] = errors.InvalidOS(data[0], data[1])
633 a8083063 Iustin Pop
    else:
634 a8083063 Iustin Pop
      new_result[node_name] = data
635 a8083063 Iustin Pop
  return new_result
636 a8083063 Iustin Pop
637 a8083063 Iustin Pop
638 a8083063 Iustin Pop
def call_hooks_runner(node_list, hpath, phase, env):
639 a8083063 Iustin Pop
  """Call the hooks runner.
640 a8083063 Iustin Pop

641 a8083063 Iustin Pop
  Args:
642 a8083063 Iustin Pop
    - op: the OpCode instance
643 a8083063 Iustin Pop
    - env: a dictionary with the environment
644 a8083063 Iustin Pop

645 a8083063 Iustin Pop
  This is a multi-node call.
646 a8083063 Iustin Pop

647 a8083063 Iustin Pop
  """
648 a8083063 Iustin Pop
  params = [hpath, phase, env]
649 a8083063 Iustin Pop
  c = Client("hooks_runner", params)
650 a8083063 Iustin Pop
  c.connect_list(node_list)
651 a8083063 Iustin Pop
  c.run()
652 a8083063 Iustin Pop
  result = c.getresult()
653 a8083063 Iustin Pop
  return result
654 a8083063 Iustin Pop
655 a8083063 Iustin Pop
656 a8083063 Iustin Pop
def call_blockdev_snapshot(node, cf_bdev):
657 a8083063 Iustin Pop
  """Request a snapshot of the given block device.
658 a8083063 Iustin Pop

659 a8083063 Iustin Pop
  This is a single-node call.
660 a8083063 Iustin Pop

661 a8083063 Iustin Pop
  """
662 a8083063 Iustin Pop
  c = Client("blockdev_snapshot", [cf_bdev.Dumps()])
663 a8083063 Iustin Pop
  c.connect(node)
664 a8083063 Iustin Pop
  c.run()
665 a8083063 Iustin Pop
  return c.getresult().get(node, False)
666 a8083063 Iustin Pop
667 a8083063 Iustin Pop
668 a8083063 Iustin Pop
def call_snapshot_export(node, snap_bdev, dest_node, instance):
669 a8083063 Iustin Pop
  """Request the export of a given snapshot.
670 a8083063 Iustin Pop

671 a8083063 Iustin Pop
  This is a single-node call.
672 a8083063 Iustin Pop

673 a8083063 Iustin Pop
  """
674 a8083063 Iustin Pop
  params = [snap_bdev.Dumps(), dest_node, instance.Dumps()]
675 a8083063 Iustin Pop
  c = Client("snapshot_export", params)
676 a8083063 Iustin Pop
  c.connect(node)
677 a8083063 Iustin Pop
  c.run()
678 a8083063 Iustin Pop
  return c.getresult().get(node, False)
679 a8083063 Iustin Pop
680 a8083063 Iustin Pop
681 a8083063 Iustin Pop
def call_finalize_export(node, instance, snap_disks):
682 a8083063 Iustin Pop
  """Request the completion of an export operation.
683 a8083063 Iustin Pop

684 a8083063 Iustin Pop
  This writes the export config file, etc.
685 a8083063 Iustin Pop

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

688 a8083063 Iustin Pop
  """
689 a8083063 Iustin Pop
  flat_disks = []
690 a8083063 Iustin Pop
  for disk in snap_disks:
691 a8083063 Iustin Pop
    flat_disks.append(disk.Dumps())
692 a8083063 Iustin Pop
  params = [instance.Dumps(), flat_disks]
693 a8083063 Iustin Pop
  c = Client("finalize_export", params)
694 a8083063 Iustin Pop
  c.connect(node)
695 a8083063 Iustin Pop
  c.run()
696 a8083063 Iustin Pop
  return c.getresult().get(node, False)
697 a8083063 Iustin Pop
698 a8083063 Iustin Pop
699 a8083063 Iustin Pop
def call_export_info(node, path):
700 a8083063 Iustin Pop
  """Queries the export information in a given path.
701 a8083063 Iustin Pop

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

704 a8083063 Iustin Pop
  """
705 a8083063 Iustin Pop
  c = Client("export_info", [path])
706 a8083063 Iustin Pop
  c.connect(node)
707 a8083063 Iustin Pop
  c.run()
708 a8083063 Iustin Pop
  result = c.getresult().get(node, False)
709 a8083063 Iustin Pop
  if not result:
710 a8083063 Iustin Pop
    return result
711 a8083063 Iustin Pop
  return objects.SerializableConfigParser.Loads(result)
712 a8083063 Iustin Pop
713 a8083063 Iustin Pop
714 a8083063 Iustin Pop
def call_instance_os_import(node, inst, osdev, swapdev, src_node, src_image):
715 a8083063 Iustin Pop
  """Request the import of a backup into an instance.
716 a8083063 Iustin Pop

717 a8083063 Iustin Pop
  This is a single-node call.
718 a8083063 Iustin Pop

719 a8083063 Iustin Pop
  """
720 a8083063 Iustin Pop
  params = [inst.Dumps(), osdev, swapdev, src_node, src_image]
721 a8083063 Iustin Pop
  c = Client("instance_os_import", params)
722 a8083063 Iustin Pop
  c.connect(node)
723 a8083063 Iustin Pop
  c.run()
724 a8083063 Iustin Pop
  return c.getresult().get(node, False)
725 a8083063 Iustin Pop
726 a8083063 Iustin Pop
727 a8083063 Iustin Pop
def call_export_list(node_list):
728 a8083063 Iustin Pop
  """Gets the stored exports list.
729 a8083063 Iustin Pop

730 a8083063 Iustin Pop
  This is a multi-node call.
731 a8083063 Iustin Pop

732 a8083063 Iustin Pop
  """
733 a8083063 Iustin Pop
  c = Client("export_list", [])
734 a8083063 Iustin Pop
  c.connect_list(node_list)
735 a8083063 Iustin Pop
  c.run()
736 a8083063 Iustin Pop
  result = c.getresult()
737 a8083063 Iustin Pop
  return result
738 a8083063 Iustin Pop
739 a8083063 Iustin Pop
740 a8083063 Iustin Pop
def call_export_remove(node, export):
741 a8083063 Iustin Pop
  """Requests removal of a given export.
742 a8083063 Iustin Pop

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

745 a8083063 Iustin Pop
  """
746 a8083063 Iustin Pop
  c = Client("export_remove", [export])
747 a8083063 Iustin Pop
  c.connect(node)
748 a8083063 Iustin Pop
  c.run()
749 a8083063 Iustin Pop
  return c.getresult().get(node, False)
750 a8083063 Iustin Pop
751 a8083063 Iustin Pop
752 a8083063 Iustin Pop
def call_node_leave_cluster(node):
753 a8083063 Iustin Pop
  """Requests a node to clean the cluster information it has.
754 a8083063 Iustin Pop

755 a8083063 Iustin Pop
  This will remove the configuration information from the ganeti data
756 a8083063 Iustin Pop
  dir.
757 a8083063 Iustin Pop

758 a8083063 Iustin Pop
  This is a single-node call.
759 a8083063 Iustin Pop

760 a8083063 Iustin Pop
  """
761 a8083063 Iustin Pop
  c = Client("node_leave_cluster", [])
762 a8083063 Iustin Pop
  c.connect(node)
763 a8083063 Iustin Pop
  c.run()
764 a8083063 Iustin Pop
  return c.getresult().get(node, False)
765 dcb93971 Michael Hanselmann
766 dcb93971 Michael Hanselmann
767 dcb93971 Michael Hanselmann
def call_node_volumes(node_list):
768 dcb93971 Michael Hanselmann
  """Gets all volumes on node(s).
769 dcb93971 Michael Hanselmann

770 dcb93971 Michael Hanselmann
  This is a multi-node call.
771 dcb93971 Michael Hanselmann

772 dcb93971 Michael Hanselmann
  """
773 dcb93971 Michael Hanselmann
  c = Client("node_volumes", [])
774 dcb93971 Michael Hanselmann
  c.connect_list(node_list)
775 dcb93971 Michael Hanselmann
  c.run()
776 dcb93971 Michael Hanselmann
  return c.getresult()