Statistics
| Branch: | Tag: | Revision:

root / scripts / gnt-cluster @ 168c1de2

History | View | Annotate | Download (23.9 kB)

1 a8083063 Iustin Pop
#!/usr/bin/python
2 a8083063 Iustin Pop
#
3 a8083063 Iustin Pop
4 a8083063 Iustin Pop
# Copyright (C) 2006, 2007 Google Inc.
5 a8083063 Iustin Pop
#
6 a8083063 Iustin Pop
# This program is free software; you can redistribute it and/or modify
7 a8083063 Iustin Pop
# it under the terms of the GNU General Public License as published by
8 a8083063 Iustin Pop
# the Free Software Foundation; either version 2 of the License, or
9 a8083063 Iustin Pop
# (at your option) any later version.
10 a8083063 Iustin Pop
#
11 a8083063 Iustin Pop
# This program is distributed in the hope that it will be useful, but
12 a8083063 Iustin Pop
# WITHOUT ANY WARRANTY; without even the implied warranty of
13 a8083063 Iustin Pop
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 a8083063 Iustin Pop
# General Public License for more details.
15 a8083063 Iustin Pop
#
16 a8083063 Iustin Pop
# You should have received a copy of the GNU General Public License
17 a8083063 Iustin Pop
# along with this program; if not, write to the Free Software
18 a8083063 Iustin Pop
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 a8083063 Iustin Pop
# 02110-1301, USA.
20 a8083063 Iustin Pop
21 7260cfbe Iustin Pop
"""Cluster related commands"""
22 a8083063 Iustin Pop
23 2d54e29c Iustin Pop
# pylint: disable-msg=W0401,W0613,W0614,C0103
24 2f79bd34 Iustin Pop
# W0401: Wildcard import ganeti.cli
25 2d54e29c Iustin Pop
# W0613: Unused argument, since all functions follow the same API
26 2f79bd34 Iustin Pop
# W0614: Unused import %s from wildcard import (since we need cli)
27 7260cfbe Iustin Pop
# C0103: Invalid name gnt-cluster
28 2f79bd34 Iustin Pop
29 a8083063 Iustin Pop
import sys
30 b3989551 Iustin Pop
import os.path
31 95b2e626 Michael Hanselmann
import time
32 6d4a1656 Michael Hanselmann
import OpenSSL
33 a8083063 Iustin Pop
34 a8083063 Iustin Pop
from ganeti.cli import *
35 a8083063 Iustin Pop
from ganeti import opcodes
36 c2a62a33 Michael Hanselmann
from ganeti import constants
37 f4d4e184 Iustin Pop
from ganeti import errors
38 b63ed789 Iustin Pop
from ganeti import utils
39 a0c9f010 Michael Hanselmann
from ganeti import bootstrap
40 b3989551 Iustin Pop
from ganeti import ssh
41 d3cfe525 Guido Trotter
from ganeti import objects
42 a8083063 Iustin Pop
43 a8083063 Iustin Pop
44 4331f6cd Michael Hanselmann
@UsesRPC
45 a8083063 Iustin Pop
def InitCluster(opts, args):
46 a8083063 Iustin Pop
  """Initialize the cluster.
47 a8083063 Iustin Pop
48 469ee405 Iustin Pop
  @param opts: the command line options selected by the user
49 469ee405 Iustin Pop
  @type args: list
50 469ee405 Iustin Pop
  @param args: should contain only one element, the desired
51 469ee405 Iustin Pop
      cluster name
52 469ee405 Iustin Pop
  @rtype: int
53 469ee405 Iustin Pop
  @return: the desired exit code
54 a8083063 Iustin Pop
55 a8083063 Iustin Pop
  """
56 90b6aa3a Manuel Franceschini
  if not opts.lvm_storage and opts.vg_name:
57 3a24c527 Iustin Pop
    ToStderr("Options --no-lvm-storage and --vg-name conflict.")
58 90b6aa3a Manuel Franceschini
    return 1
59 90b6aa3a Manuel Franceschini
60 90b6aa3a Manuel Franceschini
  vg_name = opts.vg_name
61 90b6aa3a Manuel Franceschini
  if opts.lvm_storage and not opts.vg_name:
62 90b6aa3a Manuel Franceschini
    vg_name = constants.DEFAULT_VG
63 90b6aa3a Manuel Franceschini
64 ea3a925f Alexander Schreiber
  hvlist = opts.enabled_hypervisors
65 383a3591 Iustin Pop
  if hvlist is None:
66 383a3591 Iustin Pop
    hvlist = constants.DEFAULT_ENABLED_HYPERVISOR
67 066f465d Guido Trotter
  hvlist = hvlist.split(",")
68 ea3a925f Alexander Schreiber
69 f8e7ddca Guido Trotter
  hvparams = dict(opts.hvparams)
70 ea3a925f Alexander Schreiber
  beparams = opts.beparams
71 b6a30b0d Guido Trotter
  nicparams = opts.nicparams
72 ea3a925f Alexander Schreiber
73 ea3a925f Alexander Schreiber
  # prepare beparams dict
74 d3cfe525 Guido Trotter
  beparams = objects.FillDict(constants.BEC_DEFAULTS, beparams)
75 a5728081 Guido Trotter
  utils.ForceDictType(beparams, constants.BES_PARAMETER_TYPES)
76 ea3a925f Alexander Schreiber
77 b6a30b0d Guido Trotter
  # prepare nicparams dict
78 b6a30b0d Guido Trotter
  nicparams = objects.FillDict(constants.NICC_DEFAULTS, nicparams)
79 b6a30b0d Guido Trotter
  utils.ForceDictType(nicparams, constants.NICS_PARAMETER_TYPES)
80 b6a30b0d Guido Trotter
81 ea3a925f Alexander Schreiber
  # prepare hvparams dict
82 ea3a925f Alexander Schreiber
  for hv in constants.HYPER_TYPES:
83 ea3a925f Alexander Schreiber
    if hv not in hvparams:
84 ea3a925f Alexander Schreiber
      hvparams[hv] = {}
85 d3cfe525 Guido Trotter
    hvparams[hv] = objects.FillDict(constants.HVC_DEFAULTS[hv], hvparams[hv])
86 a5728081 Guido Trotter
    utils.ForceDictType(hvparams[hv], constants.HVS_PARAMETER_TYPES)
87 ea3a925f Alexander Schreiber
88 e32df528 Iustin Pop
  if opts.candidate_pool_size is None:
89 e32df528 Iustin Pop
    opts.candidate_pool_size = constants.MASTER_POOL_SIZE_DEFAULT
