Statistics
| Branch: | Tag: | Revision:

root / scripts / gnt-cluster @ c4ed32cb

History | View | Annotate | Download (22.9 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 2f79bd34 Iustin Pop
# pylint: disable-msg=W0401,W0614
23 2f79bd34 Iustin Pop
# W0401: Wildcard import ganeti.cli
24 2f79bd34 Iustin Pop
# W0614: Unused import %s from wildcard import (since we need cli)
25 2f79bd34 Iustin Pop
26 a8083063 Iustin Pop
import sys
27 a8083063 Iustin Pop
from optparse import make_option
28 b3989551 Iustin Pop
import os.path
29 a8083063 Iustin Pop
30 a8083063 Iustin Pop
from ganeti.cli import *
31 a8083063 Iustin Pop
from ganeti import opcodes
32 c2a62a33 Michael Hanselmann
from ganeti import constants
33 f4d4e184 Iustin Pop
from ganeti import errors
34 b63ed789 Iustin Pop
from ganeti import utils
35 a0c9f010 Michael Hanselmann
from ganeti import bootstrap
36 b3989551 Iustin Pop
from ganeti import ssh
37 a8083063 Iustin Pop
38 a8083063 Iustin Pop
39 4331f6cd Michael Hanselmann
@UsesRPC
40 a8083063 Iustin Pop
def InitCluster(opts, args):
41 a8083063 Iustin Pop
  """Initialize the cluster.
42 a8083063 Iustin Pop
43 469ee405 Iustin Pop
  @param opts: the command line options selected by the user
44 469ee405 Iustin Pop
  @type args: list
45 469ee405 Iustin Pop
  @param args: should contain only one element, the desired
46 469ee405 Iustin Pop
      cluster name
47 469ee405 Iustin Pop
  @rtype: int
48 469ee405 Iustin Pop
  @return: the desired exit code
49 a8083063 Iustin Pop
50 a8083063 Iustin Pop
  """
51 90b6aa3a Manuel Franceschini
  if not opts.lvm_storage and opts.vg_name:
52 3a24c527 Iustin Pop
    ToStderr("Options --no-lvm-storage and --vg-name conflict.")
53 90b6aa3a Manuel Franceschini
    return 1
54 90b6aa3a Manuel Franceschini
55 90b6aa3a Manuel Franceschini
  vg_name = opts.vg_name
56 90b6aa3a Manuel Franceschini
  if opts.lvm_storage and not opts.vg_name:
57 90b6aa3a Manuel Franceschini
    vg_name = constants.DEFAULT_VG
58 90b6aa3a Manuel Franceschini
59 ea3a925f Alexander Schreiber
  hvlist = opts.enabled_hypervisors
60 ea3a925f Alexander Schreiber
  if hvlist is not None:
61 ea3a925f Alexander Schreiber
    hvlist = hvlist.split(",")
62 ea3a925f Alexander Schreiber
  else:
63 8f348e36 Guido Trotter
    hvlist = [opts.default_hypervisor]
64 02691904 Alexander Schreiber
65 02691904 Alexander Schreiber
  # avoid an impossible situation
66 8f348e36 Guido Trotter
  if opts.default_hypervisor not in hvlist:
67 8f348e36 Guido Trotter
    ToStderr("The default hypervisor requested (%s) is not"
68 8f348e36 Guido Trotter
             " within the enabled hypervisor list (%s)" %
69 8f348e36 Guido Trotter
             (opts.default_hypervisor, hvlist))
70 8f348e36 Guido Trotter
    return 1
71 ea3a925f Alexander Schreiber
72 ea3a925f Alexander Schreiber
  hvparams = opts.hvparams
73 ea3a925f Alexander Schreiber
  if hvparams:
74 ea3a925f Alexander Schreiber
    # a list of (name, dict) we can pass directly to dict()
75 ea3a925f Alexander Schreiber
    hvparams = dict(opts.hvparams)
76 ea3a925f Alexander Schreiber
  else:
77 ea3a925f Alexander Schreiber
    # otherwise init as empty dict
78 ea3a925f Alexander Schreiber
    hvparams = {}
79 ea3a925f Alexander Schreiber
80 ea3a925f Alexander Schreiber
  beparams = opts.beparams
81 ea3a925f Alexander Schreiber
  # check for invalid parameters
82 ea3a925f Alexander Schreiber
  for parameter in beparams:
83 ea3a925f Alexander Schreiber
    if parameter not in constants.BES_PARAMETERS:
84 1f9611b1 Alexander Schreiber
      ToStderr("Invalid backend parameter: %s", parameter)
85 ea3a925f Alexander Schreiber
      return 1
86 ea3a925f Alexander Schreiber
87 ea3a925f Alexander Schreiber
  # prepare beparams dict
88 ea3a925f Alexander Schreiber
  for parameter in constants.BES_PARAMETERS:
89 ea3a925f Alexander Schreiber
    if parameter not in beparams:
90 ea3a925f Alexander Schreiber
      beparams[parameter] = constants.BEC_DEFAULTS[parameter]
91 ea3a925f Alexander Schreiber
92 ea3a925f Alexander Schreiber
  # type wrangling
93 ea3a925f Alexander Schreiber
  try:
94 ea3a925f Alexander Schreiber
    beparams[constants.BE_VCPUS] = int(beparams[constants.BE_VCPUS])
95 ea3a925f Alexander Schreiber
  except ValueError:
96 1f9611b1 Alexander Schreiber
    ToStderr("%s must be an integer", constants.BE_VCPUS)
97 ea3a925f Alexander Schreiber
    return 1
98 ea3a925f Alexander Schreiber
99 00dd8326 Alexander Schreiber
  if not isinstance(beparams[constants.BE_MEMORY], int):
100 00dd8326 Alexander Schreiber
    beparams[constants.BE_MEMORY] = utils.ParseUnit(
101 00dd8326 Alexander Schreiber
        beparams[constants.BE_MEMORY])
102 ea3a925f Alexander Schreiber
103 ea3a925f Alexander Schreiber
  # prepare hvparams dict
104 ea3a925f Alexander Schreiber
  for hv in constants.HYPER_TYPES:
105 ea3a925f Alexander Schreiber
    if hv not in hvparams:
106 ea3a925f Alexander Schreiber
      hvparams[hv] = {}
107 ea3a925f Alexander Schreiber
    for parameter in constants.HVC_DEFAULTS[hv]:
108 ea3a925f Alexander Schreiber
      if parameter not in hvparams[hv]:
109 ea3a925f Alexander Schreiber
        hvparams[hv][parameter] = constants.HVC_DEFAULTS[hv][parameter]
110 ea3a925f Alexander Schreiber
111 ea3a925f Alexander Schreiber
  for hv in hvlist:
112 ea3a925f Alexander Schreiber
    if hv not in constants.HYPER_TYPES:
113 1f9611b1 Alexander Schreiber
      ToStderr("invalid hypervisor: %s", hv)
114 ea3a925f Alexander Schreiber
      return 1
115 ea3a925f Alexander Schreiber
116 a0c9f010 Michael Hanselmann
  bootstrap.InitCluster(cluster_name=args[0],
117 a0c9f010 Michael Hanselmann
                        secondary_ip=opts.secondary_ip,
118 a0c9f010 Michael Hanselmann
                        vg_name=vg_name,
119 a0c9f010 Michael Hanselmann
                        mac_prefix=opts.mac_prefix,
120 a0c9f010 Michael Hanselmann
                        def_bridge=opts.def_bridge,
121 a0c9f010 Michael Hanselmann
                        master_netdev=opts.master_netdev,
122 ea3a925f Alexander Schreiber
                        file_storage_dir=opts.file_storage_dir,
123 ea3a925f Alexander Schreiber
                        enabled_hypervisors=hvlist,
124 8f348e36 Guido Trotter
                        default_hypervisor=opts.default_hypervisor,
125 ea3a925f Alexander Schreiber
                        hvparams=hvparams,
126 ce735215 Guido Trotter
                        beparams=beparams,
127 ce735215 Guido Trotter
                        candidate_pool_size=opts.candidate_pool_size,
128 ce735215 Guido Trotter
                        )
129 a8083063 Iustin Pop
  return 0
130 a8083063 Iustin Pop
131 a8083063 Iustin Pop
132 4331f6cd Michael Hanselmann
@UsesRPC
133 a8083063 Iustin Pop
def DestroyCluster(opts, args):
134 a8083063 Iustin Pop
  """Destroy the cluster.
135 a8083063 Iustin Pop
136 469ee405 Iustin Pop
  @param opts: the command line options selected by the user
137 469ee405 Iustin Pop
  @type args: list
138 469ee405 Iustin Pop
  @param args: should be an empty list
139 469ee405 Iustin Pop
  @rtype: int
140 469ee405 Iustin Pop
  @return: the desired exit code
141 098c0958 Michael Hanselmann
142 a8083063 Iustin Pop
  """
143 a8083063 Iustin Pop
  if not opts.yes_do_it:
144 3a24c527 Iustin Pop
    ToStderr("Destroying a cluster is irreversible. If you really want"
145 3a24c527 Iustin Pop
             " destroy this cluster, supply the --yes-do-it option.")
146 a8083063 Iustin Pop
    return 1
147 a8083063 Iustin Pop
148 a8083063 Iustin Pop
  op = opcodes.OpDestroyCluster()
149 140aa4a8 Iustin Pop
  master = SubmitOpCode(op)
150 140aa4a8 Iustin Pop
  # if we reached this, the opcode didn't fail; we can proceed to
151 140aa4a8 Iustin Pop
  # shutdown all the daemons
152 140aa4a8 Iustin Pop
  bootstrap.FinalizeClusterDestroy(master)
153 a8083063 Iustin Pop
  return 0
154 a8083063 Iustin Pop
155 a8083063 Iustin Pop
156 07bd8a51 Iustin Pop
def RenameCluster(opts, args):
157 07bd8a51 Iustin Pop
  """Rename the cluster.
158 07bd8a51 Iustin Pop
159 469ee405 Iustin Pop
  @param opts: the command line options selected by the user
160 469ee405 Iustin Pop
  @type args: list
161 469ee405 Iustin Pop
  @param args: should contain only one element, the new cluster name
162 469ee405 Iustin Pop
  @rtype: int
163 469ee405 Iustin Pop
  @return: the desired exit code
164 07bd8a51 Iustin Pop
165 07bd8a51 Iustin Pop
  """
166 07bd8a51 Iustin Pop
  name = args[0]
167 07bd8a51 Iustin Pop
  if not opts.force:
168 07bd8a51 Iustin Pop
    usertext = ("This will rename the cluster to '%s'. If you are connected"
169 07bd8a51 Iustin Pop
                " over the network to the cluster name, the operation is very"
170 07bd8a51 Iustin Pop
                " dangerous as the IP address will be removed from the node"
171 07bd8a51 Iustin Pop
                " and the change may not go through. Continue?") % name
172 47988778 Iustin Pop
    if not AskUser(usertext):
173 07bd8a51 Iustin Pop
      return 1
174 07bd8a51 Iustin Pop
175 07bd8a51 Iustin Pop
  op = opcodes.OpRenameCluster(name=name)
176 07bd8a51 Iustin Pop
  SubmitOpCode(op)
177 07bd8a51 Iustin Pop
  return 0
178 07bd8a51 Iustin Pop
179 07bd8a51 Iustin Pop
180 afee0879 Iustin Pop
def RedistributeConfig(opts, args):
181 afee0879 Iustin Pop
  """Forces push of the cluster configuration.
182 afee0879 Iustin Pop
183 afee0879 Iustin Pop
  @param opts: the command line options selected by the user
184 afee0879 Iustin Pop
  @type args: list
185 afee0879 Iustin Pop
  @param args: empty list
186 afee0879 Iustin Pop
  @rtype: int
187 afee0879 Iustin Pop
  @return: the desired exit code
188 afee0879 Iustin Pop
189 afee0879 Iustin Pop
  """
190 afee0879 Iustin Pop
  op = opcodes.OpRedistributeConf()
191 afee0879 Iustin Pop
  SubmitOrSend(op, opts)
192 afee0879 Iustin Pop
  return 0
193 afee0879 Iustin Pop
194 afee0879 Iustin Pop
195 a8083063 Iustin Pop
def ShowClusterVersion(opts, args):
196 a8083063 Iustin Pop
  """Write version of ganeti software to the standard output.
197 a8083063 Iustin Pop
198 469ee405 Iustin Pop
  @param opts: the command line options selected by the user
199 469ee405 Iustin Pop
  @type args: list
200 469ee405 Iustin Pop
  @param args: should be an empty list
201 469ee405 Iustin Pop
  @rtype: int
202 469ee405 Iustin Pop
  @return: the desired exit code
203 a8083063 Iustin Pop
204 a8083063 Iustin Pop
  """
205 a8083063 Iustin Pop
  op = opcodes.OpQueryClusterInfo()
206 a8083063 Iustin Pop
  result = SubmitOpCode(op)
207 3a24c527 Iustin Pop
  ToStdout("Software version: %s", result["software_version"])
208 3a24c527 Iustin Pop
  ToStdout("Internode protocol: %s", result["protocol_version"])
209 3a24c527 Iustin Pop
  ToStdout("Configuration format: %s", result["config_version"])
210 3a24c527 Iustin Pop
  ToStdout("OS api version: %s", result["os_api_version"])
211 3a24c527 Iustin Pop
  ToStdout("Export interface: %s", result["export_version"])
212 a8083063 Iustin Pop
  return 0
213 a8083063 Iustin Pop
214 a8083063 Iustin Pop
215 a8083063 Iustin Pop
def ShowClusterMaster(opts, args):
216 a8083063 Iustin Pop
  """Write name of master node to the standard output.
217 a8083063 Iustin Pop
218 469ee405 Iustin Pop
  @param opts: the command line options selected by the user
219 469ee405 Iustin Pop
  @type args: list
220 469ee405 Iustin Pop
  @param args: should be an empty list
221 469ee405 Iustin Pop
  @rtype: int
222 469ee405 Iustin Pop
  @return: the desired exit code
223 a8083063 Iustin Pop
224 a8083063 Iustin Pop
  """
225 3a24c527 Iustin Pop
  ToStdout("%s", GetClient().QueryConfigValues(["master_node"])[0])
226 a8083063 Iustin Pop
  return 0
227 a8083063 Iustin Pop
228 a8083063 Iustin Pop
229 a8083063 Iustin Pop
def ShowClusterConfig(opts, args):
230 a8083063 Iustin Pop
  """Shows cluster information.
231 a8083063 Iustin Pop
232 469ee405 Iustin Pop
  @param opts: the command line options selected by the user
233 469ee405 Iustin Pop
  @type args: list
234 469ee405 Iustin Pop
  @param args: should be an empty list
235 469ee405 Iustin Pop
  @rtype: int
236 469ee405 Iustin Pop
  @return: the desired exit code
237 469ee405 Iustin Pop
238 a8083063 Iustin Pop
  """
239 a8083063 Iustin Pop
  op = opcodes.OpQueryClusterInfo()
240 a8083063 Iustin Pop
  result = SubmitOpCode(op)
241 a8083063 Iustin Pop
242 3a24c527 Iustin Pop
  ToStdout("Cluster name: %s", result["name"])
243 a8083063 Iustin Pop
244 3a24c527 Iustin Pop
  ToStdout("Master node: %s", result["master"])
245 a8083063 Iustin Pop
246 3a24c527 Iustin Pop
  ToStdout("Architecture (this node): %s (%s)",
247 3a24c527 Iustin Pop
           result["architecture"][0], result["architecture"][1])
248 a8083063 Iustin Pop
249 02691904 Alexander Schreiber
  ToStdout("Default hypervisor: %s", result["default_hypervisor"])
250 3a24c527 Iustin Pop
  ToStdout("Enabled hypervisors: %s", ", ".join(result["enabled_hypervisors"]))
251 469f88e1 Iustin Pop
252 3a24c527 Iustin Pop
  ToStdout("Hypervisor parameters:")
253 469f88e1 Iustin Pop
  for hv_name, hv_dict in result["hvparams"].items():
254 3a24c527 Iustin Pop
    ToStdout("  - %s:", hv_name)
255 469f88e1 Iustin Pop
    for item, val in hv_dict.iteritems():
256 3a24c527 Iustin Pop
      ToStdout("      %s: %s", item, val)
257 469f88e1 Iustin Pop
258 3a24c527 Iustin Pop
  ToStdout("Cluster parameters:")
259 4b7735f9 Iustin Pop
  ToStdout("  - candidate pool size: %s", result["candidate_pool_size"])
260 4b7735f9 Iustin Pop
261 4b7735f9 Iustin Pop
  ToStdout("Default instance parameters:")
262 469f88e1 Iustin Pop
  for gr_name, gr_dict in result["beparams"].items():
263 3a24c527 Iustin Pop
    ToStdout("  - %s:", gr_name)
264 469f88e1 Iustin Pop
    for item, val in gr_dict.iteritems():
265 3a24c527 Iustin Pop
      ToStdout("      %s: %s", item, val)
266 8a12ce45 Iustin Pop
267 a8083063 Iustin Pop
  return 0
268 a8083063 Iustin Pop
269 a8083063 Iustin Pop
270 a8083063 Iustin Pop
def ClusterCopyFile(opts, args):
271 a8083063 Iustin Pop
  """Copy a file from master to some nodes.
272 a8083063 Iustin Pop
273 469ee405 Iustin Pop
  @param opts: the command line options selected by the user
274 469ee405 Iustin Pop
  @type args: list
275 469ee405 Iustin Pop
  @param args: should contain only one element, the path of
276 469ee405 Iustin Pop
      the file to be copied
277 469ee405 Iustin Pop
  @rtype: int
278 469ee405 Iustin Pop
  @return: the desired exit code
279 a8083063 Iustin Pop
280 a8083063 Iustin Pop
  """
281 b3989551 Iustin Pop
  filename = args[0]
282 b3989551 Iustin Pop
  if not os.path.exists(filename):
283 b3989551 Iustin Pop
    raise errors.OpPrereqError("No such filename '%s'" % filename)
284 b3989551 Iustin Pop
285 56bece1f Iustin Pop
  cl = GetClient()
286 56bece1f Iustin Pop
287 b3989551 Iustin Pop
  myname = utils.HostInfo().name
288 b3989551 Iustin Pop
289 56bece1f Iustin Pop
  cluster_name = cl.QueryConfigValues(["cluster_name"])[0]
290 56bece1f Iustin Pop
291 4040a784 Iustin Pop
  results = GetOnlineNodes(nodes=opts.nodes, cl=cl)
292 4040a784 Iustin Pop
  results = [name for name in results if name != myname]
293 e00ea635 Michael Hanselmann
294 56bece1f Iustin Pop
  srun = ssh.SshRunner(cluster_name=cluster_name)
295 b3989551 Iustin Pop
  for node in results:
296 b3989551 Iustin Pop
    if not srun.CopyFileToNode(node, filename):
297 3a24c527 Iustin Pop
      ToStderr("Copy of file %s to node %s failed", filename, node)
298 b3989551 Iustin Pop
299 a8083063 Iustin Pop
  return 0
300 a8083063 Iustin Pop
301 a8083063 Iustin Pop
302 a8083063 Iustin Pop
def RunClusterCommand(opts, args):
303 a8083063 Iustin Pop
  """Run a command on some nodes.
304 a8083063 Iustin Pop
305 469ee405 Iustin Pop
  @param opts: the command line options selected by the user
306 469ee405 Iustin Pop
  @type args: list
307 469ee405 Iustin Pop
  @param args: should contain the command to be run and its arguments
308 469ee405 Iustin Pop
  @rtype: int
309 469ee405 Iustin Pop
  @return: the desired exit code
310 a8083063 Iustin Pop
311 a8083063 Iustin Pop
  """
312 56bece1f Iustin Pop
  cl = GetClient()
313 7688d0d3 Michael Hanselmann
314 a8083063 Iustin Pop
  command = " ".join(args)
315 4040a784 Iustin Pop
316 4040a784 Iustin Pop
  nodes = GetOnlineNodes(nodes=opts.nodes, cl=cl)
317 56bece1f Iustin Pop
318 56bece1f Iustin Pop
  cluster_name, master_node = cl.QueryConfigValues(["cluster_name",
319 56bece1f Iustin Pop
                                                    "master_node"])
320 b3989551 Iustin Pop
321 56bece1f Iustin Pop
  srun = ssh.SshRunner(cluster_name=cluster_name)
322 b3989551 Iustin Pop
323 7688d0d3 Michael Hanselmann
  # Make sure master node is at list end
324 b3989551 Iustin Pop
  if master_node in nodes:
325 b3989551 Iustin Pop
    nodes.remove(master_node)
326 b3989551 Iustin Pop
    nodes.append(master_node)
327 b3989551 Iustin Pop
328 b3989551 Iustin Pop
  for name in nodes:
329 b3989551 Iustin Pop
    result = srun.Run(name, "root", command)
330 3a24c527 Iustin Pop
    ToStdout("------------------------------------------------")
331 3a24c527 Iustin Pop
    ToStdout("node: %s", name)
332 3a24c527 Iustin Pop
    ToStdout("%s", result.output)
333 3a24c527 Iustin Pop
    ToStdout("return code = %s", result.exit_code)
334 b3989551 Iustin Pop
335 b3989551 Iustin Pop
  return 0
336 a8083063 Iustin Pop
337 a8083063 Iustin Pop
338 a8083063 Iustin Pop
def VerifyCluster(opts, args):
339 a8083063 Iustin Pop
  """Verify integrity of cluster, performing various test on nodes.
340 a8083063 Iustin Pop
341 469ee405 Iustin Pop
  @param opts: the command line options selected by the user
342 469ee405 Iustin Pop
  @type args: list
343 469ee405 Iustin Pop
  @param args: should be an empty list
344 469ee405 Iustin Pop
  @rtype: int
345 469ee405 Iustin Pop
  @return: the desired exit code
346 a8083063 Iustin Pop
347 a8083063 Iustin Pop
  """
348 8d59409f Iustin Pop
  skip_checks = []
349 e54c4c5e Guido Trotter
  if opts.skip_nplusone_mem:
350 e54c4c5e Guido Trotter
    skip_checks.append(constants.VERIFY_NPLUSONE_MEM)
351 e54c4c5e Guido Trotter
  op = opcodes.OpVerifyCluster(skip_checks=skip_checks)
352 34290825 Michael Hanselmann
  if SubmitOpCode(op):
353 34290825 Michael Hanselmann
    return 0
354 34290825 Michael Hanselmann
  else:
355 34290825 Michael Hanselmann
    return 1
356 a8083063 Iustin Pop
357 a8083063 Iustin Pop
358 f4d4e184 Iustin Pop
def VerifyDisks(opts, args):
359 f4d4e184 Iustin Pop
  """Verify integrity of cluster disks.
360 f4d4e184 Iustin Pop
361 469ee405 Iustin Pop
  @param opts: the command line options selected by the user
362 469ee405 Iustin Pop
  @type args: list
363 469ee405 Iustin Pop
  @param args: should be an empty list
364 469ee405 Iustin Pop
  @rtype: int
365 469ee405 Iustin Pop
  @return: the desired exit code
366 f4d4e184 Iustin Pop
367 f4d4e184 Iustin Pop
  """
368 f4d4e184 Iustin Pop
  op = opcodes.OpVerifyDisks()
369 f4d4e184 Iustin Pop
  result = SubmitOpCode(op)
370 dcde0241 Guido Trotter
  if not isinstance(result, (list, tuple)) or len(result) != 4:
371 f4d4e184 Iustin Pop
    raise errors.ProgrammerError("Unknown result type for OpVerifyDisks")
372 f4d4e184 Iustin Pop
373 b63ed789 Iustin Pop
  nodes, nlvm, instances, missing = result
374 b63ed789 Iustin Pop
375 f4d4e184 Iustin Pop
  if nodes:
376 3a24c527 Iustin Pop
    ToStdout("Nodes unreachable or with bad data:")
377 f4d4e184 Iustin Pop
    for name in nodes:
378 3a24c527 Iustin Pop
      ToStdout("\t%s", name)
379 f4d4e184 Iustin Pop
  retcode = constants.EXIT_SUCCESS
380 b63ed789 Iustin Pop
381 b63ed789 Iustin Pop
  if nlvm:
382 b63ed789 Iustin Pop
    for node, text in nlvm.iteritems():
383 3a24c527 Iustin Pop
      ToStdout("Error on node %s: LVM error: %s",
384 26f15862 Iustin Pop
               node, utils.SafeEncode(text[-400:]))
385 b63ed789 Iustin Pop
      retcode |= 1
386 3a24c527 Iustin Pop
      ToStdout("You need to fix these nodes first before fixing instances")
387 b63ed789 Iustin Pop
388 f4d4e184 Iustin Pop
  if instances:
389 f4d4e184 Iustin Pop
    for iname in instances:
390 b63ed789 Iustin Pop
      if iname in missing:
391 b63ed789 Iustin Pop
        continue
392 f4d4e184 Iustin Pop
      op = opcodes.OpActivateInstanceDisks(instance_name=iname)
393 f4d4e184 Iustin Pop
      try:
394 3a24c527 Iustin Pop
        ToStdout("Activating disks for instance '%s'", iname)
395 f4d4e184 Iustin Pop
        SubmitOpCode(op)
396 f4d4e184 Iustin Pop
      except errors.GenericError, err:
397 f4d4e184 Iustin Pop
        nret, msg = FormatError(err)
398 f4d4e184 Iustin Pop
        retcode |= nret
399 3a24c527 Iustin Pop
        ToStderr("Error activating disks for instance %s: %s", iname, msg)
400 b63ed789 Iustin Pop
401 b63ed789 Iustin Pop
  if missing:
402 b63ed789 Iustin Pop
    for iname, ival in missing.iteritems():
403 b63ed789 Iustin Pop
      all_missing = utils.all(ival, lambda x: x[0] in nlvm)
404 b63ed789 Iustin Pop
      if all_missing:
405 3a24c527 Iustin Pop
        ToStdout("Instance %s cannot be verified as it lives on"
406 3a24c527 Iustin Pop
                 " broken nodes", iname)
407 b63ed789 Iustin Pop
      else:
408 3a24c527 Iustin Pop
        ToStdout("Instance %s has missing logical volumes:", iname)
409 b63ed789 Iustin Pop
        ival.sort()
410 b63ed789 Iustin Pop
        for node, vol in ival:
411 b63ed789 Iustin Pop
          if node in nlvm:
412 3a24c527 Iustin Pop
            ToStdout("\tbroken node %s /dev/xenvg/%s", node, vol)
413 b63ed789 Iustin Pop
          else:
414 3a24c527 Iustin Pop
            ToStdout("\t%s /dev/xenvg/%s", node, vol)
415 3a24c527 Iustin Pop
    ToStdout("You need to run replace_disks for all the above"
416 b63ed789 Iustin Pop
           " instances, if this message persist after fixing nodes.")
417 b63ed789 Iustin Pop
    retcode |= 1
418 f4d4e184 Iustin Pop
419 f4d4e184 Iustin Pop
  return retcode
420 f4d4e184 Iustin Pop
421 f4d4e184 Iustin Pop
422 4331f6cd Michael Hanselmann
@UsesRPC
423 a8083063 Iustin Pop
def MasterFailover(opts, args):
424 a8083063 Iustin Pop
  """Failover the master node.
425 a8083063 Iustin Pop
426 a8083063 Iustin Pop
  This command, when run on a non-master node, will cause the current
427 a8083063 Iustin Pop
  master to cease being master, and the non-master to become new
428 a8083063 Iustin Pop
  master.
429 a8083063 Iustin Pop
430 469ee405 Iustin Pop
  @param opts: the command line options selected by the user
431 469ee405 Iustin Pop
  @type args: list
432 469ee405 Iustin Pop
  @param args: should be an empty list
433 469ee405 Iustin Pop
  @rtype: int
434 469ee405 Iustin Pop
  @return: the desired exit code
435 469ee405 Iustin Pop
436 a8083063 Iustin Pop
  """
437 b1b6ea87 Iustin Pop
  return bootstrap.MasterFailover()
438 a8083063 Iustin Pop
439 a8083063 Iustin Pop
440 73415719 Iustin Pop
def SearchTags(opts, args):
441 73415719 Iustin Pop
  """Searches the tags on all the cluster.
442 73415719 Iustin Pop
443 469ee405 Iustin Pop
  @param opts: the command line options selected by the user
444 469ee405 Iustin Pop
  @type args: list
445 469ee405 Iustin Pop
  @param args: should contain only one element, the tag pattern
446 469ee405 Iustin Pop
  @rtype: int
447 469ee405 Iustin Pop
  @return: the desired exit code
448 469ee405 Iustin Pop
449 73415719 Iustin Pop
  """
450 73415719 Iustin Pop
  op = opcodes.OpSearchTags(pattern=args[0])
451 73415719 Iustin Pop
  result = SubmitOpCode(op)
452 73415719 Iustin Pop
  if not result:
453 73415719 Iustin Pop
    return 1
454 73415719 Iustin Pop
  result = list(result)
455 73415719 Iustin Pop
  result.sort()
456 73415719 Iustin Pop
  for path, tag in result:
457 3a24c527 Iustin Pop
    ToStdout("%s %s", path, tag)
458 73415719 Iustin Pop
459 73415719 Iustin Pop
460 90b6aa3a Manuel Franceschini
def SetClusterParams(opts, args):
461 90b6aa3a Manuel Franceschini
  """Modify the cluster.
462 90b6aa3a Manuel Franceschini
463 469ee405 Iustin Pop
  @param opts: the command line options selected by the user
464 469ee405 Iustin Pop
  @type args: list
465 469ee405 Iustin Pop
  @param args: should be an empty list
466 469ee405 Iustin Pop
  @rtype: int
467 469ee405 Iustin Pop
  @return: the desired exit code
468 90b6aa3a Manuel Franceschini
469 90b6aa3a Manuel Franceschini
  """
470 779c15bb Iustin Pop
  if not (not opts.lvm_storage or opts.vg_name or
471 779c15bb Iustin Pop
          opts.enabled_hypervisors or opts.hvparams or
472 4b7735f9 Iustin Pop
          opts.beparams or opts.candidate_pool_size is not None):
473 3a24c527 Iustin Pop
    ToStderr("Please give at least one of the parameters.")
474 90b6aa3a Manuel Franceschini
    return 1
475 90b6aa3a Manuel Franceschini
476 90b6aa3a Manuel Franceschini
  vg_name = opts.vg_name
477 90b6aa3a Manuel Franceschini
  if not opts.lvm_storage and opts.vg_name:
478 3a24c527 Iustin Pop
    ToStdout("Options --no-lvm-storage and --vg-name conflict.")
479 90b6aa3a Manuel Franceschini
    return 1
480 90b6aa3a Manuel Franceschini
481 779c15bb Iustin Pop
  hvlist = opts.enabled_hypervisors
482 779c15bb Iustin Pop
  if hvlist is not None:
483 779c15bb Iustin Pop
    hvlist = hvlist.split(",")
484 779c15bb Iustin Pop
485 779c15bb Iustin Pop
  hvparams = opts.hvparams
486 779c15bb Iustin Pop
  if hvparams:
487 779c15bb Iustin Pop
    # a list of (name, dict) we can pass directly to dict()
488 779c15bb Iustin Pop
    hvparams = dict(opts.hvparams)
489 779c15bb Iustin Pop
490 779c15bb Iustin Pop
  beparams = opts.beparams
491 779c15bb Iustin Pop
492 779c15bb Iustin Pop
  op = opcodes.OpSetClusterParams(vg_name=opts.vg_name,
493 779c15bb Iustin Pop
                                  enabled_hypervisors=hvlist,
494 779c15bb Iustin Pop
                                  hvparams=hvparams,
495 4b7735f9 Iustin Pop
                                  beparams=beparams,
496 4b7735f9 Iustin Pop
                                  candidate_pool_size=opts.candidate_pool_size)
497 90b6aa3a Manuel Franceschini
  SubmitOpCode(op)
498 90b6aa3a Manuel Franceschini
  return 0
499 90b6aa3a Manuel Franceschini
500 90b6aa3a Manuel Franceschini
501 3ccafd0e Iustin Pop
def QueueOps(opts, args):
502 3ccafd0e Iustin Pop
  """Queue operations.
503 3ccafd0e Iustin Pop
504 469ee405 Iustin Pop
  @param opts: the command line options selected by the user
505 469ee405 Iustin Pop
  @type args: list
506 469ee405 Iustin Pop
  @param args: should contain only one element, the subcommand
507 469ee405 Iustin Pop
  @rtype: int
508 469ee405 Iustin Pop
  @return: the desired exit code
509 469ee405 Iustin Pop
510 3ccafd0e Iustin Pop
  """
511 3ccafd0e Iustin Pop
  command = args[0]
512 3ccafd0e Iustin Pop
  client = GetClient()
513 3ccafd0e Iustin Pop
  if command in ("drain", "undrain"):
514 3ccafd0e Iustin Pop
    drain_flag = command == "drain"
515 3ccafd0e Iustin Pop
    client.SetQueueDrainFlag(drain_flag)
516 3ccafd0e Iustin Pop
  elif command == "info":
517 3ccafd0e Iustin Pop
    result = client.QueryConfigValues(["drain_flag"])
518 3ccafd0e Iustin Pop
    if result[0]:
519 3a24c527 Iustin Pop
      val = "set"
520 3ccafd0e Iustin Pop
    else:
521 3a24c527 Iustin Pop
      val = "unset"
522 3a24c527 Iustin Pop
    ToStdout("The drain flag is %s" % val)
523 3ccafd0e Iustin Pop
  return 0
524 3ccafd0e Iustin Pop
525 a8083063 Iustin Pop
# this is an option common to more than one command, so we declare
526 a8083063 Iustin Pop
# it here and reuse it
527 a8083063 Iustin Pop
node_option = make_option("-n", "--node", action="append", dest="nodes",
528 f4bc1f2c Michael Hanselmann
                          help="Node to copy to (if not given, all nodes),"
529 f4bc1f2c Michael Hanselmann
                               " can be given multiple times",
530 f4bc1f2c Michael Hanselmann
                          metavar="<node>", default=[])
531 a8083063 Iustin Pop
532 a8083063 Iustin Pop
commands = {
533 a8083063 Iustin Pop
  'init': (InitCluster, ARGS_ONE,
534 a8083063 Iustin Pop
           [DEBUG_OPT,
535 a8083063 Iustin Pop
            make_option("-s", "--secondary-ip", dest="secondary_ip",
536 a8083063 Iustin Pop
                        help="Specify the secondary ip for this node;"
537 a8083063 Iustin Pop
                        " if given, the entire cluster must have secondary"
538 a8083063 Iustin Pop
                        " addresses",
539 a8083063 Iustin Pop
                        metavar="ADDRESS", default=None),
540 a8083063 Iustin Pop
            make_option("-m", "--mac-prefix", dest="mac_prefix",
541 a8083063 Iustin Pop
                        help="Specify the mac prefix for the instance IP"
542 a8083063 Iustin Pop
                        " addresses, in the format XX:XX:XX",
543 a8083063 Iustin Pop
                        metavar="PREFIX",
544 c5e489f7 Iustin Pop
                        default=constants.DEFAULT_MAC_PREFIX,),
545 a8083063 Iustin Pop
            make_option("-g", "--vg-name", dest="vg_name",
546 a8083063 Iustin Pop
                        help="Specify the volume group name "
547 a8083063 Iustin Pop
                        " (cluster-wide) for disk allocation [xenvg]",
548 a8083063 Iustin Pop
                        metavar="VG",
549 90b6aa3a Manuel Franceschini
                        default=None,),
550 a8083063 Iustin Pop
            make_option("-b", "--bridge", dest="def_bridge",
551 a8083063 Iustin Pop
                        help="Specify the default bridge name (cluster-wide)"
552 cf62a272 Michael Hanselmann
                          " to connect the instances to [%s]" %
553 cf62a272 Michael Hanselmann
                          constants.DEFAULT_BRIDGE,
554 a8083063 Iustin Pop
                        metavar="BRIDGE",
555 cf62a272 Michael Hanselmann
                        default=constants.DEFAULT_BRIDGE,),
556 880478f8 Iustin Pop
            make_option("--master-netdev", dest="master_netdev",
557 880478f8 Iustin Pop
                        help="Specify the node interface (cluster-wide)"
558 cf62a272 Michael Hanselmann
                          " on which the master IP address will be added "
559 cf62a272 Michael Hanselmann
                          " [%s]" % constants.DEFAULT_BRIDGE,
560 880478f8 Iustin Pop
                        metavar="NETDEV",
561 cf62a272 Michael Hanselmann
                        default=constants.DEFAULT_BRIDGE,),
562 79e82404 Manuel Franceschini
            make_option("--file-storage-dir", dest="file_storage_dir",
563 79e82404 Manuel Franceschini
                        help="Specify the default directory (cluster-wide)"
564 79e82404 Manuel Franceschini
                             " for storing the file-based disks [%s]" %
565 79e82404 Manuel Franceschini
                             constants.DEFAULT_FILE_STORAGE_DIR,
566 79e82404 Manuel Franceschini
                        metavar="DIR",
567 79e82404 Manuel Franceschini
                        default=constants.DEFAULT_FILE_STORAGE_DIR,),
568 90b6aa3a Manuel Franceschini
            make_option("--no-lvm-storage", dest="lvm_storage",
569 90b6aa3a Manuel Franceschini
                        help="No support for lvm based instances"
570 90b6aa3a Manuel Franceschini
                             " (cluster-wide)",
571 90b6aa3a Manuel Franceschini
                        action="store_false", default=True,),
572 ea3a925f Alexander Schreiber
            make_option("--enabled-hypervisors", dest="enabled_hypervisors",
573 ea3a925f Alexander Schreiber
                        help="Comma-separated list of hypervisors",
574 ea3a925f Alexander Schreiber
                        type="string", default=None),
575 02691904 Alexander Schreiber
            make_option("-t", "--default-hypervisor",
576 02691904 Alexander Schreiber
                        dest="default_hypervisor",
577 02691904 Alexander Schreiber
                        help="Default hypervisor to use for instance creation",
578 02691904 Alexander Schreiber
                        choices=list(constants.HYPER_TYPES),
579 02691904 Alexander Schreiber
                        default=constants.DEFAULT_ENABLED_HYPERVISOR),
580 ea3a925f Alexander Schreiber
            ikv_option("-H", "--hypervisor-parameters", dest="hvparams",
581 ea3a925f Alexander Schreiber
                       help="Hypervisor and hypervisor options, in the"
582 ea3a925f Alexander Schreiber
                         " format"
583 ea3a925f Alexander Schreiber
                       " hypervisor:option=value,option=value,...",
584 ea3a925f Alexander Schreiber
                       default=[],
585 ea3a925f Alexander Schreiber
                       action="append",
586 ea3a925f Alexander Schreiber
                       type="identkeyval"),
587 ea3a925f Alexander Schreiber
            keyval_option("-B", "--backend-parameters", dest="beparams",
588 ea3a925f Alexander Schreiber
                          type="keyval", default={},
589 ea3a925f Alexander Schreiber
                          help="Backend parameters"),
590 ce735215 Guido Trotter
            make_option("-C", "--candidate-pool-size",
591 ce735215 Guido Trotter
                        default=constants.MASTER_POOL_SIZE_DEFAULT,
592 ce735215 Guido Trotter
                        help="Set the candidate pool size",
593 ce735215 Guido Trotter
                        dest="candidate_pool_size", type="int"),
594 a8083063 Iustin Pop
            ],
595 9a033156 Iustin Pop
           "[opts...] <cluster_name>",
596 a8083063 Iustin Pop
           "Initialises a new cluster configuration"),
597 a8083063 Iustin Pop
  'destroy': (DestroyCluster, ARGS_NONE,
598 a8083063 Iustin Pop
              [DEBUG_OPT,
599 a8083063 Iustin Pop
               make_option("--yes-do-it", dest="yes_do_it",
600 a8083063 Iustin Pop
                           help="Destroy cluster",
601 a8083063 Iustin Pop
                           action="store_true"),
602 a8083063 Iustin Pop
              ],
603 9a033156 Iustin Pop
              "", "Destroy cluster"),
604 07bd8a51 Iustin Pop
  'rename': (RenameCluster, ARGS_ONE, [DEBUG_OPT, FORCE_OPT],
605 9a033156 Iustin Pop
               "<new_name>",
606 07bd8a51 Iustin Pop
               "Renames the cluster"),
607 afee0879 Iustin Pop
  'redist-conf': (RedistributeConfig, ARGS_NONE, [DEBUG_OPT, SUBMIT_OPT],
608 afee0879 Iustin Pop
                  "",
609 afee0879 Iustin Pop
                  "Forces a push of the configuration file and ssconf files"
610 afee0879 Iustin Pop
                  " to the nodes in the cluster"),
611 e54c4c5e Guido Trotter
  'verify': (VerifyCluster, ARGS_NONE, [DEBUG_OPT,
612 e54c4c5e Guido Trotter
             make_option("--no-nplus1-mem", dest="skip_nplusone_mem",
613 e54c4c5e Guido Trotter
                         help="Skip N+1 memory redundancy tests",
614 e54c4c5e Guido Trotter
                         action="store_true",
615 e54c4c5e Guido Trotter
                         default=False,),
616 e54c4c5e Guido Trotter
             ],
617 9a033156 Iustin Pop
             "", "Does a check on the cluster configuration"),
618 f4d4e184 Iustin Pop
  'verify-disks': (VerifyDisks, ARGS_NONE, [DEBUG_OPT],
619 9a033156 Iustin Pop
                   "", "Does a check on the cluster disk status"),
620 a8083063 Iustin Pop
  'masterfailover': (MasterFailover, ARGS_NONE, [DEBUG_OPT],
621 9a033156 Iustin Pop
                     "", "Makes the current node the master"),
622 a8083063 Iustin Pop
  'version': (ShowClusterVersion, ARGS_NONE, [DEBUG_OPT],
623 9a033156 Iustin Pop
              "", "Shows the cluster version"),
624 a8083063 Iustin Pop
  'getmaster': (ShowClusterMaster, ARGS_NONE, [DEBUG_OPT],
625 9a033156 Iustin Pop
                "", "Shows the cluster master"),
626 a8083063 Iustin Pop
  'copyfile': (ClusterCopyFile, ARGS_ONE, [DEBUG_OPT, node_option],
627 9a033156 Iustin Pop
               "[-n node...] <filename>",
628 a8083063 Iustin Pop
               "Copies a file to all (or only some) nodes"),
629 a8083063 Iustin Pop
  'command': (RunClusterCommand, ARGS_ATLEAST(1), [DEBUG_OPT, node_option],
630 9a033156 Iustin Pop
              "[-n node...] <command>",
631 a8083063 Iustin Pop
              "Runs a command on all (or only some) nodes"),
632 a8083063 Iustin Pop
  'info': (ShowClusterConfig, ARGS_NONE, [DEBUG_OPT],
633 9a033156 Iustin Pop
                 "", "Show cluster configuration"),
634 846baef9 Iustin Pop
  'list-tags': (ListTags, ARGS_NONE,
635 9a033156 Iustin Pop
                [DEBUG_OPT], "", "List the tags of the cluster"),
636 810c50b7 Iustin Pop
  'add-tags': (AddTags, ARGS_ANY, [DEBUG_OPT, TAG_SRC_OPT],
637 9a033156 Iustin Pop
               "tag...", "Add tags to the cluster"),
638 810c50b7 Iustin Pop
  'remove-tags': (RemoveTags, ARGS_ANY, [DEBUG_OPT, TAG_SRC_OPT],
639 9a033156 Iustin Pop
                  "tag...", "Remove tags from the cluster"),
640 73415719 Iustin Pop
  'search-tags': (SearchTags, ARGS_ONE,
641 9a033156 Iustin Pop
                  [DEBUG_OPT], "", "Searches the tags on all objects on"
642 73415719 Iustin Pop
                  " the cluster for a given pattern (regex)"),
643 3ccafd0e Iustin Pop
  'queue': (QueueOps, ARGS_ONE, [DEBUG_OPT],
644 3ccafd0e Iustin Pop
            "drain|undrain|info", "Change queue properties"),
645 90b6aa3a Manuel Franceschini
  'modify': (SetClusterParams, ARGS_NONE,
646 90b6aa3a Manuel Franceschini
             [DEBUG_OPT,
647 90b6aa3a Manuel Franceschini
              make_option("-g", "--vg-name", dest="vg_name",
648 90b6aa3a Manuel Franceschini
                          help="Specify the volume group name "
649 90b6aa3a Manuel Franceschini
                          " (cluster-wide) for disk allocation "
650 90b6aa3a Manuel Franceschini
                          "and enable lvm based storage",
651 90b6aa3a Manuel Franceschini
                          metavar="VG",),
652 90b6aa3a Manuel Franceschini
              make_option("--no-lvm-storage", dest="lvm_storage",
653 90b6aa3a Manuel Franceschini
                          help="Disable support for lvm based instances"
654 90b6aa3a Manuel Franceschini
                               " (cluster-wide)",
655 90b6aa3a Manuel Franceschini
                          action="store_false", default=True,),
656 779c15bb Iustin Pop
              make_option("--enabled-hypervisors", dest="enabled_hypervisors",
657 779c15bb Iustin Pop
                          help="Comma-separated list of hypervisors",
658 779c15bb Iustin Pop
                          type="string", default=None),
659 779c15bb Iustin Pop
              ikv_option("-H", "--hypervisor-parameters", dest="hvparams",
660 779c15bb Iustin Pop
                         help="Hypervisor and hypervisor options, in the"
661 779c15bb Iustin Pop
                         " format"
662 779c15bb Iustin Pop
                         " hypervisor:option=value,option=value,...",
663 779c15bb Iustin Pop
                         default=[],
664 779c15bb Iustin Pop
                         action="append",
665 779c15bb Iustin Pop
                         type="identkeyval"),
666 779c15bb Iustin Pop
              keyval_option("-B", "--backend-parameters", dest="beparams",
667 779c15bb Iustin Pop
                            type="keyval", default={},
668 779c15bb Iustin Pop
                            help="Backend parameters"),
669 4b7735f9 Iustin Pop
              make_option("-C", "--candidate-pool-size", default=None,
670 4b7735f9 Iustin Pop
                          help="Set the candidate pool size",
671 4b7735f9 Iustin Pop
                          dest="candidate_pool_size", type="int"),
672 90b6aa3a Manuel Franceschini
              ],
673 90b6aa3a Manuel Franceschini
             "[opts...]",
674 90b6aa3a Manuel Franceschini
             "Alters the parameters of the cluster"),
675 a8083063 Iustin Pop
  }
676 a8083063 Iustin Pop
677 a8083063 Iustin Pop
if __name__ == '__main__':
678 846baef9 Iustin Pop
  sys.exit(GenericMain(commands, override={"tag_type": constants.TAG_CLUSTER}))