Statistics
| Branch: | Tag: | Revision:

root / scripts / gnt-cluster @ aafb303d

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