90 e32df528 Iustin Pop
91 e3646f22 Iustin Pop
  if opts.mac_prefix is None:
92 e3646f22 Iustin Pop
    opts.mac_prefix = constants.DEFAULT_MAC_PREFIX
93 e3646f22 Iustin Pop
94 a0c9f010 Michael Hanselmann
  bootstrap.InitCluster(cluster_name=args[0],
95 a0c9f010 Michael Hanselmann
                        secondary_ip=opts.secondary_ip,
96 a0c9f010 Michael Hanselmann
                        vg_name=vg_name,
97 a0c9f010 Michael Hanselmann
                        mac_prefix=opts.mac_prefix,
98 a0c9f010 Michael Hanselmann
                        master_netdev=opts.master_netdev,
99 ea3a925f Alexander Schreiber
                        file_storage_dir=opts.file_storage_dir,
100 ea3a925f Alexander Schreiber
                        enabled_hypervisors=hvlist,
101 ea3a925f Alexander Schreiber
                        hvparams=hvparams,
102 ce735215 Guido Trotter
                        beparams=beparams,
103 b6a30b0d Guido Trotter
                        nicparams=nicparams,
104 ce735215 Guido Trotter
                        candidate_pool_size=opts.candidate_pool_size,
105 b86a6bcd Guido Trotter
                        modify_etc_hosts=opts.modify_etc_hosts,
106 b989b9d9 Ken Wehr
                        modify_ssh_setup=opts.modify_ssh_setup,
107 ce735215 Guido Trotter
                        )
108 3552cd2e Luca Bigliardi
  op = opcodes.OpPostInitCluster()
109 400ca2f7 Iustin Pop
  SubmitOpCode(op, opts=opts)
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 400ca2f7 Iustin Pop
  master = SubmitOpCode(op, opts=opts)
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 400ca2f7 Iustin Pop
  SubmitOpCode(op, opts=opts)
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 cac599f1 Michael Hanselmann
211 664a9d73 Renรฉ Nussbaumer
def _PrintGroupedParams(paramsdict, level=1):
212 1094acda Guido Trotter
  """Print Grouped parameters (be, nic, disk) by group.
213 1094acda Guido Trotter
214 1094acda Guido Trotter
  @type paramsdict: dict of dicts
215 1094acda Guido Trotter
  @param paramsdict: {group: {param: value, ...}, ...}
216 664a9d73 Renรฉ Nussbaumer
  @type level: int
217 664a9d73 Renรฉ Nussbaumer
  @param level: Level of indention
218 1094acda Guido Trotter
219 1094acda Guido Trotter
  """
220 664a9d73 Renรฉ Nussbaumer
  indent = "  " * level
221 664a9d73 Renรฉ Nussbaumer
  for item, val in paramsdict.items():
222 664a9d73 Renรฉ Nussbaumer
    if isinstance(val, dict):
223 664a9d73 Renรฉ Nussbaumer
      ToStdout("%s- %s:", indent, item)
224 664a9d73 Renรฉ Nussbaumer
      _PrintGroupedParams(val, level=level + 1)
225 664a9d73 Renรฉ Nussbaumer
    else:
226 664a9d73 Renรฉ Nussbaumer
      ToStdout("%s  %s: %s", indent, item, val)
227 a8083063 Iustin Pop
228 cac599f1 Michael Hanselmann
229 a8083063 Iustin Pop
def ShowClusterConfig(opts, args):
230 a8083063 Iustin Pop
  """Shows cluster information.
231 a8083063 Iustin Pop
232 469ee405 Iustin Pop
  @param opts: the command line options selected by the user
233 469ee405 Iustin Pop
  @type args: list
234 469ee405 Iustin Pop
  @param args: should be an empty list
235 469ee405 Iustin Pop
  @rtype: int
236 469ee405 Iustin Pop
  @return: the desired exit code
237 469ee405 Iustin Pop
238 a8083063 Iustin Pop
  """
239 2e7b8369 Iustin Pop
  cl = GetClient()
240 2e7b8369 Iustin Pop
  result = cl.QueryClusterInfo()
241 a8083063 Iustin Pop
242 3a24c527 Iustin Pop
  ToStdout("Cluster name: %s", result["name"])
243 259578eb Iustin Pop
  ToStdout("Cluster UUID: %s", result["uuid"])
244 a8083063 Iustin Pop
245 90f72445 Iustin Pop
  ToStdout("Creation time: %s", utils.FormatTime(result["ctime"]))
246 90f72445 Iustin Pop
  ToStdout("Modification time: %s", utils.FormatTime(result["mtime"]))
247 90f72445 Iustin Pop
248 3a24c527 Iustin Pop
  ToStdout("Master node: %s", result["master"])
249 a8083063 Iustin Pop
250 3a24c527 Iustin Pop
  ToStdout("Architecture (this node): %s (%s)",
251 3a24c527 Iustin Pop
           result["architecture"][0], result["architecture"][1])
252 a8083063 Iustin Pop
253 c118d1f4 Michael Hanselmann
  if result["tags"]:
254 1f864b60 Iustin Pop
    tags = utils.CommaJoin(utils.NiceSort(result["tags"]))
255 c118d1f4 Michael Hanselmann
  else:
256 c118d1f4 Michael Hanselmann
    tags = "(none)"
257 c118d1f4 Michael Hanselmann
258 c118d1f4 Michael Hanselmann
  ToStdout("Tags: %s", tags)
259 c118d1f4 Michael Hanselmann
260 02691904 Alexander Schreiber
  ToStdout("Default hypervisor: %s", result["default_hypervisor"])
261 1f864b60 Iustin Pop
  ToStdout("Enabled hypervisors: %s",
262 1f864b60 Iustin Pop
           utils.CommaJoin(result["enabled_hypervisors"]))
263 469f88e1 Iustin Pop
264 3a24c527 Iustin Pop
  ToStdout("Hypervisor parameters:")
265 1094acda Guido Trotter
  _PrintGroupedParams(result["hvparams"])
266 469f88e1 Iustin Pop
267 664a9d73 Renรฉ Nussbaumer
  ToStdout("OS specific hypervisor parameters:")
268 664a9d73 Renรฉ Nussbaumer
  _PrintGroupedParams(result["os_hvp"])
269 664a9d73 Renรฉ Nussbaumer
270 3a24c527 Iustin Pop
  ToStdout("Cluster parameters:")
271 4b7735f9 Iustin Pop
  ToStdout("  - candidate pool size: %s", result["candidate_pool_size"])
272 a8001106 Guido Trotter
  ToStdout("  - master netdev: %s", result["master_netdev"])
