Statistics
| Branch: | Tag: | Revision:

root / scripts / gnt-cluster @ 4fbc93dd

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