Statistics
| Branch: | Tag: | Revision:

root / scripts / gnt-cluster @ 28b498cd

History | View | Annotate | Download (25.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 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 066f465d Guido Trotter
  hvlist = hvlist.split(",")
62 ea3a925f Alexander Schreiber
63 f8e7ddca Guido Trotter
  hvparams = dict(opts.hvparams)
64 ea3a925f Alexander Schreiber
  beparams = opts.beparams
65 b6a30b0d Guido Trotter
  nicparams = opts.nicparams
66 ea3a925f Alexander Schreiber
67 ea3a925f Alexander Schreiber
  # prepare beparams dict
68 d3cfe525 Guido Trotter
  beparams = objects.FillDict(constants.BEC_DEFAULTS, beparams)
69 a5728081 Guido Trotter
  utils.ForceDictType(beparams, constants.BES_PARAMETER_TYPES)
70 ea3a925f Alexander Schreiber
71 b6a30b0d Guido Trotter
  # prepare nicparams dict
72 b6a30b0d Guido Trotter
  nicparams = objects.FillDict(constants.NICC_DEFAULTS, nicparams)
73 b6a30b0d Guido Trotter
  utils.ForceDictType(nicparams, constants.NICS_PARAMETER_TYPES)
74 b6a30b0d Guido Trotter
75 ea3a925f Alexander Schreiber
  # prepare hvparams dict
76 ea3a925f Alexander Schreiber
  for hv in constants.HYPER_TYPES:
77 ea3a925f Alexander Schreiber
    if hv not in hvparams:
78 ea3a925f Alexander Schreiber
      hvparams[hv] = {}
79 d3cfe525 Guido Trotter
    hvparams[hv] = objects.FillDict(constants.HVC_DEFAULTS[hv], hvparams[hv])
80 a5728081 Guido Trotter
    utils.ForceDictType(hvparams[hv], constants.HVS_PARAMETER_TYPES)
81 ea3a925f Alexander Schreiber
82 a0c9f010 Michael Hanselmann
  bootstrap.InitCluster(cluster_name=args[0],
83 a0c9f010 Michael Hanselmann
                        secondary_ip=opts.secondary_ip,
84 a0c9f010 Michael Hanselmann
                        vg_name=vg_name,
85 a0c9f010 Michael Hanselmann
                        mac_prefix=opts.mac_prefix,
86 a0c9f010 Michael Hanselmann
                        master_netdev=opts.master_netdev,
87 ea3a925f Alexander Schreiber
                        file_storage_dir=opts.file_storage_dir,
88 ea3a925f Alexander Schreiber
                        enabled_hypervisors=hvlist,
89 ea3a925f Alexander Schreiber
                        hvparams=hvparams,
90 ce735215 Guido Trotter
                        beparams=beparams,
91 b6a30b0d Guido Trotter
                        nicparams=nicparams,
92 ce735215 Guido Trotter
                        candidate_pool_size=opts.candidate_pool_size,
93 b86a6bcd Guido Trotter
                        modify_etc_hosts=opts.modify_etc_hosts,
94 ce735215 Guido Trotter
                        )
95 3552cd2e Luca Bigliardi
  op = opcodes.OpPostInitCluster()
96 3552cd2e Luca Bigliardi
  SubmitOpCode(op)
97 a8083063 Iustin Pop
  return 0
98 a8083063 Iustin Pop
99 a8083063 Iustin Pop
100 4331f6cd Michael Hanselmann
@UsesRPC
101 a8083063 Iustin Pop
def DestroyCluster(opts, args):
102 a8083063 Iustin Pop
  """Destroy the cluster.
103 a8083063 Iustin Pop
104 469ee405 Iustin Pop
  @param opts: the command line options selected by the user
105 469ee405 Iustin Pop
  @type args: list
106 469ee405 Iustin Pop
  @param args: should be an empty list
107 469ee405 Iustin Pop
  @rtype: int
108 469ee405 Iustin Pop
  @return: the desired exit code
109 098c0958 Michael Hanselmann
110 a8083063 Iustin Pop
  """
111 a8083063 Iustin Pop
  if not opts.yes_do_it:
112 3a24c527 Iustin Pop
    ToStderr("Destroying a cluster is irreversible. If you really want"
113 3a24c527 Iustin Pop
             " destroy this cluster, supply the --yes-do-it option.")
114 a8083063 Iustin Pop
    return 1
115 a8083063 Iustin Pop
116 a8083063 Iustin Pop
  op = opcodes.OpDestroyCluster()
117 140aa4a8 Iustin Pop
  master = SubmitOpCode(op)
118 140aa4a8 Iustin Pop
  # if we reached this, the opcode didn't fail; we can proceed to
119 140aa4a8 Iustin Pop
  # shutdown all the daemons
120 140aa4a8 Iustin Pop
  bootstrap.FinalizeClusterDestroy(master)
121 a8083063 Iustin Pop
  return 0
122 a8083063 Iustin Pop
123 a8083063 Iustin Pop
124 07bd8a51 Iustin Pop
def RenameCluster(opts, args):
125 07bd8a51 Iustin Pop
  """Rename the cluster.
126 07bd8a51 Iustin Pop
127 469ee405 Iustin Pop
  @param opts: the command line options selected by the user
128 469ee405 Iustin Pop
  @type args: list
129 469ee405 Iustin Pop
  @param args: should contain only one element, the new cluster name
130 469ee405 Iustin Pop
  @rtype: int
131 469ee405 Iustin Pop
  @return: the desired exit code
132 07bd8a51 Iustin Pop
133 07bd8a51 Iustin Pop
  """
134 07bd8a51 Iustin Pop
  name = args[0]
135 07bd8a51 Iustin Pop
  if not opts.force:
136 07bd8a51 Iustin Pop
    usertext = ("This will rename the cluster to '%s'. If you are connected"
137 07bd8a51 Iustin Pop
                " over the network to the cluster name, the operation is very"
138 07bd8a51 Iustin Pop
                " dangerous as the IP address will be removed from the node"
139 07bd8a51 Iustin Pop
                " and the change may not go through. Continue?") % name
140 47988778 Iustin Pop
    if not AskUser(usertext):
141 07bd8a51 Iustin Pop
      return 1
142 07bd8a51 Iustin Pop
143 07bd8a51 Iustin Pop
  op = opcodes.OpRenameCluster(name=name)
144 07bd8a51 Iustin Pop
  SubmitOpCode(op)
145 07bd8a51 Iustin Pop
  return 0
146 07bd8a51 Iustin Pop
147 07bd8a51 Iustin Pop
148 afee0879 Iustin Pop
def RedistributeConfig(opts, args):
149 afee0879 Iustin Pop
  """Forces push of the cluster configuration.
150 afee0879 Iustin Pop
151 afee0879 Iustin Pop
  @param opts: the command line options selected by the user
152 afee0879 Iustin Pop
  @type args: list
153 afee0879 Iustin Pop
  @param args: empty list
154 afee0879 Iustin Pop
  @rtype: int
155 afee0879 Iustin Pop
  @return: the desired exit code
156 afee0879 Iustin Pop
157 afee0879 Iustin Pop
  """
158 81a49123 Iustin Pop
  op = opcodes.OpRedistributeConfig()
159 afee0879 Iustin Pop
  SubmitOrSend(op, opts)
160 afee0879 Iustin Pop
  return 0
161 afee0879 Iustin Pop
162 afee0879 Iustin Pop
163 a8083063 Iustin Pop
def ShowClusterVersion(opts, args):
164 a8083063 Iustin Pop
  """Write version of ganeti software to the standard output.
165 a8083063 Iustin Pop
166 469ee405 Iustin Pop
  @param opts: the command line options selected by the user
167 469ee405 Iustin Pop
  @type args: list
168 469ee405 Iustin Pop
  @param args: should be an empty list
169 469ee405 Iustin Pop
  @rtype: int
170 469ee405 Iustin Pop
  @return: the desired exit code
171 a8083063 Iustin Pop
172 a8083063 Iustin Pop
  """
173 2e7b8369 Iustin Pop
  cl = GetClient()
174 2e7b8369 Iustin Pop
  result = cl.QueryClusterInfo()
175 3a24c527 Iustin Pop
  ToStdout("Software version: %s", result["software_version"])
176 3a24c527 Iustin Pop
  ToStdout("Internode protocol: %s", result["protocol_version"])
177 3a24c527 Iustin Pop
  ToStdout("Configuration format: %s", result["config_version"])
178 3a24c527 Iustin Pop
  ToStdout("OS api version: %s", result["os_api_version"])
179 3a24c527 Iustin Pop
  ToStdout("Export interface: %s", result["export_version"])
180 a8083063 Iustin Pop
  return 0
181 a8083063 Iustin Pop
182 a8083063 Iustin Pop
183 a8083063 Iustin Pop
def ShowClusterMaster(opts, args):
184 a8083063 Iustin Pop
  """Write name of master node to the standard output.
185 a8083063 Iustin Pop
186 469ee405 Iustin Pop
  @param opts: the command line options selected by the user
187 469ee405 Iustin Pop
  @type args: list
188 469ee405 Iustin Pop
  @param args: should be an empty list
189 469ee405 Iustin Pop
  @rtype: int
190 469ee405 Iustin Pop
  @return: the desired exit code
191 a8083063 Iustin Pop
192 a8083063 Iustin Pop
  """
193 8eb148ae Iustin Pop
  master = bootstrap.GetMaster()
194 8eb148ae Iustin Pop
  ToStdout(master)
195 a8083063 Iustin Pop
  return 0
196 a8083063 Iustin Pop
197 1094acda Guido Trotter
def _PrintGroupedParams(paramsdict):
198 1094acda Guido Trotter
  """Print Grouped parameters (be, nic, disk) by group.
199 1094acda Guido Trotter
200 1094acda Guido Trotter
  @type paramsdict: dict of dicts
201 1094acda Guido Trotter
  @param paramsdict: {group: {param: value, ...}, ...}
202 1094acda Guido Trotter
203 1094acda Guido Trotter
  """
204 1094acda Guido Trotter
  for gr_name, gr_dict in paramsdict.items():
205 1094acda Guido Trotter
    ToStdout("  - %s:", gr_name)
206 1094acda Guido Trotter
    for item, val in gr_dict.iteritems():
207 1094acda Guido Trotter
      ToStdout("      %s: %s", item, val)
208 a8083063 Iustin Pop
209 a8083063 Iustin Pop
def ShowClusterConfig(opts, args):
210 a8083063 Iustin Pop
  """Shows cluster information.
211 a8083063 Iustin Pop
212 469ee405 Iustin Pop
  @param opts: the command line options selected by the user
213 469ee405 Iustin Pop
  @type args: list
214 469ee405 Iustin Pop
  @param args: should be an empty list
215 469ee405 Iustin Pop
  @rtype: int
216 469ee405 Iustin Pop
  @return: the desired exit code
217 469ee405 Iustin Pop
218 a8083063 Iustin Pop
  """
219 2e7b8369 Iustin Pop
  cl = GetClient()
220 2e7b8369 Iustin Pop
  result = cl.QueryClusterInfo()
221 a8083063 Iustin Pop
222 3a24c527 Iustin Pop
  ToStdout("Cluster name: %s", result["name"])
223 a8083063 Iustin Pop
224 90f72445 Iustin Pop
  ToStdout("Creation time: %s", utils.FormatTime(result["ctime"]))
225 90f72445 Iustin Pop
  ToStdout("Modification time: %s", utils.FormatTime(result["mtime"]))
226 90f72445 Iustin Pop
227 3a24c527 Iustin Pop
  ToStdout("Master node: %s", result["master"])
228 a8083063 Iustin Pop
229 3a24c527 Iustin Pop
  ToStdout("Architecture (this node): %s (%s)",
230 3a24c527 Iustin Pop
           result["architecture"][0], result["architecture"][1])
231 a8083063 Iustin Pop
232 c118d1f4 Michael Hanselmann
  if result["tags"]:
233 c118d1f4 Michael Hanselmann
    tags = ", ".join(utils.NiceSort(result["tags"]))
234 c118d1f4 Michael Hanselmann
  else:
235 c118d1f4 Michael Hanselmann
    tags = "(none)"
236 c118d1f4 Michael Hanselmann
237 c118d1f4 Michael Hanselmann
  ToStdout("Tags: %s", tags)
238 c118d1f4 Michael Hanselmann
239 02691904 Alexander Schreiber
  ToStdout("Default hypervisor: %s", result["default_hypervisor"])
240 3a24c527 Iustin Pop
  ToStdout("Enabled hypervisors: %s", ", ".join(result["enabled_hypervisors"]))
241 469f88e1 Iustin Pop
242 3a24c527 Iustin Pop
  ToStdout("Hypervisor parameters:")
243 1094acda Guido Trotter
  _PrintGroupedParams(result["hvparams"])
244 469f88e1 Iustin Pop
245 3a24c527 Iustin Pop
  ToStdout("Cluster parameters:")
246 4b7735f9 Iustin Pop
  ToStdout("  - candidate pool size: %s", result["candidate_pool_size"])
247 a8001106 Guido Trotter
  ToStdout("  - master netdev: %s", result["master_netdev"])
248 a8001106 Guido Trotter
  ToStdout("  - lvm volume group: %s", result["volume_group_name"])
249 a8001106 Guido Trotter
  ToStdout("  - file storage path: %s", result["file_storage_dir"])
250 4b7735f9 Iustin Pop
251 4b7735f9 Iustin Pop
  ToStdout("Default instance parameters:")
252 1094acda Guido Trotter
  _PrintGroupedParams(result["beparams"])
253 1094acda Guido Trotter
254 1094acda Guido Trotter
  ToStdout("Default nic parameters:")
255 1094acda Guido Trotter
  _PrintGroupedParams(result["nicparams"])
256 8a12ce45 Iustin Pop
257 a8083063 Iustin Pop
  return 0
258 a8083063 Iustin Pop
259 a8083063 Iustin Pop
260 a8083063 Iustin Pop
def ClusterCopyFile(opts, args):
261 a8083063 Iustin Pop
  """Copy a file from master to some nodes.
262 a8083063 Iustin Pop
263 469ee405 Iustin Pop
  @param opts: the command line options selected by the user
264 469ee405 Iustin Pop
  @type args: list
265 469ee405 Iustin Pop
  @param args: should contain only one element, the path of
266 469ee405 Iustin Pop
      the file to be copied
267 469ee405 Iustin Pop
  @rtype: int
268 469ee405 Iustin Pop
  @return: the desired exit code
269 a8083063 Iustin Pop
270 a8083063 Iustin Pop
  """
271 b3989551 Iustin Pop
  filename = args[0]
272 b3989551 Iustin Pop
  if not os.path.exists(filename):
273 b3989551 Iustin Pop
    raise errors.OpPrereqError("No such filename '%s'" % filename)
274 b3989551 Iustin Pop
275 56bece1f Iustin Pop
  cl = GetClient()
276 56bece1f Iustin Pop
277 b3989551 Iustin Pop
  myname = utils.HostInfo().name
278 b3989551 Iustin Pop
279 56bece1f Iustin Pop
  cluster_name = cl.QueryConfigValues(["cluster_name"])[0]
280 56bece1f Iustin Pop
281 4040a784 Iustin Pop
  results = GetOnlineNodes(nodes=opts.nodes, cl=cl)
282 4040a784 Iustin Pop
  results = [name for name in results if name != myname]
283 e00ea635 Michael Hanselmann
284 56bece1f Iustin Pop
  srun = ssh.SshRunner(cluster_name=cluster_name)
285 b3989551 Iustin Pop
  for node in results:
286 b3989551 Iustin Pop
    if not srun.CopyFileToNode(node, filename):
287 3a24c527 Iustin Pop
      ToStderr("Copy of file %s to node %s failed", filename, node)
288 b3989551 Iustin Pop
289 a8083063 Iustin Pop
  return 0
290 a8083063 Iustin Pop
291 a8083063 Iustin Pop
292 a8083063 Iustin Pop
def RunClusterCommand(opts, args):
293 a8083063 Iustin Pop
  """Run a command on some nodes.
294 a8083063 Iustin Pop
295 469ee405 Iustin Pop
  @param opts: the command line options selected by the user
296 469ee405 Iustin Pop
  @type args: list
297 469ee405 Iustin Pop
  @param args: should contain the command to be run and its arguments
298 469ee405 Iustin Pop
  @rtype: int
299 469ee405 Iustin Pop
  @return: the desired exit code
300 a8083063 Iustin Pop
301 a8083063 Iustin Pop
  """
302 56bece1f Iustin Pop
  cl = GetClient()
303 7688d0d3 Michael Hanselmann
304 a8083063 Iustin Pop
  command = " ".join(args)
305 4040a784 Iustin Pop
306 4040a784 Iustin Pop
  nodes = GetOnlineNodes(nodes=opts.nodes, cl=cl)
307 56bece1f Iustin Pop
308 56bece1f Iustin Pop
  cluster_name, master_node = cl.QueryConfigValues(["cluster_name",
309 56bece1f Iustin Pop
                                                    "master_node"])
310 b3989551 Iustin Pop
311 56bece1f Iustin Pop
  srun = ssh.SshRunner(cluster_name=cluster_name)
312 b3989551 Iustin Pop
313 7688d0d3 Michael Hanselmann
  # Make sure master node is at list end
314 b3989551 Iustin Pop
  if master_node in nodes:
315 b3989551 Iustin Pop
    nodes.remove(master_node)
316 b3989551 Iustin Pop
    nodes.append(master_node)
317 b3989551 Iustin Pop
318 b3989551 Iustin Pop
  for name in nodes:
319 b3989551 Iustin Pop
    result = srun.Run(name, "root", command)
320 3a24c527 Iustin Pop
    ToStdout("------------------------------------------------")
321 3a24c527 Iustin Pop
    ToStdout("node: %s", name)
322 3a24c527 Iustin Pop
    ToStdout("%s", result.output)
323 3a24c527 Iustin Pop
    ToStdout("return code = %s", result.exit_code)
324 b3989551 Iustin Pop
325 b3989551 Iustin Pop
  return 0
326 a8083063 Iustin Pop
327 a8083063 Iustin Pop
328 a8083063 Iustin Pop
def VerifyCluster(opts, args):
329 a8083063 Iustin Pop
  """Verify integrity of cluster, performing various test on nodes.
330 a8083063 Iustin Pop
331 469ee405 Iustin Pop
  @param opts: the command line options selected by the user
332 469ee405 Iustin Pop
  @type args: list
333 469ee405 Iustin Pop
  @param args: should be an empty list
334 469ee405 Iustin Pop
  @rtype: int
335 469ee405 Iustin Pop
  @return: the desired exit code
336 a8083063 Iustin Pop
337 a8083063 Iustin Pop
  """
338 8d59409f Iustin Pop
  skip_checks = []
339 e54c4c5e Guido Trotter
  if opts.skip_nplusone_mem:
340 e54c4c5e Guido Trotter
    skip_checks.append(constants.VERIFY_NPLUSONE_MEM)
341 e54c4c5e Guido Trotter
  op = opcodes.OpVerifyCluster(skip_checks=skip_checks)
342 34290825 Michael Hanselmann
  if SubmitOpCode(op):
343 34290825 Michael Hanselmann
    return 0
344 34290825 Michael Hanselmann
  else:
345 34290825 Michael Hanselmann
    return 1
346 a8083063 Iustin Pop
347 a8083063 Iustin Pop
348 f4d4e184 Iustin Pop
def VerifyDisks(opts, args):
349 f4d4e184 Iustin Pop
  """Verify integrity of cluster disks.
350 f4d4e184 Iustin Pop
351 469ee405 Iustin Pop
  @param opts: the command line options selected by the user
352 469ee405 Iustin Pop
  @type args: list
353 469ee405 Iustin Pop
  @param args: should be an empty list
354 469ee405 Iustin Pop
  @rtype: int
355 469ee405 Iustin Pop
  @return: the desired exit code
356 f4d4e184 Iustin Pop
357 f4d4e184 Iustin Pop
  """
358 f4d4e184 Iustin Pop
  op = opcodes.OpVerifyDisks()
359 f4d4e184 Iustin Pop
  result = SubmitOpCode(op)
360 29d376ec Iustin Pop
  if not isinstance(result, (list, tuple)) or len(result) != 3:
361 f4d4e184 Iustin Pop
    raise errors.ProgrammerError("Unknown result type for OpVerifyDisks")
362 f4d4e184 Iustin Pop
363 29d376ec Iustin Pop
  bad_nodes, instances, missing = result
364 b63ed789 Iustin Pop
365 f4d4e184 Iustin Pop
  retcode = constants.EXIT_SUCCESS
366 b63ed789 Iustin Pop
367 29d376ec Iustin Pop
  if bad_nodes:
368 29d376ec Iustin Pop
    for node, text in bad_nodes.items():
369 29d376ec Iustin Pop
      ToStdout("Error gathering data on node %s: %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 29d376ec Iustin Pop
      all_missing = utils.all(ival, lambda x: x[0] in bad_nodes)
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 29d376ec Iustin Pop
          if node in bad_nodes:
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 5af3da74 Guido Trotter
          opts.beparams or opts.nicparams or
481 5af3da74 Guido Trotter
          opts.candidate_pool_size is not None):
482 3a24c527 Iustin Pop
    ToStderr("Please give at least one of the parameters.")
483 90b6aa3a Manuel Franceschini
    return 1
484 90b6aa3a Manuel Franceschini
485 90b6aa3a Manuel Franceschini
  vg_name = opts.vg_name
486 90b6aa3a Manuel Franceschini
  if not opts.lvm_storage and opts.vg_name:
487 3a24c527 Iustin Pop
    ToStdout("Options --no-lvm-storage and --vg-name conflict.")
488 90b6aa3a Manuel Franceschini
    return 1
489 b8a8fbe1 Guido Trotter
  elif not opts.lvm_storage:
490 b8a8fbe1 Guido Trotter
    vg_name = ''
491 90b6aa3a Manuel Franceschini
492 779c15bb Iustin Pop
  hvlist = opts.enabled_hypervisors
493 779c15bb Iustin Pop
  if hvlist is not None:
494 779c15bb Iustin Pop
    hvlist = hvlist.split(",")
495 779c15bb Iustin Pop
496 f8e7ddca Guido Trotter
  # a list of (name, dict) we can pass directly to dict() (or [])
497 f8e7ddca Guido Trotter
  hvparams = dict(opts.hvparams)
498 a5728081 Guido Trotter
  for hv, hv_params in hvparams.iteritems():
499 a5728081 Guido Trotter
    utils.ForceDictType(hv_params, constants.HVS_PARAMETER_TYPES)
500 779c15bb Iustin Pop
501 779c15bb Iustin Pop
  beparams = opts.beparams
502 a5728081 Guido Trotter
  utils.ForceDictType(beparams, constants.BES_PARAMETER_TYPES)
503 779c15bb Iustin Pop
504 5af3da74 Guido Trotter
  nicparams = opts.nicparams
505 5af3da74 Guido Trotter
  utils.ForceDictType(nicparams, constants.NICS_PARAMETER_TYPES)
506 5af3da74 Guido Trotter
507 b8a8fbe1 Guido Trotter
  op = opcodes.OpSetClusterParams(vg_name=vg_name,
508 779c15bb Iustin Pop
                                  enabled_hypervisors=hvlist,
509 779c15bb Iustin Pop
                                  hvparams=hvparams,
510 4b7735f9 Iustin Pop
                                  beparams=beparams,
511 5af3da74 Guido Trotter
                                  nicparams=nicparams,
512 4b7735f9 Iustin Pop
                                  candidate_pool_size=opts.candidate_pool_size)
513 90b6aa3a Manuel Franceschini
  SubmitOpCode(op)
514 90b6aa3a Manuel Franceschini
  return 0
515 90b6aa3a Manuel Franceschini
516 90b6aa3a Manuel Franceschini
517 3ccafd0e Iustin Pop
def QueueOps(opts, args):
518 3ccafd0e Iustin Pop
  """Queue operations.
519 3ccafd0e Iustin Pop
520 469ee405 Iustin Pop
  @param opts: the command line options selected by the user
521 469ee405 Iustin Pop
  @type args: list
522 469ee405 Iustin Pop
  @param args: should contain only one element, the subcommand
523 469ee405 Iustin Pop
  @rtype: int
524 469ee405 Iustin Pop
  @return: the desired exit code
525 469ee405 Iustin Pop
526 3ccafd0e Iustin Pop
  """
527 3ccafd0e Iustin Pop
  command = args[0]
528 3ccafd0e Iustin Pop
  client = GetClient()
529 3ccafd0e Iustin Pop
  if command in ("drain", "undrain"):
530 3ccafd0e Iustin Pop
    drain_flag = command == "drain"
531 3ccafd0e Iustin Pop
    client.SetQueueDrainFlag(drain_flag)
532 3ccafd0e Iustin Pop
  elif command == "info":
533 3ccafd0e Iustin Pop
    result = client.QueryConfigValues(["drain_flag"])
534 3ccafd0e Iustin Pop
    if result[0]:
535 3a24c527 Iustin Pop
      val = "set"
536 3ccafd0e Iustin Pop
    else:
537 3a24c527 Iustin Pop
      val = "unset"
538 3a24c527 Iustin Pop
    ToStdout("The drain flag is %s" % val)
539 2e668b38 Guido Trotter
  else:
540 2e668b38 Guido Trotter
    raise errors.OpPrereqError("Command '%s' is not valid." % command)
541 2e668b38 Guido Trotter
542 3ccafd0e Iustin Pop
  return 0
543 3ccafd0e Iustin Pop
544 95b2e626 Michael Hanselmann
545 28b498cd Michael Hanselmann
def _ShowWatcherPause(until):
546 28b498cd Michael Hanselmann
  if until is None or until < time.time():
547 28b498cd Michael Hanselmann
    ToStdout("The watcher is not paused.")
548 28b498cd Michael Hanselmann
  else:
549 28b498cd Michael Hanselmann
    ToStdout("The watcher is paused until %s.", time.ctime(until))
550 28b498cd Michael Hanselmann
551 28b498cd Michael Hanselmann
552 95b2e626 Michael Hanselmann
def WatcherOps(opts, args):
553 95b2e626 Michael Hanselmann
  """Watcher operations.
554 95b2e626 Michael Hanselmann
555 95b2e626 Michael Hanselmann
  @param opts: the command line options selected by the user
556 95b2e626 Michael Hanselmann
  @type args: list
557 95b2e626 Michael Hanselmann
  @param args: should contain only one element, the subcommand
558 95b2e626 Michael Hanselmann
  @rtype: int
559 95b2e626 Michael Hanselmann
  @return: the desired exit code
560 95b2e626 Michael Hanselmann
561 95b2e626 Michael Hanselmann
  """
562 95b2e626 Michael Hanselmann
  command = args[0]
563 95b2e626 Michael Hanselmann
  client = GetClient()
564 95b2e626 Michael Hanselmann
565 95b2e626 Michael Hanselmann
  if command == "continue":
566 95b2e626 Michael Hanselmann
    client.SetWatcherPause(None)
567 28b498cd Michael Hanselmann
    ToStdout("The watcher is no longer paused.")
568 95b2e626 Michael Hanselmann
569 95b2e626 Michael Hanselmann
  elif command == "pause":
570 95b2e626 Michael Hanselmann
    if len(args) < 2:
571 95b2e626 Michael Hanselmann
      raise errors.OpPrereqError("Missing pause duration")
572 95b2e626 Michael Hanselmann
573 28b498cd Michael Hanselmann
    result = client.SetWatcherPause(time.time() + ParseTimespec(args[1]))
574 28b498cd Michael Hanselmann
    _ShowWatcherPause(result)
575 95b2e626 Michael Hanselmann
576 95b2e626 Michael Hanselmann
  elif command == "info":
577 95b2e626 Michael Hanselmann
    result = client.QueryConfigValues(["watcher_pause"])
578 28b498cd Michael Hanselmann
    _ShowWatcherPause(result)
579 95b2e626 Michael Hanselmann
580 95b2e626 Michael Hanselmann
  else:
581 95b2e626 Michael Hanselmann
    raise errors.OpPrereqError("Command '%s' is not valid." % command)
582 95b2e626 Michael Hanselmann
583 95b2e626 Michael Hanselmann
  return 0
584 95b2e626 Michael Hanselmann
585 95b2e626 Michael Hanselmann
586 a8083063 Iustin Pop
# this is an option common to more than one command, so we declare
587 a8083063 Iustin Pop
# it here and reuse it
588 c38c44ad Michael Hanselmann
node_option = cli_option("-n", "--node", action="append", dest="nodes",
589 c38c44ad Michael Hanselmann
                         help="Node to copy to (if not given, all nodes),"
590 c38c44ad Michael Hanselmann
                              " can be given multiple times",
591 c38c44ad Michael Hanselmann
                         metavar="<node>", default=[])
592 a8083063 Iustin Pop
593 a8083063 Iustin Pop
commands = {
594 83ec7961 Michael Hanselmann
  'init': (InitCluster, [ArgHost(min=1, max=1)],
595 a8083063 Iustin Pop
           [DEBUG_OPT,
596 c38c44ad Michael Hanselmann
            cli_option("-s", "--secondary-ip", dest="secondary_ip",
597 c38c44ad Michael Hanselmann
                       help="Specify the secondary ip for this node;"
598 c38c44ad Michael Hanselmann
                       " if given, the entire cluster must have secondary"
599 c38c44ad Michael Hanselmann
                       " addresses",
600 c38c44ad Michael Hanselmann
                       metavar="ADDRESS", default=None),
601 c38c44ad Michael Hanselmann
            cli_option("-m", "--mac-prefix", dest="mac_prefix",
602 c38c44ad Michael Hanselmann
                       help="Specify the mac prefix for the instance IP"
603 c38c44ad Michael Hanselmann
                       " addresses, in the format XX:XX:XX",
604 c38c44ad Michael Hanselmann
                       metavar="PREFIX",
605 c38c44ad Michael Hanselmann
                       default=constants.DEFAULT_MAC_PREFIX,),
606 c38c44ad Michael Hanselmann
            cli_option("-g", "--vg-name", dest="vg_name",
607 c38c44ad Michael Hanselmann
                       help="Specify the volume group name "
608 c38c44ad Michael Hanselmann
                       " (cluster-wide) for disk allocation [xenvg]",
609 c38c44ad Michael Hanselmann
                       metavar="VG",
610 c38c44ad Michael Hanselmann
                       default=None,),
611 c38c44ad Michael Hanselmann
            cli_option("--master-netdev", dest="master_netdev",
612 c38c44ad Michael Hanselmann
                       help="Specify the node interface (cluster-wide)"
613 c38c44ad Michael Hanselmann
                         " on which the master IP address will be added "
614 c38c44ad Michael Hanselmann
                         " [%s]" % constants.DEFAULT_BRIDGE,
615 c38c44ad Michael Hanselmann
                       metavar="NETDEV",
616 c38c44ad Michael Hanselmann
                       default=constants.DEFAULT_BRIDGE,),
617 c38c44ad Michael Hanselmann
            cli_option("--file-storage-dir", dest="file_storage_dir",
618 c38c44ad Michael Hanselmann
                       help="Specify the default directory (cluster-wide)"
619 c38c44ad Michael Hanselmann
                            " for storing the file-based disks [%s]" %
620 c38c44ad Michael Hanselmann
                            constants.DEFAULT_FILE_STORAGE_DIR,
621 c38c44ad Michael Hanselmann
                       metavar="DIR",
622 c38c44ad Michael Hanselmann
                       default=constants.DEFAULT_FILE_STORAGE_DIR,),
623 c38c44ad Michael Hanselmann
            cli_option("--no-lvm-storage", dest="lvm_storage",
624 c38c44ad Michael Hanselmann
                       help="No support for lvm based instances"
625 c38c44ad Michael Hanselmann
                            " (cluster-wide)",
626 c38c44ad Michael Hanselmann
                       action="store_false", default=True,),
627 c38c44ad Michael Hanselmann
            cli_option("--no-etc-hosts", dest="modify_etc_hosts",
628 c38c44ad Michael Hanselmann
                       help="Don't modify /etc/hosts"
629 c38c44ad Michael Hanselmann
                            " (cluster-wide)",
630 c38c44ad Michael Hanselmann
                       action="store_false", default=True,),
631 c38c44ad Michael Hanselmann
            cli_option("--enabled-hypervisors", dest="enabled_hypervisors",
632 c38c44ad Michael Hanselmann
                       help="Comma-separated list of hypervisors",
633 c38c44ad Michael Hanselmann
                       type="string",
634 c38c44ad Michael Hanselmann
                       default=constants.DEFAULT_ENABLED_HYPERVISOR),
635 552c8dff Michael Hanselmann
            cli_option("-H", "--hypervisor-parameters", dest="hvparams",
636 c38c44ad Michael Hanselmann
                       help="Hypervisor and hypervisor options, in the format"
637 c38c44ad Michael Hanselmann
                            " hypervisor:option=value,option=value,...",
638 ea3a925f Alexander Schreiber
                       default=[],
639 ea3a925f Alexander Schreiber
                       action="append",
640 ea3a925f Alexander Schreiber
                       type="identkeyval"),
641 552c8dff Michael Hanselmann
            cli_option("-B", "--backend-parameters", dest="beparams",
642 552c8dff Michael Hanselmann
                       type="keyval", default={},
643 552c8dff Michael Hanselmann
                       help="Backend parameters"),
644 552c8dff Michael Hanselmann
            cli_option("-N", "--nic-parameters", dest="nicparams",
645 552c8dff Michael Hanselmann
                       type="keyval", default={},
646 552c8dff Michael Hanselmann
                       help="NIC parameters"),
647 c38c44ad Michael Hanselmann
            cli_option("-C", "--candidate-pool-size",
648 c38c44ad Michael Hanselmann
                       default=constants.MASTER_POOL_SIZE_DEFAULT,
649 c38c44ad Michael Hanselmann
                       help="Set the candidate pool size",
650 c38c44ad Michael Hanselmann
                       dest="candidate_pool_size", type="int"),
651 a8083063 Iustin Pop
            ],
652 9a033156 Iustin Pop
           "[opts...] <cluster_name>",
653 a8083063 Iustin Pop
           "Initialises a new cluster configuration"),
654 4a265c08 Michael Hanselmann
  'destroy': (DestroyCluster, ARGS_NONE,
655 a8083063 Iustin Pop
              [DEBUG_OPT,
656 c38c44ad Michael Hanselmann
               cli_option("--yes-do-it", dest="yes_do_it",
657 c38c44ad Michael Hanselmann
                          help="Destroy cluster",
658 c38c44ad Michael Hanselmann
                          action="store_true"),
659 a8083063 Iustin Pop
              ],
660 9a033156 Iustin Pop
              "", "Destroy cluster"),
661 83ec7961 Michael Hanselmann
  'rename': (RenameCluster, [ArgHost(min=1, max=1)],
662 a8005e17 Michael Hanselmann
             [DEBUG_OPT, FORCE_OPT],
663 a8005e17 Michael Hanselmann
             "<new_name>",
664 a8005e17 Michael Hanselmann
             "Renames the cluster"),
665 4a265c08 Michael Hanselmann
  'redist-conf': (RedistributeConfig, ARGS_NONE, [DEBUG_OPT, SUBMIT_OPT],
666 afee0879 Iustin Pop
                  "",
667 afee0879 Iustin Pop
                  "Forces a push of the configuration file and ssconf files"
668 afee0879 Iustin Pop
                  " to the nodes in the cluster"),
669 4a265c08 Michael Hanselmann
  'verify': (VerifyCluster, ARGS_NONE, [DEBUG_OPT,
670 c38c44ad Michael Hanselmann
             cli_option("--no-nplus1-mem", dest="skip_nplusone_mem",
671 c38c44ad Michael Hanselmann
                        help="Skip N+1 memory redundancy tests",
672 c38c44ad Michael Hanselmann
                        action="store_true",
673 c38c44ad Michael Hanselmann
                        default=False,),
674 e54c4c5e Guido Trotter
             ],
675 9a033156 Iustin Pop
             "", "Does a check on the cluster configuration"),
676 4a265c08 Michael Hanselmann
  'verify-disks': (VerifyDisks, ARGS_NONE, [DEBUG_OPT],
677 9a033156 Iustin Pop
                   "", "Does a check on the cluster disk status"),
678 4a265c08 Michael Hanselmann
  'repair-disk-sizes': (RepairDiskSizes, ARGS_MANY_INSTANCES, [DEBUG_OPT],
679 60975797 Iustin Pop
                   "", "Updates mismatches in recorded disk sizes"),
680 4a265c08 Michael Hanselmann
  'masterfailover': (MasterFailover, ARGS_NONE, [DEBUG_OPT,
681 c38c44ad Michael Hanselmann
                     cli_option("--no-voting", dest="no_voting",
682 c38c44ad Michael Hanselmann
                                help="Skip node agreement check (dangerous)",
683 c38c44ad Michael Hanselmann
                                action="store_true",
684 c38c44ad Michael Hanselmann
                                default=False,),
685 8e2524c3 Guido Trotter
                     ],
686 9a033156 Iustin Pop
                     "", "Makes the current node the master"),
687 4a265c08 Michael Hanselmann
  'version': (ShowClusterVersion, ARGS_NONE, [DEBUG_OPT],
688 9a033156 Iustin Pop
              "", "Shows the cluster version"),
689 4a265c08 Michael Hanselmann
  'getmaster': (ShowClusterMaster, ARGS_NONE, [DEBUG_OPT],
690 9a033156 Iustin Pop
                "", "Shows the cluster master"),
691 a8005e17 Michael Hanselmann
  'copyfile': (ClusterCopyFile, [ArgFile(min=1, max=1)],
692 a8005e17 Michael Hanselmann
               [DEBUG_OPT, node_option],
693 9a033156 Iustin Pop
               "[-n node...] <filename>",
694 a8083063 Iustin Pop
               "Copies a file to all (or only some) nodes"),
695 a8005e17 Michael Hanselmann
  'command': (RunClusterCommand, [ArgCommand(min=1)], [DEBUG_OPT, node_option],
696 9a033156 Iustin Pop
              "[-n node...] <command>",
697 a8083063 Iustin Pop
              "Runs a command on all (or only some) nodes"),
698 4a265c08 Michael Hanselmann
  'info': (ShowClusterConfig, ARGS_NONE, [DEBUG_OPT],
699 a8005e17 Michael Hanselmann
           "", "Show cluster configuration"),
700 4a265c08 Michael Hanselmann
  'list-tags': (ListTags, ARGS_NONE,
701 9a033156 Iustin Pop
                [DEBUG_OPT], "", "List the tags of the cluster"),
702 a8005e17 Michael Hanselmann
  'add-tags': (AddTags, [ArgUnknown()], [DEBUG_OPT, TAG_SRC_OPT],
703 9a033156 Iustin Pop
               "tag...", "Add tags to the cluster"),
704 a8005e17 Michael Hanselmann
  'remove-tags': (RemoveTags, [ArgUnknown()], [DEBUG_OPT, TAG_SRC_OPT],
705 9a033156 Iustin Pop
                  "tag...", "Remove tags from the cluster"),
706 a8005e17 Michael Hanselmann
  'search-tags': (SearchTags, [ArgUnknown(min=1, max=1)],
707 9a033156 Iustin Pop
                  [DEBUG_OPT], "", "Searches the tags on all objects on"
708 73415719 Iustin Pop
                  " the cluster for a given pattern (regex)"),
709 a8005e17 Michael Hanselmann
  'queue': (QueueOps,
710 a8005e17 Michael Hanselmann
            [ArgChoice(min=1, max=1, choices=["drain", "undrain", "info"])],
711 a8005e17 Michael Hanselmann
            [DEBUG_OPT],
712 3ccafd0e Iustin Pop
            "drain|undrain|info", "Change queue properties"),
713 95b2e626 Michael Hanselmann
  'watcher': (WatcherOps,
714 95b2e626 Michael Hanselmann
              [ArgChoice(min=1, max=1,
715 95b2e626 Michael Hanselmann
                         choices=["pause", "continue", "info"]),
716 95b2e626 Michael Hanselmann
               ArgSuggest(min=0, max=1, choices=["30m", "1h", "4h"])],
717 95b2e626 Michael Hanselmann
              [DEBUG_OPT],
718 95b2e626 Michael Hanselmann
              "{pause <timespec>|continue|info}", "Change watcher properties"),
719 4a265c08 Michael Hanselmann
  'modify': (SetClusterParams, ARGS_NONE,
720 90b6aa3a Manuel Franceschini
             [DEBUG_OPT,
721 c38c44ad Michael Hanselmann
              cli_option("-g", "--vg-name", dest="vg_name",
722 c38c44ad Michael Hanselmann
                         help="Specify the volume group name "
723 c38c44ad Michael Hanselmann
                         " (cluster-wide) for disk allocation "
724 c38c44ad Michael Hanselmann
                         "and enable lvm based storage",
725 c38c44ad Michael Hanselmann
                         metavar="VG",),
726 c38c44ad Michael Hanselmann
              cli_option("--no-lvm-storage", dest="lvm_storage",
727 c38c44ad Michael Hanselmann
                         help="Disable support for lvm based instances"
728 c38c44ad Michael Hanselmann
                              " (cluster-wide)",
729 c38c44ad Michael Hanselmann
                         action="store_false", default=True,),
730 c38c44ad Michael Hanselmann
              cli_option("--enabled-hypervisors", dest="enabled_hypervisors",
731 c38c44ad Michael Hanselmann
                         help="Comma-separated list of hypervisors",
732 c38c44ad Michael Hanselmann
                         type="string", default=None),
733 552c8dff Michael Hanselmann
              cli_option("-H", "--hypervisor-parameters", dest="hvparams",
734 779c15bb Iustin Pop
                         help="Hypervisor and hypervisor options, in the"
735 779c15bb Iustin Pop
                         " format"
736 779c15bb Iustin Pop
                         " hypervisor:option=value,option=value,...",
737 779c15bb Iustin Pop
                         default=[],
738 779c15bb Iustin Pop
                         action="append",
739 779c15bb Iustin Pop
                         type="identkeyval"),
740 552c8dff Michael Hanselmann
              cli_option("-B", "--backend-parameters", dest="beparams",
741 552c8dff Michael Hanselmann
                         type="keyval", default={},
742 552c8dff Michael Hanselmann
                         help="Backend parameters"),
743 552c8dff Michael Hanselmann
              cli_option("-N", "--nic-parameters", dest="nicparams",
744 552c8dff Michael Hanselmann
                         type="keyval", default={},
745 552c8dff Michael Hanselmann
                         help="NIC parameters"),
746 c38c44ad Michael Hanselmann
              cli_option("-C", "--candidate-pool-size", default=None,
747 c38c44ad Michael Hanselmann
                         help="Set the candidate pool size",
748 c38c44ad Michael Hanselmann
                         dest="candidate_pool_size", type="int"),
749 90b6aa3a Manuel Franceschini
              ],
750 90b6aa3a Manuel Franceschini
             "[opts...]",
751 90b6aa3a Manuel Franceschini
             "Alters the parameters of the cluster"),
752 a8083063 Iustin Pop
  }
753 a8083063 Iustin Pop
754 a8083063 Iustin Pop
if __name__ == '__main__':
755 846baef9 Iustin Pop
  sys.exit(GenericMain(commands, override={"tag_type": constants.TAG_CLUSTER}))