273 a8001106 Guido Trotter
  ToStdout("  - lvm volume group: %s", result["volume_group_name"])
274 a8001106 Guido Trotter
  ToStdout("  - file storage path: %s", result["file_storage_dir"])
275 4b7735f9 Iustin Pop
276 4b7735f9 Iustin Pop
  ToStdout("Default instance parameters:")
277 1094acda Guido Trotter
  _PrintGroupedParams(result["beparams"])
278 1094acda Guido Trotter
279 1094acda Guido Trotter
  ToStdout("Default nic parameters:")
280 1094acda Guido Trotter
  _PrintGroupedParams(result["nicparams"])
281 8a12ce45 Iustin Pop
282 a8083063 Iustin Pop
  return 0
283 a8083063 Iustin Pop
284 a8083063 Iustin Pop
285 a8083063 Iustin Pop
def ClusterCopyFile(opts, args):
286 a8083063 Iustin Pop
  """Copy a file from master to some nodes.
287 a8083063 Iustin Pop
288 469ee405 Iustin Pop
  @param opts: the command line options selected by the user
289 469ee405 Iustin Pop
  @type args: list
290 469ee405 Iustin Pop
  @param args: should contain only one element, the path of
291 469ee405 Iustin Pop
      the file to be copied
292 469ee405 Iustin Pop
  @rtype: int
293 469ee405 Iustin Pop
  @return: the desired exit code
294 a8083063 Iustin Pop
295 a8083063 Iustin Pop
  """
296 b3989551 Iustin Pop
  filename = args[0]
297 b3989551 Iustin Pop
  if not os.path.exists(filename):
298 debac808 Iustin Pop
    raise errors.OpPrereqError("No such filename '%s'" % filename,
299 debac808 Iustin Pop
                               errors.ECODE_INVAL)
300 b3989551 Iustin Pop
301 56bece1f Iustin Pop
  cl = GetClient()
302 56bece1f Iustin Pop
303 104f4ca1 Iustin Pop
  myname = utils.GetHostInfo().name
304 b3989551 Iustin Pop
305 56bece1f Iustin Pop
  cluster_name = cl.QueryConfigValues(["cluster_name"])[0]
306 56bece1f Iustin Pop
307 4040a784 Iustin Pop
  results = GetOnlineNodes(nodes=opts.nodes, cl=cl)
308 4040a784 Iustin Pop
  results = [name for name in results if name != myname]
309 e00ea635 Michael Hanselmann
310 56bece1f Iustin Pop
  srun = ssh.SshRunner(cluster_name=cluster_name)
311 b3989551 Iustin Pop
  for node in results:
312 b3989551 Iustin Pop
    if not srun.CopyFileToNode(node, filename):
313 3a24c527 Iustin Pop
      ToStderr("Copy of file %s to node %s failed", filename, node)
314 b3989551 Iustin Pop
315 a8083063 Iustin Pop
  return 0
316 a8083063 Iustin Pop
317 a8083063 Iustin Pop
318 a8083063 Iustin Pop
def RunClusterCommand(opts, args):
319 a8083063 Iustin Pop
  """Run a command on some nodes.
320 a8083063 Iustin Pop
321 469ee405 Iustin Pop
  @param opts: the command line options selected by the user
322 469ee405 Iustin Pop
  @type args: list
323 469ee405 Iustin Pop
  @param args: should contain the command to be run and its arguments
324 469ee405 Iustin Pop
  @rtype: int
325 469ee405 Iustin Pop
  @return: the desired exit code
326 a8083063 Iustin Pop
327 a8083063 Iustin Pop
  """
328 56bece1f Iustin Pop
  cl = GetClient()
329 7688d0d3 Michael Hanselmann
330 a8083063 Iustin Pop
  command = " ".join(args)
331 4040a784 Iustin Pop
332 4040a784 Iustin Pop
  nodes = GetOnlineNodes(nodes=opts.nodes, cl=cl)
333 56bece1f Iustin Pop
334 56bece1f Iustin Pop
  cluster_name, master_node = cl.QueryConfigValues(["cluster_name",
335 56bece1f Iustin Pop
                                                    "master_node"])
336 b3989551 Iustin Pop
337 56bece1f Iustin Pop
  srun = ssh.SshRunner(cluster_name=cluster_name)
338 b3989551 Iustin Pop
339 7688d0d3 Michael Hanselmann
  # Make sure master node is at list end
340 b3989551 Iustin Pop
  if master_node in nodes:
341 b3989551 Iustin Pop
    nodes.remove(master_node)
342 b3989551 Iustin Pop
    nodes.append(master_node)
343 b3989551 Iustin Pop
344 b3989551 Iustin Pop
  for name in nodes:
345 b3989551 Iustin Pop
    result = srun.Run(name, "root", command)
346 3a24c527 Iustin Pop
    ToStdout("------------------------------------------------")
347 3a24c527 Iustin Pop
    ToStdout("node: %s", name)
348 3a24c527 Iustin Pop
    ToStdout("%s", result.output)
349 3a24c527 Iustin Pop
    ToStdout("return code = %s", result.exit_code)
350 b3989551 Iustin Pop
351 b3989551 Iustin Pop
  return 0
352 a8083063 Iustin Pop
353 a8083063 Iustin Pop
354 a8083063 Iustin Pop
def VerifyCluster(opts, args):
355 a8083063 Iustin Pop
  """Verify integrity of cluster, performing various test on nodes.
356 a8083063 Iustin Pop
357 469ee405 Iustin Pop
  @param opts: the command line options selected by the user
358 469ee405 Iustin Pop
  @type args: list
359 469ee405 Iustin Pop
  @param args: should be an empty list
360 469ee405 Iustin Pop
  @rtype: int
361 469ee405 Iustin Pop
  @return: the desired exit code
362 a8083063 Iustin Pop
363 a8083063 Iustin Pop
  """
364 8d59409f Iustin Pop
  skip_checks = []
365 e54c4c5e Guido Trotter
  if opts.skip_nplusone_mem:
366 e54c4c5e Guido Trotter
    skip_checks.append(constants.VERIFY_NPLUSONE_MEM)
367 7c874ee1 Iustin Pop
  op = opcodes.OpVerifyCluster(skip_checks=skip_checks,
368 7c874ee1 Iustin Pop
                               verbose=opts.verbose,
369 a0c9776a Iustin Pop
                               error_codes=opts.error_codes,
370 a0c9776a Iustin Pop
                               debug_simulate_errors=opts.simulate_errors)
371 400ca2f7 Iustin Pop
  if SubmitOpCode(op, opts=opts):
372 34290825 Michael Hanselmann
    return 0
373 34290825 Michael Hanselmann
  else:
374 34290825 Michael Hanselmann
    return 1
375 a8083063 Iustin Pop
376 a8083063 Iustin Pop
377 f4d4e184 Iustin Pop
def VerifyDisks(opts, args):
378 f4d4e184 Iustin Pop
  """Verify integrity of cluster disks.
379 f4d4e184 Iustin Pop
380 469ee405 Iustin Pop
  @param opts: the command line options selected by the user
381 469ee405 Iustin Pop
  @type args: list
382 469ee405 Iustin Pop
  @param args: should be an empty list
383 469ee405 Iustin Pop
  @rtype: int
384 469ee405 Iustin Pop
  @return: the desired exit code
385 f4d4e184 Iustin Pop
386 f4d4e184 Iustin Pop
  """
387 f4d4e184 Iustin Pop
  op = opcodes.OpVerifyDisks()
388 400ca2f7 Iustin Pop
  result = SubmitOpCode(op, opts=opts)
389 29d376ec Iustin Pop
  if not isinstance(result, (list, tuple)) or len(result) != 3:
390 f4d4e184 Iustin Pop
    raise errors.ProgrammerError("Unknown result type for OpVerifyDisks")
391 f4d4e184 Iustin Pop
392 29d376ec Iustin Pop
  bad_nodes, instances, missing = result
393 b63ed789 Iustin Pop
394 f4d4e184 Iustin Pop
  retcode = constants.EXIT_SUCCESS
395 b63ed789 Iustin Pop
396 29d376ec Iustin Pop
  if bad_nodes:
397 29d376ec Iustin Pop
    for node, text in bad_nodes.items():
398 29d376ec Iustin Pop
      ToStdout("Error gathering data on node %s: %s",
399 26f15862 Iustin Pop
               node, utils.SafeEncode(text[-400:]))
400 b63ed789 Iustin Pop
      retcode |= 1
401 3a24c527 Iustin Pop
      ToStdout("You need to fix these nodes first before fixing instances")
402 b63ed789 Iustin Pop
403 f4d4e184 Iustin Pop
  if instances:
404 f4d4e184 Iustin Pop
    for iname in instances:
405 b63ed789 Iustin Pop
      if iname in missing:
406 b63ed789 Iustin Pop
        continue
407 f4d4e184 Iustin Pop
      op = opcodes.OpActivateInstanceDisks(instance_name=iname)
408 f4d4e184 Iustin Pop
      try:
409 3a24c527 Iustin Pop
        ToStdout("Activating disks for instance '%s'", iname)
410 400ca2f7 Iustin Pop
        SubmitOpCode(op, opts=opts)
411 f4d4e184 Iustin Pop
      except errors.GenericError, err:
412 f4d4e184 Iustin Pop
        nret, msg = FormatError(err)
413 f4d4e184 Iustin Pop
        retcode |= nret
414 3a24c527 Iustin Pop
        ToStderr("Error activating disks for instance %s: %s", iname, msg)
415 b63ed789 Iustin Pop
416 b63ed789 Iustin Pop
  if missing:
417 b63ed789 Iustin Pop
    for iname, ival in missing.iteritems():
418 29d376ec Iustin Pop
      all_missing = utils.all(ival, lambda x: x[0] in bad_nodes)
419 b63ed789 Iustin Pop
      if all_missing:
420 3a24c527 Iustin Pop
        ToStdout("Instance %s cannot be verified as it lives on"
421 3a24c527 Iustin Pop
                 " broken nodes", iname)
422 b63ed789 Iustin Pop
      else:
423 3a24c527 Iustin Pop
        ToStdout("Instance %s has missing logical volumes:", iname)
424 b63ed789 Iustin Pop
        ival.sort()
425 b63ed789 Iustin Pop
        for node, vol in ival:
426 29d376ec Iustin Pop
          if node in bad_nodes:
427 3a24c527 Iustin Pop
            ToStdout("\tbroken node %s /dev/xenvg/%s", node, vol)
428 b63ed789 Iustin Pop
          else:
429 3a24c527 Iustin Pop
            ToStdout("\t%s /dev/xenvg/%s", node, vol)
430 3a24c527 Iustin Pop
    ToStdout("You need to run replace_disks for all the above"
431 b63ed789 Iustin Pop
           " instances, if this message persist after fixing nodes.")
432 b63ed789 Iustin Pop
    retcode |= 1
433 f4d4e184 Iustin Pop
434 f4d4e184 Iustin Pop
  return retcode
435 f4d4e184 Iustin Pop
436 f4d4e184 Iustin Pop
437 60975797 Iustin Pop
def RepairDiskSizes(opts, args):
438 60975797 Iustin Pop
  """Verify sizes of cluster disks.
439 60975797 Iustin Pop
440 60975797 Iustin Pop
  @param opts: the command line options selected by the user
441 60975797 Iustin Pop
  @type args: list
442 60975797 Iustin Pop
  @param args: optional list of instances to restrict check to
443 60975797 Iustin Pop
  @rtype: int
444 60975797 Iustin Pop
  @return: the desired exit code
445 60975797 Iustin Pop
446 60975797 Iustin Pop
  """
447 60975797 Iustin Pop
  op = opcodes.OpRepairDiskSizes(instances=args)
448 400ca2f7 Iustin Pop
  SubmitOpCode(op, opts=opts)
449 60975797 Iustin Pop
450 60975797 Iustin Pop
451 4331f6cd Michael Hanselmann
@UsesRPC
452 a8083063 Iustin Pop
def MasterFailover(opts, args):
453 a8083063 Iustin Pop
  """Failover the master node.
454 a8083063 Iustin Pop
455 a8083063 Iustin Pop
  This command, when run on a non-master node, will cause the current
456 a8083063 Iustin Pop
  master to cease being master, and the non-master to become new
457 a8083063 Iustin Pop
  master.
458 a8083063 Iustin Pop
459 469ee405 Iustin Pop
  @param opts: the command line options selected by the user
460 469ee405 Iustin Pop
  @type args: list
461 469ee405 Iustin Pop
  @param args: should be an empty list
462 469ee405 Iustin Pop
  @rtype: int
463 469ee405 Iustin Pop
  @return: the desired exit code
464 469ee405 Iustin Pop
465 a8083063 Iustin Pop
  """
466 8e2524c3 Guido Trotter
  if opts.no_voting:
467 8e2524c3 Guido Trotter
    usertext = ("This will perform the failover even if most other nodes"
468 8e2524c3 Guido Trotter
                " are down, or if this node is outdated. This is dangerous"
469 8e2524c3 Guido Trotter
                " as it can lead to a non-consistent cluster. Check the"
470 8e2524c3 Guido Trotter
                " gnt-cluster(8) man page before proceeding. Continue?")
471 8e2524c3 Guido Trotter
    if not AskUser(usertext):
472 8e2524c3 Guido Trotter
      return 1
473 8e2524c3 Guido Trotter
474 8e2524c3 Guido Trotter
  return bootstrap.MasterFailover(no_voting=opts.no_voting)
475 a8083063 Iustin Pop
476 a8083063 Iustin Pop
477 73415719 Iustin Pop
def SearchTags(opts, args):
478 73415719 Iustin Pop
  """Searches the tags on all the cluster.
479 73415719 Iustin Pop
480 469ee405 Iustin Pop
  @param opts: the command line options selected by the user
481 469ee405 Iustin Pop
  @type args: list
482 469ee405 Iustin Pop
  @param args: should contain only one element, the tag pattern
483 469ee405 Iustin Pop
  @rtype: int
484 469ee405 Iustin Pop
  @return: the desired exit code
485 469ee405 Iustin Pop
486 73415719 Iustin Pop
  """
487 73415719 Iustin Pop
  op = opcodes.OpSearchTags(pattern=args[0])
488 400ca2f7 Iustin Pop
  result = SubmitOpCode(op, opts=opts)
489 73415719 Iustin Pop
  if not result:
490 73415719 Iustin Pop
    return 1
491 73415719 Iustin Pop
  result = list(result)
492 73415719 Iustin Pop
  result.sort()
493 73415719 Iustin Pop
  for path, tag in result:
494 3a24c527 Iustin Pop
    ToStdout("%s %s", path, tag)
495 73415719 Iustin Pop
496 73415719 Iustin Pop
497 6d4a1656 Michael Hanselmann
def _RenewCrypto(new_cluster_cert, new_rapi_cert, rapi_cert_filename,
498 6d4a1656 Michael Hanselmann
                 new_hmac_key, force):
499 6d4a1656 Michael Hanselmann
  """Renews cluster certificates, keys and secrets.
500 6d4a1656 Michael Hanselmann
501 6d4a1656 Michael Hanselmann
  @type new_cluster_cert: bool
502 6d4a1656 Michael Hanselmann
  @param new_cluster_cert: Whether to generate a new cluster certificate
503 6d4a1656 Michael Hanselmann
  @type new_rapi_cert: bool
504 6d4a1656 Michael Hanselmann
  @param new_rapi_cert: Whether to generate a new RAPI certificate
505 6d4a1656 Michael Hanselmann
  @type rapi_cert_filename: string
506 6d4a1656 Michael Hanselmann
  @param rapi_cert_filename: Path to file containing new RAPI certificate
507 6d4a1656 Michael Hanselmann
  @type new_hmac_key: bool
508 6d4a1656 Michael Hanselmann
  @param new_hmac_key: Whether to generate a new HMAC key
509 6d4a1656 Michael Hanselmann
  @type force: bool
510 6d4a1656 Michael Hanselmann
  @param force: Whether to ask user for confirmation
511 6d4a1656 Michael Hanselmann
512 6d4a1656 Michael Hanselmann
  """
513 6d4a1656 Michael Hanselmann
  assert new_cluster_cert or new_rapi_cert or rapi_cert_filename or new_hmac_key
514 6d4a1656 Michael Hanselmann
515 6d4a1656 Michael Hanselmann
  if new_rapi_cert and rapi_cert_filename:
516 6d4a1656 Michael Hanselmann
    ToStderr("Only one of the --new-rapi-certficate and --rapi-certificate"
517 6d4a1656 Michael Hanselmann
             " options can be specified at the same time.")
518 6d4a1656 Michael Hanselmann
    return 1
519 6d4a1656 Michael Hanselmann
520 6d4a1656 Michael Hanselmann
  if rapi_cert_filename:
521 6d4a1656 Michael Hanselmann
    # Read and verify new certificate
522 6d4a1656 Michael Hanselmann
    try:
523 6d4a1656 Michael Hanselmann
      rapi_cert_pem = utils.ReadFile(rapi_cert_filename)
524 6d4a1656 Michael Hanselmann
525 6d4a1656 Michael Hanselmann
      OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM,
526 6d4a1656 Michael Hanselmann
                                      rapi_cert_pem)
527 6d4a1656 Michael Hanselmann
    except Exception, err: # pylint: disable-msg=W0703
528 6d4a1656 Michael Hanselmann
      ToStderr("Can't load new RAPI certificate from %s: %s" %
529 6d4a1656 Michael Hanselmann
               (rapi_cert_filename, str(err)))
530 6d4a1656 Michael Hanselmann
      return 1
531 6d4a1656 Michael Hanselmann
532 6d4a1656 Michael Hanselmann
    try:
533 6d4a1656 Michael Hanselmann
      OpenSSL.crypto.load_privatekey(OpenSSL.crypto.FILETYPE_PEM, rapi_cert_pem)
534 6d4a1656 Michael Hanselmann
    except Exception, err: # pylint: disable-msg=W0703
535 6d4a1656 Michael Hanselmann
      ToStderr("Can't load new RAPI private key from %s: %s" %
536 6d4a1656 Michael Hanselmann
               (rapi_cert_filename, str(err)))
537 6d4a1656 Michael Hanselmann
      return 1
538 6d4a1656 Michael Hanselmann
539 6d4a1656 Michael Hanselmann
  else:
540 6d4a1656 Michael Hanselmann
    rapi_cert_pem = None
541 6d4a1656 Michael Hanselmann
542 6d4a1656 Michael Hanselmann
  if not force:
543 6d4a1656 Michael Hanselmann
    usertext = ("This requires all daemons on all nodes to be restarted and"
544 6d4a1656 Michael Hanselmann
                " may take some time. Continue?")
545 6d4a1656 Michael Hanselmann
    if not AskUser(usertext):
546 6d4a1656 Michael Hanselmann
      return 1
547 6d4a1656 Michael Hanselmann
548 6d4a1656 Michael Hanselmann
  def _RenewCryptoInner(ctx):
549 6d4a1656 Michael Hanselmann
    ctx.feedback_fn("Updating certificates and keys")
550 6d4a1656 Michael Hanselmann
    bootstrap.GenerateClusterCrypto(new_cluster_cert, new_rapi_cert,
551 6d4a1656 Michael Hanselmann
                                    new_hmac_key,
552 6d4a1656 Michael Hanselmann
                                    rapi_cert_pem=rapi_cert_pem)
553 6d4a1656 Michael Hanselmann
554 6d4a1656 Michael Hanselmann
    files_to_copy = []
555 6d4a1656 Michael Hanselmann
556 6d4a1656 Michael Hanselmann
    if new_cluster_cert:
557 168c1de2 Michael Hanselmann
      files_to_copy.append(constants.NODED_CERT_FILE)
558 6d4a1656 Michael Hanselmann
559 6d4a1656 Michael Hanselmann
    if new_rapi_cert or rapi_cert_pem:
560 6d4a1656 Michael Hanselmann
      files_to_copy.append(constants.RAPI_CERT_FILE)
561 6d4a1656 Michael Hanselmann
562 6d4a1656 Michael Hanselmann
    if new_hmac_key:
563 6d4a1656 Michael Hanselmann
      files_to_copy.append(constants.HMAC_CLUSTER_KEY)
564 6d4a1656 Michael Hanselmann
565 6d4a1656 Michael Hanselmann
    if files_to_copy:
566 6d4a1656 Michael Hanselmann
      for node_name in ctx.nonmaster_nodes:
567 6d4a1656 Michael Hanselmann
        ctx.feedback_fn("Copying %s to %s" %
568 6d4a1656 Michael Hanselmann
                        (", ".join(files_to_copy), node_name))
569 6d4a1656 Michael Hanselmann
        for file_name in files_to_copy:
570 6d4a1656 Michael Hanselmann
          ctx.ssh.CopyFileToNode(node_name, file_name)
571 6d4a1656 Michael Hanselmann
572 6d4a1656 Michael Hanselmann
  RunWhileClusterStopped(ToStdout, _RenewCryptoInner)
573 6d4a1656 Michael Hanselmann
574 6d4a1656 Michael Hanselmann
  ToStdout("All requested certificates and keys have been replaced."
575 6d4a1656 Michael Hanselmann
           " Running \"gnt-cluster verify\" now is recommended.")
576 6d4a1656 Michael Hanselmann
577 6d4a1656 Michael Hanselmann
  return 0
578 6d4a1656 Michael Hanselmann
579 6d4a1656 Michael Hanselmann
580 6d4a1656 Michael Hanselmann
def RenewCrypto(opts, args):
581 6d4a1656 Michael Hanselmann
  """Renews cluster certificates, keys and secrets.
582 6d4a1656 Michael Hanselmann
583 6d4a1656 Michael Hanselmann
  """
584 6d4a1656 Michael Hanselmann
  return _RenewCrypto(opts.new_cluster_cert,
585 6d4a1656 Michael Hanselmann
                      opts.new_rapi_cert,
586 6d4a1656 Michael Hanselmann
                      opts.rapi_cert,
587 6d4a1656 Michael Hanselmann
                      opts.new_hmac_key,
588 6d4a1656 Michael Hanselmann
                      opts.force)
589 6d4a1656 Michael Hanselmann
590 6d4a1656 Michael Hanselmann
591 90b6aa3a Manuel Franceschini
def SetClusterParams(opts, args):
592 90b6aa3a Manuel Franceschini
  """Modify the cluster.
593 90b6aa3a Manuel Franceschini
594 469ee405 Iustin Pop
  @param opts: the command line options selected by the user
595 469ee405 Iustin Pop
  @type args: list
596 469ee405 Iustin Pop
  @param args: should be an empty list
597 469ee405 Iustin Pop
  @rtype: int
598 469ee405 Iustin Pop
  @return: the desired exit code
599 90b6aa3a Manuel Franceschini
600 90b6aa3a Manuel Franceschini
  """
601 779c15bb Iustin Pop
  if not (not opts.lvm_storage or opts.vg_name or
602 779c15bb Iustin Pop
          opts.enabled_hypervisors or opts.hvparams or
603 5af3da74 Guido Trotter
          opts.beparams or opts.nicparams or
604 5af3da74 Guido Trotter
          opts.candidate_pool_size is not None):
605 3a24c527 Iustin Pop
    ToStderr("Please give at least one of the parameters.")
606 90b6aa3a Manuel Franceschini
    return 1
607 90b6aa3a Manuel Franceschini
608 90b6aa3a Manuel Franceschini
  vg_name = opts.vg_name
609 90b6aa3a Manuel Franceschini
  if not opts.lvm_storage and opts.vg_name:
610 6d4a1656 Michael Hanselmann
    ToStderr("Options --no-lvm-storage and --vg-name conflict.")
611 90b6aa3a Manuel Franceschini
    return 1
612 6d4a1656 Michael Hanselmann
613 6d4a1656 Michael Hanselmann
  if not opts.lvm_storage:
614 6d4a1656 Michael Hanselmann
    vg_name = ""
615 90b6aa3a Manuel Franceschini
616 779c15bb Iustin Pop
  hvlist = opts.enabled_hypervisors
617 779c15bb Iustin Pop
  if hvlist is not None:
618 779c15bb Iustin Pop
    hvlist = hvlist.split(",")
619 779c15bb Iustin Pop
620 f8e7ddca Guido Trotter
  # a list of (name, dict) we can pass directly to dict() (or [])
621 f8e7ddca Guido Trotter
  hvparams = dict(opts.hvparams)
622 f4ad2ef0 Iustin Pop
  for hv_params in hvparams.values():
623 a5728081 Guido Trotter
    utils.ForceDictType(hv_params, constants.HVS_PARAMETER_TYPES)
624 779c15bb Iustin Pop
625 779c15bb Iustin Pop
  beparams = opts.beparams
626 a5728081 Guido Trotter
  utils.ForceDictType(beparams, constants.BES_PARAMETER_TYPES)
627 779c15bb Iustin Pop
628 5af3da74 Guido Trotter
  nicparams = opts.nicparams
629 5af3da74 Guido Trotter
  utils.ForceDictType(nicparams, constants.NICS_PARAMETER_TYPES)
630 5af3da74 Guido Trotter
631 b8a8fbe1 Guido Trotter
  op = opcodes.OpSetClusterParams(vg_name=vg_name,
632 779c15bb Iustin Pop
                                  enabled_hypervisors=hvlist,
633 779c15bb Iustin Pop
                                  hvparams=hvparams,
634 17463d22 Renรฉ Nussbaumer
                                  os_hvp=None,
635 4b7735f9 Iustin Pop
                                  beparams=beparams,
636 5af3da74 Guido Trotter
                                  nicparams=nicparams,
637 4b7735f9 Iustin Pop
                                  candidate_pool_size=opts.candidate_pool_size)
638 400ca2f7 Iustin Pop
  SubmitOpCode(op, opts=opts)
639 90b6aa3a Manuel Franceschini
  return 0
640 90b6aa3a Manuel Franceschini
641 90b6aa3a Manuel Franceschini
642 3ccafd0e Iustin Pop
def QueueOps(opts, args):
643 3ccafd0e Iustin Pop
  """Queue operations.
644 3ccafd0e Iustin Pop
645 469ee405 Iustin Pop
  @param opts: the command line options selected by the user
646 469ee405 Iustin Pop
  @type args: list
647 469ee405 Iustin Pop
  @param args: should contain only one element, the subcommand
648 469ee405 Iustin Pop
  @rtype: int
649 469ee405 Iustin Pop
  @return: the desired exit code
650 469ee405 Iustin Pop
651 3ccafd0e Iustin Pop
  """
652 3ccafd0e Iustin Pop
  command = args[0]
653 3ccafd0e Iustin Pop
  client = GetClient()
654 3ccafd0e Iustin Pop
  if command in ("drain", "undrain"):
655 3ccafd0e Iustin Pop
    drain_flag = command == "drain"
656 3ccafd0e Iustin Pop
    client.SetQueueDrainFlag(drain_flag)
657 3ccafd0e Iustin Pop
  elif command == "info":
658 3ccafd0e Iustin Pop
    result = client.QueryConfigValues(["drain_flag"])
659 3ccafd0e Iustin Pop
    if result[0]:
660 3a24c527 Iustin Pop
      val = "set"
661 3ccafd0e Iustin Pop
    else:
662 3a24c527 Iustin Pop
      val = "unset"
663 3a24c527 Iustin Pop
    ToStdout("The drain flag is %s" % val)
664 2e668b38 Guido Trotter
  else:
665 debac808 Iustin Pop
    raise errors.OpPrereqError("Command '%s' is not valid." % command,
666 debac808 Iustin Pop
                               errors.ECODE_INVAL)
667 2e668b38 Guido Trotter
668 3ccafd0e Iustin Pop
  return 0
669 3ccafd0e Iustin Pop
670 95b2e626 Michael Hanselmann
671 28b498cd Michael Hanselmann
def _ShowWatcherPause(until):
672 28b498cd Michael Hanselmann
  if until is None or until < time.time():
673 28b498cd Michael Hanselmann
    ToStdout("The watcher is not paused.")
674 28b498cd Michael Hanselmann
  else:
675 28b498cd Michael Hanselmann
    ToStdout("The watcher is paused until %s.", time.ctime(until))
676 28b498cd Michael Hanselmann
677 28b498cd Michael Hanselmann
678 95b2e626 Michael Hanselmann
def WatcherOps(opts, args):
679 95b2e626 Michael Hanselmann
  """Watcher operations.
680 95b2e626 Michael Hanselmann
681 95b2e626 Michael Hanselmann
  @param opts: the command line options selected by the user
682 95b2e626 Michael Hanselmann
  @type args: list
683 95b2e626 Michael Hanselmann
  @param args: should contain only one element, the subcommand
684 95b2e626 Michael Hanselmann
  @rtype: int
685 95b2e626 Michael Hanselmann
  @return: the desired exit code
686 95b2e626 Michael Hanselmann
687 95b2e626 Michael Hanselmann
  """
688 95b2e626 Michael Hanselmann
  command = args[0]
689 95b2e626 Michael Hanselmann
  client = GetClient()
690 95b2e626 Michael Hanselmann
691 95b2e626 Michael Hanselmann
  if command == "continue":
692 95b2e626 Michael Hanselmann
    client.SetWatcherPause(None)
693 28b498cd Michael Hanselmann
    ToStdout("The watcher is no longer paused.")
694 95b2e626 Michael Hanselmann
695 95b2e626 Michael Hanselmann
  elif command == "pause":
696 95b2e626 Michael Hanselmann
    if len(args) < 2:
697 debac808 Iustin Pop
      raise errors.OpPrereqError("Missing pause duration", errors.ECODE_INVAL)
698 95b2e626 Michael Hanselmann
699 28b498cd Michael Hanselmann
    result = client.SetWatcherPause(time.time() + ParseTimespec(args[1]))
700 28b498cd Michael Hanselmann
    _ShowWatcherPause(result)
701 95b2e626 Michael Hanselmann
702 95b2e626 Michael Hanselmann
  elif command == "info":
703 95b2e626 Michael Hanselmann
    result = client.QueryConfigValues(["watcher_pause"])
704 cac599f1 Michael Hanselmann
    _ShowWatcherPause(result[0])
705 95b2e626 Michael Hanselmann
706 95b2e626 Michael Hanselmann
  else:
707 debac808 Iustin Pop
    raise errors.OpPrereqError("Command '%s' is not valid." % command,
708 debac808 Iustin Pop
                               errors.ECODE_INVAL)
709 95b2e626 Michael Hanselmann
710 95b2e626 Michael Hanselmann
  return 0
711 95b2e626 Michael Hanselmann
712 95b2e626 Michael Hanselmann
713 a8083063 Iustin Pop
commands = {
714 6ea815cf Iustin Pop
  'init': (
715 6ea815cf Iustin Pop
    InitCluster, [ArgHost(min=1, max=1)],
716 064c21f8 Iustin Pop
    [BACKEND_OPT, CP_SIZE_OPT, ENABLED_HV_OPT, GLOBAL_FILEDIR_OPT,
717 6ea815cf Iustin Pop
     HVLIST_OPT, MAC_PREFIX_OPT, MASTER_NETDEV_OPT, NIC_PARAMS_OPT,
718 b989b9d9 Ken Wehr
     NOLVM_STORAGE_OPT, NOMODIFY_ETCHOSTS_OPT, NOMODIFY_SSH_SETUP_OPT,
719 b989b9d9 Ken Wehr
     SECONDARY_IP_OPT, VG_NAME_OPT],
720 6ea815cf Iustin Pop
    "[opts...] <cluster_name>", "Initialises a new cluster configuration"),
721 6ea815cf Iustin Pop
  'destroy': (
722 064c21f8 Iustin Pop
    DestroyCluster, ARGS_NONE, [YES_DOIT_OPT],
723 6ea815cf Iustin Pop
    "", "Destroy cluster"),
724 6ea815cf Iustin Pop
  'rename': (
725 6ea815cf Iustin Pop
    RenameCluster, [ArgHost(min=1, max=1)],
726 064c21f8 Iustin Pop
    [FORCE_OPT],
727 6ea815cf Iustin Pop
    "<new_name>",
728 6ea815cf Iustin Pop
    "Renames the cluster"),
729 6ea815cf Iustin Pop
  'redist-conf': (
730 064c21f8 Iustin Pop
    RedistributeConfig, ARGS_NONE, [SUBMIT_OPT],
731 6ea815cf Iustin Pop
    "", "Forces a push of the configuration file and ssconf files"
732 6ea815cf Iustin Pop
    " to the nodes in the cluster"),
733 6ea815cf Iustin Pop
  'verify': (
734 6ea815cf Iustin Pop
    VerifyCluster, ARGS_NONE,
735 064c21f8 Iustin Pop
    [VERBOSE_OPT, DEBUG_SIMERR_OPT, ERROR_CODES_OPT, NONPLUS1_OPT],
736 6ea815cf Iustin Pop
    "", "Does a check on the cluster configuration"),
737 6ea815cf Iustin Pop
  'verify-disks': (
738 064c21f8 Iustin Pop
    VerifyDisks, ARGS_NONE, [],
739 6ea815cf Iustin Pop
    "", "Does a check on the cluster disk status"),
740 6ea815cf Iustin Pop
  'repair-disk-sizes': (
741 064c21f8 Iustin Pop
    RepairDiskSizes, ARGS_MANY_INSTANCES, [],
742 6ea815cf Iustin Pop
    "", "Updates mismatches in recorded disk sizes"),
743 6ea815cf Iustin Pop
  'masterfailover': (
744 064c21f8 Iustin Pop
    MasterFailover, ARGS_NONE, [NOVOTING_OPT],
745 6ea815cf Iustin Pop
    "", "Makes the current node the master"),
746 6ea815cf Iustin Pop
  'version': (
747 064c21f8 Iustin Pop
    ShowClusterVersion, ARGS_NONE, [],
748 6ea815cf Iustin Pop
    "", "Shows the cluster version"),
749 6ea815cf Iustin Pop
  'getmaster': (
750 064c21f8 Iustin Pop
    ShowClusterMaster, ARGS_NONE, [],
751 6ea815cf Iustin Pop
    "", "Shows the cluster master"),
752 6ea815cf Iustin Pop
  'copyfile': (
753 6ea815cf Iustin Pop
    ClusterCopyFile, [ArgFile(min=1, max=1)],
754 064c21f8 Iustin Pop
    [NODE_LIST_OPT],
755 6ea815cf Iustin Pop
    "[-n node...] <filename>", "Copies a file to all (or only some) nodes"),
756 6ea815cf Iustin Pop
  'command': (
757 6ea815cf Iustin Pop
    RunClusterCommand, [ArgCommand(min=1)],
758 064c21f8 Iustin Pop
    [NODE_LIST_OPT],
759 6ea815cf Iustin Pop
    "[-n node...] <command>", "Runs a command on all (or only some) nodes"),
760 6ea815cf Iustin Pop
  'info': (
761 064c21f8 Iustin Pop
    ShowClusterConfig, ARGS_NONE, [],
762 6ea815cf Iustin Pop
    "", "Show cluster configuration"),
763 6ea815cf Iustin Pop
  'list-tags': (
764 064c21f8 Iustin Pop
    ListTags, ARGS_NONE, [], "", "List the tags of the cluster"),
765 6ea815cf Iustin Pop
  'add-tags': (
766 064c21f8 Iustin Pop
    AddTags, [ArgUnknown()], [TAG_SRC_OPT],
767 6ea815cf Iustin Pop
    "tag...", "Add tags to the cluster"),
768 6ea815cf Iustin Pop
  'remove-tags': (
769 064c21f8 Iustin Pop
    RemoveTags, [ArgUnknown()], [TAG_SRC_OPT],
770 6ea815cf Iustin Pop
    "tag...", "Remove tags from the cluster"),
771 6ea815cf Iustin Pop
  'search-tags': (
772 6ea815cf Iustin Pop
    SearchTags, [ArgUnknown(min=1, max=1)],
773 064c21f8 Iustin Pop
    [], "", "Searches the tags on all objects on"
774 6ea815cf Iustin Pop
    " the cluster for a given pattern (regex)"),
775 6ea815cf Iustin Pop
  'queue': (
776 6ea815cf Iustin Pop
    QueueOps,
777 6ea815cf Iustin Pop
    [ArgChoice(min=1, max=1, choices=["drain", "undrain", "info"])],
778 064c21f8 Iustin Pop
    [], "drain|undrain|info", "Change queue properties"),
779 6ea815cf Iustin Pop
  'watcher': (
780 6ea815cf Iustin Pop
    WatcherOps,
781 6ea815cf Iustin Pop
    [ArgChoice(min=1, max=1, choices=["pause", "continue", "info"]),
782 6ea815cf Iustin Pop
     ArgSuggest(min=0, max=1, choices=["30m", "1h", "4h"])],
783 064c21f8 Iustin Pop
    [],
784 6ea815cf Iustin Pop
    "{pause <timespec>|continue|info}", "Change watcher properties"),
785 6ea815cf Iustin Pop
  'modify': (
786 6ea815cf Iustin Pop
    SetClusterParams, ARGS_NONE,
787 064c21f8 Iustin Pop
    [BACKEND_OPT, CP_SIZE_OPT, ENABLED_HV_OPT, HVLIST_OPT,
788 6ea815cf Iustin Pop
     NIC_PARAMS_OPT, NOLVM_STORAGE_OPT, VG_NAME_OPT],
789 6ea815cf Iustin Pop
    "[opts...]",
790 6ea815cf Iustin Pop
    "Alters the parameters of the cluster"),
791 6d4a1656 Michael Hanselmann
  "renew-crypto": (
792 6d4a1656 Michael Hanselmann
    RenewCrypto, ARGS_NONE,
793 6d4a1656 Michael Hanselmann
    [NEW_CLUSTER_CERT_OPT, NEW_RAPI_CERT_OPT, RAPI_CERT_OPT, NEW_HMAC_KEY_OPT,
794 6d4a1656 Michael Hanselmann
     FORCE_OPT],
795 6d4a1656 Michael Hanselmann
    "[opts...]",
796 6d4a1656 Michael Hanselmann
    "Renews cluster certificates, keys and secrets"),
797 a8083063 Iustin Pop
  }
798 a8083063 Iustin Pop
799 6d4a1656 Michael Hanselmann
800 a8083063 Iustin Pop
if __name__ == '__main__':
801 846baef9 Iustin Pop
  sys.exit(GenericMain(commands, override={"tag_type": constants.TAG_CLUSTER}))