Statistics
| Branch: | Tag: | Revision:

root / scripts / gnt-cluster @ fdad8c4d

History | View | Annotate | Download (24.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 1338f2b4 Balazs Lecz
from ganeti import uidpool
43 a8083063 Iustin Pop
44 a8083063 Iustin Pop
45 4331f6cd Michael Hanselmann
@UsesRPC
46 a8083063 Iustin Pop
def InitCluster(opts, args):
47 a8083063 Iustin Pop
  """Initialize the cluster.
48 a8083063 Iustin Pop
49 469ee405 Iustin Pop
  @param opts: the command line options selected by the user
50 469ee405 Iustin Pop
  @type args: list
51 469ee405 Iustin Pop
  @param args: should contain only one element, the desired
52 469ee405 Iustin Pop
      cluster name
53 469ee405 Iustin Pop
  @rtype: int
54 469ee405 Iustin Pop
  @return: the desired exit code
55 a8083063 Iustin Pop
56 a8083063 Iustin Pop
  """
57 90b6aa3a Manuel Franceschini
  if not opts.lvm_storage and opts.vg_name:
58 3a24c527 Iustin Pop
    ToStderr("Options --no-lvm-storage and --vg-name conflict.")
59 90b6aa3a Manuel Franceschini
    return 1
60 90b6aa3a Manuel Franceschini
61 90b6aa3a Manuel Franceschini
  vg_name = opts.vg_name
62 90b6aa3a Manuel Franceschini
  if opts.lvm_storage and not opts.vg_name:
63 90b6aa3a Manuel Franceschini
    vg_name = constants.DEFAULT_VG
64 90b6aa3a Manuel Franceschini
65 ea3a925f Alexander Schreiber
  hvlist = opts.enabled_hypervisors
66 383a3591 Iustin Pop
  if hvlist is None:
67 383a3591 Iustin Pop
    hvlist = constants.DEFAULT_ENABLED_HYPERVISOR
68 066f465d Guido Trotter
  hvlist = hvlist.split(",")
69 ea3a925f Alexander Schreiber
70 f8e7ddca Guido Trotter
  hvparams = dict(opts.hvparams)
71 ea3a925f Alexander Schreiber
  beparams = opts.beparams
72 b6a30b0d Guido Trotter
  nicparams = opts.nicparams
73 ea3a925f Alexander Schreiber
74 ea3a925f Alexander Schreiber
  # prepare beparams dict
75 d3cfe525 Guido Trotter
  beparams = objects.FillDict(constants.BEC_DEFAULTS, beparams)
76 a5728081 Guido Trotter
  utils.ForceDictType(beparams, constants.BES_PARAMETER_TYPES)
77 ea3a925f Alexander Schreiber
78 b6a30b0d Guido Trotter
  # prepare nicparams dict
79 b6a30b0d Guido Trotter
  nicparams = objects.FillDict(constants.NICC_DEFAULTS, nicparams)
80 b6a30b0d Guido Trotter
  utils.ForceDictType(nicparams, constants.NICS_PARAMETER_TYPES)
81 b6a30b0d Guido Trotter
82 ea3a925f Alexander Schreiber
  # prepare hvparams dict
83 ea3a925f Alexander Schreiber
  for hv in constants.HYPER_TYPES:
84 ea3a925f Alexander Schreiber
    if hv not in hvparams:
85 ea3a925f Alexander Schreiber
      hvparams[hv] = {}
86 d3cfe525 Guido Trotter
    hvparams[hv] = objects.FillDict(constants.HVC_DEFAULTS[hv], hvparams[hv])
87 a5728081 Guido Trotter
    utils.ForceDictType(hvparams[hv], constants.HVS_PARAMETER_TYPES)
88 ea3a925f Alexander Schreiber
89 e32df528 Iustin Pop
  if opts.candidate_pool_size is None:
90 e32df528 Iustin Pop
    opts.candidate_pool_size = constants.MASTER_POOL_SIZE_DEFAULT
91 e32df528 Iustin Pop
92 e3646f22 Iustin Pop
  if opts.mac_prefix is None:
93 e3646f22 Iustin Pop
    opts.mac_prefix = constants.DEFAULT_MAC_PREFIX
94 e3646f22 Iustin Pop
95 a0c9f010 Michael Hanselmann
  bootstrap.InitCluster(cluster_name=args[0],
96 a0c9f010 Michael Hanselmann
                        secondary_ip=opts.secondary_ip,
97 a0c9f010 Michael Hanselmann
                        vg_name=vg_name,
98 a0c9f010 Michael Hanselmann
                        mac_prefix=opts.mac_prefix,
99 a0c9f010 Michael Hanselmann
                        master_netdev=opts.master_netdev,
100 ea3a925f Alexander Schreiber
                        file_storage_dir=opts.file_storage_dir,
101 ea3a925f Alexander Schreiber
                        enabled_hypervisors=hvlist,
102 ea3a925f Alexander Schreiber
                        hvparams=hvparams,
103 ce735215 Guido Trotter
                        beparams=beparams,
104 b6a30b0d Guido Trotter
                        nicparams=nicparams,
105 ce735215 Guido Trotter
                        candidate_pool_size=opts.candidate_pool_size,
106 b86a6bcd Guido Trotter
                        modify_etc_hosts=opts.modify_etc_hosts,
107 b989b9d9 Ken Wehr
                        modify_ssh_setup=opts.modify_ssh_setup,
108 3953242f Iustin Pop
                        maintain_node_health=opts.maintain_node_health,
109 ce735215 Guido Trotter
                        )
110 3552cd2e Luca Bigliardi
  op = opcodes.OpPostInitCluster()
111 400ca2f7 Iustin Pop
  SubmitOpCode(op, opts=opts)
112 a8083063 Iustin Pop
  return 0
113 a8083063 Iustin Pop
114 a8083063 Iustin Pop
115 4331f6cd Michael Hanselmann
@UsesRPC
116 a8083063 Iustin Pop
def DestroyCluster(opts, args):
117 a8083063 Iustin Pop
  """Destroy the cluster.
118 a8083063 Iustin Pop
119 469ee405 Iustin Pop
  @param opts: the command line options selected by the user
120 469ee405 Iustin Pop
  @type args: list
121 469ee405 Iustin Pop
  @param args: should be an empty list
122 469ee405 Iustin Pop
  @rtype: int
123 469ee405 Iustin Pop
  @return: the desired exit code
124 098c0958 Michael Hanselmann
125 a8083063 Iustin Pop
  """
126 a8083063 Iustin Pop
  if not opts.yes_do_it:
127 3a24c527 Iustin Pop
    ToStderr("Destroying a cluster is irreversible. If you really want"
128 3a24c527 Iustin Pop
             " destroy this cluster, supply the --yes-do-it option.")
129 a8083063 Iustin Pop
    return 1
130 a8083063 Iustin Pop
131 a8083063 Iustin Pop
  op = opcodes.OpDestroyCluster()
132 400ca2f7 Iustin Pop
  master = SubmitOpCode(op, opts=opts)
133 140aa4a8 Iustin Pop
  # if we reached this, the opcode didn't fail; we can proceed to
134 140aa4a8 Iustin Pop
  # shutdown all the daemons
135 140aa4a8 Iustin Pop
  bootstrap.FinalizeClusterDestroy(master)
136 a8083063 Iustin Pop
  return 0
137 a8083063 Iustin Pop
138 a8083063 Iustin Pop
139 07bd8a51 Iustin Pop
def RenameCluster(opts, args):
140 07bd8a51 Iustin Pop
  """Rename the cluster.
141 07bd8a51 Iustin Pop
142 469ee405 Iustin Pop
  @param opts: the command line options selected by the user
143 469ee405 Iustin Pop
  @type args: list
144 469ee405 Iustin Pop
  @param args: should contain only one element, the new cluster name
145 469ee405 Iustin Pop
  @rtype: int
146 469ee405 Iustin Pop
  @return: the desired exit code
147 07bd8a51 Iustin Pop
148 07bd8a51 Iustin Pop
  """
149 07bd8a51 Iustin Pop
  name = args[0]
150 07bd8a51 Iustin Pop
  if not opts.force:
151 07bd8a51 Iustin Pop
    usertext = ("This will rename the cluster to '%s'. If you are connected"
152 07bd8a51 Iustin Pop
                " over the network to the cluster name, the operation is very"
153 07bd8a51 Iustin Pop
                " dangerous as the IP address will be removed from the node"
154 07bd8a51 Iustin Pop
                " and the change may not go through. Continue?") % name
155 47988778 Iustin Pop
    if not AskUser(usertext):
156 07bd8a51 Iustin Pop
      return 1
157 07bd8a51 Iustin Pop
158 07bd8a51 Iustin Pop
  op = opcodes.OpRenameCluster(name=name)
159 400ca2f7 Iustin Pop
  SubmitOpCode(op, opts=opts)
160 07bd8a51 Iustin Pop
  return 0
161 07bd8a51 Iustin Pop
162 07bd8a51 Iustin Pop
163 afee0879 Iustin Pop
def RedistributeConfig(opts, args):
164 afee0879 Iustin Pop
  """Forces push of the cluster configuration.
165 afee0879 Iustin Pop
166 afee0879 Iustin Pop
  @param opts: the command line options selected by the user
167 afee0879 Iustin Pop
  @type args: list
168 afee0879 Iustin Pop
  @param args: empty list
169 afee0879 Iustin Pop
  @rtype: int
170 afee0879 Iustin Pop
  @return: the desired exit code
171 afee0879 Iustin Pop
172 afee0879 Iustin Pop
  """
173 81a49123 Iustin Pop
  op = opcodes.OpRedistributeConfig()
174 afee0879 Iustin Pop
  SubmitOrSend(op, opts)
175 afee0879 Iustin Pop
  return 0
176 afee0879 Iustin Pop
177 afee0879 Iustin Pop
178 a8083063 Iustin Pop
def ShowClusterVersion(opts, args):
179 a8083063 Iustin Pop
  """Write version of ganeti software to the standard output.
180 a8083063 Iustin Pop
181 469ee405 Iustin Pop
  @param opts: the command line options selected by the user
182 469ee405 Iustin Pop
  @type args: list
183 469ee405 Iustin Pop
  @param args: should be an empty list
184 469ee405 Iustin Pop
  @rtype: int
185 469ee405 Iustin Pop
  @return: the desired exit code
186 a8083063 Iustin Pop
187 a8083063 Iustin Pop
  """
188 2e7b8369 Iustin Pop
  cl = GetClient()
189 2e7b8369 Iustin Pop
  result = cl.QueryClusterInfo()
190 3a24c527 Iustin Pop
  ToStdout("Software version: %s", result["software_version"])
191 3a24c527 Iustin Pop
  ToStdout("Internode protocol: %s", result["protocol_version"])
192 3a24c527 Iustin Pop
  ToStdout("Configuration format: %s", result["config_version"])
193 3a24c527 Iustin Pop
  ToStdout("OS api version: %s", result["os_api_version"])
194 3a24c527 Iustin Pop
  ToStdout("Export interface: %s", result["export_version"])
195 a8083063 Iustin Pop
  return 0
196 a8083063 Iustin Pop
197 a8083063 Iustin Pop
198 a8083063 Iustin Pop
def ShowClusterMaster(opts, args):
199 a8083063 Iustin Pop
  """Write name of master node to the standard output.
200 a8083063 Iustin Pop
201 469ee405 Iustin Pop
  @param opts: the command line options selected by the user
202 469ee405 Iustin Pop
  @type args: list
203 469ee405 Iustin Pop
  @param args: should be an empty list
204 469ee405 Iustin Pop
  @rtype: int
205 469ee405 Iustin Pop
  @return: the desired exit code
206 a8083063 Iustin Pop
207 a8083063 Iustin Pop
  """
208 8eb148ae Iustin Pop
  master = bootstrap.GetMaster()
209 8eb148ae Iustin Pop
  ToStdout(master)
210 a8083063 Iustin Pop
  return 0
211 a8083063 Iustin Pop
212 cac599f1 Michael Hanselmann
213 664a9d73 Renรฉ Nussbaumer
def _PrintGroupedParams(paramsdict, level=1):
214 1094acda Guido Trotter
  """Print Grouped parameters (be, nic, disk) by group.
215 1094acda Guido Trotter
216 1094acda Guido Trotter
  @type paramsdict: dict of dicts
217 1094acda Guido Trotter
  @param paramsdict: {group: {param: value, ...}, ...}
218 664a9d73 Renรฉ Nussbaumer
  @type level: int
219 664a9d73 Renรฉ Nussbaumer
  @param level: Level of indention
220 1094acda Guido Trotter
221 1094acda Guido Trotter
  """
222 664a9d73 Renรฉ Nussbaumer
  indent = "  " * level
223 664a9d73 Renรฉ Nussbaumer
  for item, val in paramsdict.items():
224 664a9d73 Renรฉ Nussbaumer
    if isinstance(val, dict):
225 664a9d73 Renรฉ Nussbaumer
      ToStdout("%s- %s:", indent, item)
226 664a9d73 Renรฉ Nussbaumer
      _PrintGroupedParams(val, level=level + 1)
227 664a9d73 Renรฉ Nussbaumer
    else:
228 664a9d73 Renรฉ Nussbaumer
      ToStdout("%s  %s: %s", indent, item, val)
229 a8083063 Iustin Pop
230 cac599f1 Michael Hanselmann
231 a8083063 Iustin Pop
def ShowClusterConfig(opts, args):
232 a8083063 Iustin Pop
  """Shows cluster information.
233 a8083063 Iustin Pop
234 469ee405 Iustin Pop
  @param opts: the command line options selected by the user
235 469ee405 Iustin Pop
  @type args: list
236 469ee405 Iustin Pop
  @param args: should be an empty list
237 469ee405 Iustin Pop
  @rtype: int
238 469ee405 Iustin Pop
  @return: the desired exit code
239 469ee405 Iustin Pop
240 a8083063 Iustin Pop
  """
241 2e7b8369 Iustin Pop
  cl = GetClient()
242 2e7b8369 Iustin Pop
  result = cl.QueryClusterInfo()
243 a8083063 Iustin Pop
244 3a24c527 Iustin Pop
  ToStdout("Cluster name: %s", result["name"])
245 259578eb Iustin Pop
  ToStdout("Cluster UUID: %s", result["uuid"])
246 a8083063 Iustin Pop
247 90f72445 Iustin Pop
  ToStdout("Creation time: %s", utils.FormatTime(result["ctime"]))
248 90f72445 Iustin Pop
  ToStdout("Modification time: %s", utils.FormatTime(result["mtime"]))
249 90f72445 Iustin Pop
250 3a24c527 Iustin Pop
  ToStdout("Master node: %s", result["master"])
251 a8083063 Iustin Pop
252 3a24c527 Iustin Pop
  ToStdout("Architecture (this node): %s (%s)",
253 3a24c527 Iustin Pop
           result["architecture"][0], result["architecture"][1])
254 a8083063 Iustin Pop
255 c118d1f4 Michael Hanselmann
  if result["tags"]:
256 1f864b60 Iustin Pop
    tags = utils.CommaJoin(utils.NiceSort(result["tags"]))
257 c118d1f4 Michael Hanselmann
  else:
258 c118d1f4 Michael Hanselmann
    tags = "(none)"
259 c118d1f4 Michael Hanselmann
260 c118d1f4 Michael Hanselmann
  ToStdout("Tags: %s", tags)
261 c118d1f4 Michael Hanselmann
262 02691904 Alexander Schreiber
  ToStdout("Default hypervisor: %s", result["default_hypervisor"])
263 1f864b60 Iustin Pop
  ToStdout("Enabled hypervisors: %s",
264 1f864b60 Iustin Pop
           utils.CommaJoin(result["enabled_hypervisors"]))
265 469f88e1 Iustin Pop
266 3a24c527 Iustin Pop
  ToStdout("Hypervisor parameters:")
267 1094acda Guido Trotter
  _PrintGroupedParams(result["hvparams"])
268 469f88e1 Iustin Pop
269 664a9d73 Renรฉ Nussbaumer
  ToStdout("OS specific hypervisor parameters:")
270 664a9d73 Renรฉ Nussbaumer
  _PrintGroupedParams(result["os_hvp"])
271 664a9d73 Renรฉ Nussbaumer
272 3a24c527 Iustin Pop
  ToStdout("Cluster parameters:")
273 4b7735f9 Iustin Pop
  ToStdout("  - candidate pool size: %s", result["candidate_pool_size"])
274 a8001106 Guido Trotter
  ToStdout("  - master netdev: %s", result["master_netdev"])
275 a8001106 Guido Trotter
  ToStdout("  - lvm volume group: %s", result["volume_group_name"])
276 a8001106 Guido Trotter
  ToStdout("  - file storage path: %s", result["file_storage_dir"])
277 3953242f Iustin Pop
  ToStdout("  - maintenance of node health: %s",
278 3953242f Iustin Pop
           result["maintain_node_health"])
279 4b7735f9 Iustin Pop
280 4b7735f9 Iustin Pop
  ToStdout("Default instance parameters:")
281 1094acda Guido Trotter
  _PrintGroupedParams(result["beparams"])
282 1094acda Guido Trotter
283 1094acda Guido Trotter
  ToStdout("Default nic parameters:")
284 1094acda Guido Trotter
  _PrintGroupedParams(result["nicparams"])
285 8a12ce45 Iustin Pop
286 a8083063 Iustin Pop
  return 0
287 a8083063 Iustin Pop
288 a8083063 Iustin Pop
289 a8083063 Iustin Pop
def ClusterCopyFile(opts, args):
290 a8083063 Iustin Pop
  """Copy a file from master to some nodes.
291 a8083063 Iustin Pop
292 469ee405 Iustin Pop
  @param opts: the command line options selected by the user
293 469ee405 Iustin Pop
  @type args: list
294 469ee405 Iustin Pop
  @param args: should contain only one element, the path of
295 469ee405 Iustin Pop
      the file to be copied
296 469ee405 Iustin Pop
  @rtype: int
297 469ee405 Iustin Pop
  @return: the desired exit code
298 a8083063 Iustin Pop
299 a8083063 Iustin Pop
  """
300 b3989551 Iustin Pop
  filename = args[0]
301 b3989551 Iustin Pop
  if not os.path.exists(filename):
302 debac808 Iustin Pop
    raise errors.OpPrereqError("No such filename '%s'" % filename,
303 debac808 Iustin Pop
                               errors.ECODE_INVAL)
304 b3989551 Iustin Pop
305 56bece1f Iustin Pop
  cl = GetClient()
306 56bece1f Iustin Pop
307 56bece1f Iustin Pop
  cluster_name = cl.QueryConfigValues(["cluster_name"])[0]
308 56bece1f Iustin Pop
309 74adc100 Iustin Pop
  results = GetOnlineNodes(nodes=opts.nodes, cl=cl, filter_master=True,
310 74adc100 Iustin Pop
                           secondary_ips=opts.use_replication_network)
311 e00ea635 Michael Hanselmann
312 56bece1f Iustin Pop
  srun = ssh.SshRunner(cluster_name=cluster_name)
313 b3989551 Iustin Pop
  for node in results:
314 b3989551 Iustin Pop
    if not srun.CopyFileToNode(node, filename):
315 3a24c527 Iustin Pop
      ToStderr("Copy of file %s to node %s failed", filename, node)
316 b3989551 Iustin Pop
317 a8083063 Iustin Pop
  return 0
318 a8083063 Iustin Pop
319 a8083063 Iustin Pop
320 a8083063 Iustin Pop
def RunClusterCommand(opts, args):
321 a8083063 Iustin Pop
  """Run a command on some nodes.
322 a8083063 Iustin Pop
323 469ee405 Iustin Pop
  @param opts: the command line options selected by the user
324 469ee405 Iustin Pop
  @type args: list
325 469ee405 Iustin Pop
  @param args: should contain the command to be run and its arguments
326 469ee405 Iustin Pop
  @rtype: int
327 469ee405 Iustin Pop
  @return: the desired exit code
328 a8083063 Iustin Pop
329 a8083063 Iustin Pop
  """
330 56bece1f Iustin Pop
  cl = GetClient()
331 7688d0d3 Michael Hanselmann
332 a8083063 Iustin Pop
  command = " ".join(args)
333 4040a784 Iustin Pop
334 4040a784 Iustin Pop
  nodes = GetOnlineNodes(nodes=opts.nodes, cl=cl)
335 56bece1f Iustin Pop
336 56bece1f Iustin Pop
  cluster_name, master_node = cl.QueryConfigValues(["cluster_name",
337 56bece1f Iustin Pop
                                                    "master_node"])
338 b3989551 Iustin Pop
339 56bece1f Iustin Pop
  srun = ssh.SshRunner(cluster_name=cluster_name)
340 b3989551 Iustin Pop
341 7688d0d3 Michael Hanselmann
  # Make sure master node is at list end
342 b3989551 Iustin Pop
  if master_node in nodes:
343 b3989551 Iustin Pop
    nodes.remove(master_node)
344 b3989551 Iustin Pop
    nodes.append(master_node)
345 b3989551 Iustin Pop
346 b3989551 Iustin Pop
  for name in nodes:
347 b3989551 Iustin Pop
    result = srun.Run(name, "root", command)
348 3a24c527 Iustin Pop
    ToStdout("------------------------------------------------")
349 3a24c527 Iustin Pop
    ToStdout("node: %s", name)
350 3a24c527 Iustin Pop
    ToStdout("%s", result.output)
351 3a24c527 Iustin Pop
    ToStdout("return code = %s", result.exit_code)
352 b3989551 Iustin Pop
353 b3989551 Iustin Pop
  return 0
354 a8083063 Iustin Pop
355 a8083063 Iustin Pop
356 a8083063 Iustin Pop
def VerifyCluster(opts, args):
357 a8083063 Iustin Pop
  """Verify integrity of cluster, performing various test on nodes.
358 a8083063 Iustin Pop
359 469ee405 Iustin Pop
  @param opts: the command line options selected by the user
360 469ee405 Iustin Pop
  @type args: list
361 469ee405 Iustin Pop
  @param args: should be an empty list
362 469ee405 Iustin Pop
  @rtype: int
363 469ee405 Iustin Pop
  @return: the desired exit code
364 a8083063 Iustin Pop
365 a8083063 Iustin Pop
  """
366 8d59409f Iustin Pop
  skip_checks = []
367 e54c4c5e Guido Trotter
  if opts.skip_nplusone_mem:
368 e54c4c5e Guido Trotter
    skip_checks.append(constants.VERIFY_NPLUSONE_MEM)
369 7c874ee1 Iustin Pop
  op = opcodes.OpVerifyCluster(skip_checks=skip_checks,
370 7c874ee1 Iustin Pop
                               verbose=opts.verbose,
371 a0c9776a Iustin Pop
                               error_codes=opts.error_codes,
372 a0c9776a Iustin Pop
                               debug_simulate_errors=opts.simulate_errors)
373 400ca2f7 Iustin Pop
  if SubmitOpCode(op, opts=opts):
374 34290825 Michael Hanselmann
    return 0
375 34290825 Michael Hanselmann
  else:
376 34290825 Michael Hanselmann
    return 1
377 a8083063 Iustin Pop
378 a8083063 Iustin Pop
379 f4d4e184 Iustin Pop
def VerifyDisks(opts, args):
380 f4d4e184 Iustin Pop
  """Verify integrity of cluster disks.
381 f4d4e184 Iustin Pop
382 469ee405 Iustin Pop
  @param opts: the command line options selected by the user
383 469ee405 Iustin Pop
  @type args: list
384 469ee405 Iustin Pop
  @param args: should be an empty list
385 469ee405 Iustin Pop
  @rtype: int
386 469ee405 Iustin Pop
  @return: the desired exit code
387 f4d4e184 Iustin Pop
388 f4d4e184 Iustin Pop
  """
389 f4d4e184 Iustin Pop
  op = opcodes.OpVerifyDisks()
390 400ca2f7 Iustin Pop
  result = SubmitOpCode(op, opts=opts)
391 29d376ec Iustin Pop
  if not isinstance(result, (list, tuple)) or len(result) != 3:
392 f4d4e184 Iustin Pop
    raise errors.ProgrammerError("Unknown result type for OpVerifyDisks")
393 f4d4e184 Iustin Pop
394 29d376ec Iustin Pop
  bad_nodes, instances, missing = result
395 b63ed789 Iustin Pop
396 f4d4e184 Iustin Pop
  retcode = constants.EXIT_SUCCESS
397 b63ed789 Iustin Pop
398 29d376ec Iustin Pop
  if bad_nodes:
399 29d376ec Iustin Pop
    for node, text in bad_nodes.items():
400 29d376ec Iustin Pop
      ToStdout("Error gathering data on node %s: %s",
401 26f15862 Iustin Pop
               node, utils.SafeEncode(text[-400:]))
402 b63ed789 Iustin Pop
      retcode |= 1
403 3a24c527 Iustin Pop
      ToStdout("You need to fix these nodes first before fixing instances")
404 b63ed789 Iustin Pop
405 f4d4e184 Iustin Pop
  if instances:
406 f4d4e184 Iustin Pop
    for iname in instances:
407 b63ed789 Iustin Pop
      if iname in missing:
408 b63ed789 Iustin Pop
        continue
409 f4d4e184 Iustin Pop
      op = opcodes.OpActivateInstanceDisks(instance_name=iname)
410 f4d4e184 Iustin Pop
      try:
411 3a24c527 Iustin Pop
        ToStdout("Activating disks for instance '%s'", iname)
412 400ca2f7 Iustin Pop
        SubmitOpCode(op, opts=opts)
413 f4d4e184 Iustin Pop
      except errors.GenericError, err:
414 f4d4e184 Iustin Pop
        nret, msg = FormatError(err)
415 f4d4e184 Iustin Pop
        retcode |= nret
416 3a24c527 Iustin Pop
        ToStderr("Error activating disks for instance %s: %s", iname, msg)
417 b63ed789 Iustin Pop
418 b63ed789 Iustin Pop
  if missing:
419 b63ed789 Iustin Pop
    for iname, ival in missing.iteritems():
420 29d376ec Iustin Pop
      all_missing = utils.all(ival, lambda x: x[0] in bad_nodes)
421 b63ed789 Iustin Pop
      if all_missing:
422 3a24c527 Iustin Pop
        ToStdout("Instance %s cannot be verified as it lives on"
423 3a24c527 Iustin Pop
                 " broken nodes", iname)
424 b63ed789 Iustin Pop
      else:
425 3a24c527 Iustin Pop
        ToStdout("Instance %s has missing logical volumes:", iname)
426 b63ed789 Iustin Pop
        ival.sort()
427 b63ed789 Iustin Pop
        for node, vol in ival:
428 29d376ec Iustin Pop
          if node in bad_nodes:
429 3a24c527 Iustin Pop
            ToStdout("\tbroken node %s /dev/xenvg/%s", node, vol)
430 b63ed789 Iustin Pop
          else:
431 3a24c527 Iustin Pop
            ToStdout("\t%s /dev/xenvg/%s", node, vol)
432 3a24c527 Iustin Pop
    ToStdout("You need to run replace_disks for all the above"
433 b63ed789 Iustin Pop
           " instances, if this message persist after fixing nodes.")
434 b63ed789 Iustin Pop
    retcode |= 1
435 f4d4e184 Iustin Pop
436 f4d4e184 Iustin Pop
  return retcode
437 f4d4e184 Iustin Pop
438 f4d4e184 Iustin Pop
439 60975797 Iustin Pop
def RepairDiskSizes(opts, args):
440 60975797 Iustin Pop
  """Verify sizes of cluster disks.
441 60975797 Iustin Pop
442 60975797 Iustin Pop
  @param opts: the command line options selected by the user
443 60975797 Iustin Pop
  @type args: list
444 60975797 Iustin Pop
  @param args: optional list of instances to restrict check to
445 60975797 Iustin Pop
  @rtype: int
446 60975797 Iustin Pop
  @return: the desired exit code
447 60975797 Iustin Pop
448 60975797 Iustin Pop
  """
449 60975797 Iustin Pop
  op = opcodes.OpRepairDiskSizes(instances=args)
450 400ca2f7 Iustin Pop
  SubmitOpCode(op, opts=opts)
451 60975797 Iustin Pop
452 60975797 Iustin Pop
453 4331f6cd Michael Hanselmann
@UsesRPC
454 a8083063 Iustin Pop
def MasterFailover(opts, args):
455 a8083063 Iustin Pop
  """Failover the master node.
456 a8083063 Iustin Pop
457 a8083063 Iustin Pop
  This command, when run on a non-master node, will cause the current
458 a8083063 Iustin Pop
  master to cease being master, and the non-master to become new
459 a8083063 Iustin Pop
  master.
460 a8083063 Iustin Pop
461 469ee405 Iustin Pop
  @param opts: the command line options selected by the user
462 469ee405 Iustin Pop
  @type args: list
463 469ee405 Iustin Pop
  @param args: should be an empty list
464 469ee405 Iustin Pop
  @rtype: int
465 469ee405 Iustin Pop
  @return: the desired exit code
466 469ee405 Iustin Pop
467 a8083063 Iustin Pop
  """
468 8e2524c3 Guido Trotter
  if opts.no_voting:
469 8e2524c3 Guido Trotter
    usertext = ("This will perform the failover even if most other nodes"
470 8e2524c3 Guido Trotter
                " are down, or if this node is outdated. This is dangerous"
471 8e2524c3 Guido Trotter
                " as it can lead to a non-consistent cluster. Check the"
472 8e2524c3 Guido Trotter
                " gnt-cluster(8) man page before proceeding. Continue?")
473 8e2524c3 Guido Trotter
    if not AskUser(usertext):
474 8e2524c3 Guido Trotter
      return 1
475 8e2524c3 Guido Trotter
476 8e2524c3 Guido Trotter
  return bootstrap.MasterFailover(no_voting=opts.no_voting)
477 a8083063 Iustin Pop
478 a8083063 Iustin Pop
479 73415719 Iustin Pop
def SearchTags(opts, args):
480 73415719 Iustin Pop
  """Searches the tags on all the cluster.
481 73415719 Iustin Pop
482 469ee405 Iustin Pop
  @param opts: the command line options selected by the user
483 469ee405 Iustin Pop
  @type args: list
484 469ee405 Iustin Pop
  @param args: should contain only one element, the tag pattern
485 469ee405 Iustin Pop
  @rtype: int
486 469ee405 Iustin Pop
  @return: the desired exit code
487 469ee405 Iustin Pop
488 73415719 Iustin Pop
  """
489 73415719 Iustin Pop
  op = opcodes.OpSearchTags(pattern=args[0])
490 400ca2f7 Iustin Pop
  result = SubmitOpCode(op, opts=opts)
491 73415719 Iustin Pop
  if not result:
492 73415719 Iustin Pop
    return 1
493 73415719 Iustin Pop
  result = list(result)
494 73415719 Iustin Pop
  result.sort()
495 73415719 Iustin Pop
  for path, tag in result:
496 3a24c527 Iustin Pop
    ToStdout("%s %s", path, tag)
497 73415719 Iustin Pop
498 73415719 Iustin Pop
499 6d4a1656 Michael Hanselmann
def _RenewCrypto(new_cluster_cert, new_rapi_cert, rapi_cert_filename,
500 6b7d5878 Michael Hanselmann
                 new_confd_hmac_key, force):
501 6d4a1656 Michael Hanselmann
  """Renews cluster certificates, keys and secrets.
502 6d4a1656 Michael Hanselmann
503 6d4a1656 Michael Hanselmann
  @type new_cluster_cert: bool
504 6d4a1656 Michael Hanselmann
  @param new_cluster_cert: Whether to generate a new cluster certificate
505 6d4a1656 Michael Hanselmann
  @type new_rapi_cert: bool
506 6d4a1656 Michael Hanselmann
  @param new_rapi_cert: Whether to generate a new RAPI certificate
507 6d4a1656 Michael Hanselmann
  @type rapi_cert_filename: string
508 6d4a1656 Michael Hanselmann
  @param rapi_cert_filename: Path to file containing new RAPI certificate
509 6b7d5878 Michael Hanselmann
  @type new_confd_hmac_key: bool
510 6b7d5878 Michael Hanselmann
  @param new_confd_hmac_key: Whether to generate a new HMAC key
511 6d4a1656 Michael Hanselmann
  @type force: bool
512 6d4a1656 Michael Hanselmann
  @param force: Whether to ask user for confirmation
513 6d4a1656 Michael Hanselmann
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 6b7d5878 Michael Hanselmann
                                    new_confd_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 6b7d5878 Michael Hanselmann
    if new_confd_hmac_key:
563 6b7d5878 Michael Hanselmann
      files_to_copy.append(constants.CONFD_HMAC_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 6b7d5878 Michael Hanselmann
                      opts.new_confd_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 3953242f Iustin Pop
          opts.candidate_pool_size is not None or
605 1338f2b4 Balazs Lecz
          opts.uid_pool is not None or
606 fdad8c4d Balazs Lecz
          opts.maintain_node_health is not None or
607 fdad8c4d Balazs Lecz
          opts.add_uids is not None or
608 fdad8c4d Balazs Lecz
          opts.remove_uids is not None):
609 3a24c527 Iustin Pop
    ToStderr("Please give at least one of the parameters.")
610 90b6aa3a Manuel Franceschini
    return 1
611 90b6aa3a Manuel Franceschini
612 90b6aa3a Manuel Franceschini
  vg_name = opts.vg_name
613 90b6aa3a Manuel Franceschini
  if not opts.lvm_storage and opts.vg_name:
614 6d4a1656 Michael Hanselmann
    ToStderr("Options --no-lvm-storage and --vg-name conflict.")
615 90b6aa3a Manuel Franceschini
    return 1
616 6d4a1656 Michael Hanselmann
617 6d4a1656 Michael Hanselmann
  if not opts.lvm_storage:
618 6d4a1656 Michael Hanselmann
    vg_name = ""
619 90b6aa3a Manuel Franceschini
620 779c15bb Iustin Pop
  hvlist = opts.enabled_hypervisors
621 779c15bb Iustin Pop
  if hvlist is not None:
622 779c15bb Iustin Pop
    hvlist = hvlist.split(",")
623 779c15bb Iustin Pop
624 f8e7ddca Guido Trotter
  # a list of (name, dict) we can pass directly to dict() (or [])
625 f8e7ddca Guido Trotter
  hvparams = dict(opts.hvparams)
626 f4ad2ef0 Iustin Pop
  for hv_params in hvparams.values():
627 a5728081 Guido Trotter
    utils.ForceDictType(hv_params, constants.HVS_PARAMETER_TYPES)
628 779c15bb Iustin Pop
629 779c15bb Iustin Pop
  beparams = opts.beparams
630 a5728081 Guido Trotter
  utils.ForceDictType(beparams, constants.BES_PARAMETER_TYPES)
631 779c15bb Iustin Pop
632 5af3da74 Guido Trotter
  nicparams = opts.nicparams
633 5af3da74 Guido Trotter
  utils.ForceDictType(nicparams, constants.NICS_PARAMETER_TYPES)
634 5af3da74 Guido Trotter
635 1338f2b4 Balazs Lecz
636 3953242f Iustin Pop
  mnh = opts.maintain_node_health
637 3953242f Iustin Pop
638 1338f2b4 Balazs Lecz
  uid_pool = opts.uid_pool
639 1338f2b4 Balazs Lecz
  if uid_pool is not None:
640 1338f2b4 Balazs Lecz
    uid_pool = uidpool.ParseUidPool(uid_pool)
641 1338f2b4 Balazs Lecz
642 fdad8c4d Balazs Lecz
  add_uids = opts.add_uids
643 fdad8c4d Balazs Lecz
  if add_uids is not None:
644 fdad8c4d Balazs Lecz
    add_uids = uidpool.ParseUidPool(add_uids)
645 fdad8c4d Balazs Lecz
646 fdad8c4d Balazs Lecz
  remove_uids = opts.remove_uids
647 fdad8c4d Balazs Lecz
  if remove_uids is not None:
648 fdad8c4d Balazs Lecz
    remove_uids = uidpool.ParseUidPool(remove_uids)
649 fdad8c4d Balazs Lecz
650 b8a8fbe1 Guido Trotter
  op = opcodes.OpSetClusterParams(vg_name=vg_name,
651 779c15bb Iustin Pop
                                  enabled_hypervisors=hvlist,
652 779c15bb Iustin Pop
                                  hvparams=hvparams,
653 17463d22 Renรฉ Nussbaumer
                                  os_hvp=None,
654 4b7735f9 Iustin Pop
                                  beparams=beparams,
655 5af3da74 Guido Trotter
                                  nicparams=nicparams,
656 3953242f Iustin Pop
                                  candidate_pool_size=opts.candidate_pool_size,
657 1338f2b4 Balazs Lecz
                                  maintain_node_health=mnh,
658 fdad8c4d Balazs Lecz
                                  uid_pool=uid_pool,
659 fdad8c4d Balazs Lecz
                                  add_uids=add_uids,
660 fdad8c4d Balazs Lecz
                                  remove_uids=remove_uids)
661 400ca2f7 Iustin Pop
  SubmitOpCode(op, opts=opts)
662 90b6aa3a Manuel Franceschini
  return 0
663 90b6aa3a Manuel Franceschini
664 90b6aa3a Manuel Franceschini
665 3ccafd0e Iustin Pop
def QueueOps(opts, args):
666 3ccafd0e Iustin Pop
  """Queue operations.
667 3ccafd0e Iustin Pop
668 469ee405 Iustin Pop
  @param opts: the command line options selected by the user
669 469ee405 Iustin Pop
  @type args: list
670 469ee405 Iustin Pop
  @param args: should contain only one element, the subcommand
671 469ee405 Iustin Pop
  @rtype: int
672 469ee405 Iustin Pop
  @return: the desired exit code
673 469ee405 Iustin Pop
674 3ccafd0e Iustin Pop
  """
675 3ccafd0e Iustin Pop
  command = args[0]
676 3ccafd0e Iustin Pop
  client = GetClient()
677 3ccafd0e Iustin Pop
  if command in ("drain", "undrain"):
678 3ccafd0e Iustin Pop
    drain_flag = command == "drain"
679 3ccafd0e Iustin Pop
    client.SetQueueDrainFlag(drain_flag)
680 3ccafd0e Iustin Pop
  elif command == "info":
681 3ccafd0e Iustin Pop
    result = client.QueryConfigValues(["drain_flag"])
682 3ccafd0e Iustin Pop
    if result[0]:
683 3a24c527 Iustin Pop
      val = "set"
684 3ccafd0e Iustin Pop
    else:
685 3a24c527 Iustin Pop
      val = "unset"
686 3a24c527 Iustin Pop
    ToStdout("The drain flag is %s" % val)
687 2e668b38 Guido Trotter
  else:
688 debac808 Iustin Pop
    raise errors.OpPrereqError("Command '%s' is not valid." % command,
689 debac808 Iustin Pop
                               errors.ECODE_INVAL)
690 2e668b38 Guido Trotter
691 3ccafd0e Iustin Pop
  return 0
692 3ccafd0e Iustin Pop
693 95b2e626 Michael Hanselmann
694 28b498cd Michael Hanselmann
def _ShowWatcherPause(until):
695 28b498cd Michael Hanselmann
  if until is None or until < time.time():
696 28b498cd Michael Hanselmann
    ToStdout("The watcher is not paused.")
697 28b498cd Michael Hanselmann
  else:
698 28b498cd Michael Hanselmann
    ToStdout("The watcher is paused until %s.", time.ctime(until))
699 28b498cd Michael Hanselmann
700 28b498cd Michael Hanselmann
701 95b2e626 Michael Hanselmann
def WatcherOps(opts, args):
702 95b2e626 Michael Hanselmann
  """Watcher operations.
703 95b2e626 Michael Hanselmann
704 95b2e626 Michael Hanselmann
  @param opts: the command line options selected by the user
705 95b2e626 Michael Hanselmann
  @type args: list
706 95b2e626 Michael Hanselmann
  @param args: should contain only one element, the subcommand
707 95b2e626 Michael Hanselmann
  @rtype: int
708 95b2e626 Michael Hanselmann
  @return: the desired exit code
709 95b2e626 Michael Hanselmann
710 95b2e626 Michael Hanselmann
  """
711 95b2e626 Michael Hanselmann
  command = args[0]
712 95b2e626 Michael Hanselmann
  client = GetClient()
713 95b2e626 Michael Hanselmann
714 95b2e626 Michael Hanselmann
  if command == "continue":
715 95b2e626 Michael Hanselmann
    client.SetWatcherPause(None)
716 28b498cd Michael Hanselmann
    ToStdout("The watcher is no longer paused.")
717 95b2e626 Michael Hanselmann
718 95b2e626 Michael Hanselmann
  elif command == "pause":
719 95b2e626 Michael Hanselmann
    if len(args) < 2:
720 debac808 Iustin Pop
      raise errors.OpPrereqError("Missing pause duration", errors.ECODE_INVAL)
721 95b2e626 Michael Hanselmann
722 28b498cd Michael Hanselmann
    result = client.SetWatcherPause(time.time() + ParseTimespec(args[1]))
723 28b498cd Michael Hanselmann
    _ShowWatcherPause(result)
724 95b2e626 Michael Hanselmann
725 95b2e626 Michael Hanselmann
  elif command == "info":
726 95b2e626 Michael Hanselmann
    result = client.QueryConfigValues(["watcher_pause"])
727 cac599f1 Michael Hanselmann
    _ShowWatcherPause(result[0])
728 95b2e626 Michael Hanselmann
729 95b2e626 Michael Hanselmann
  else:
730 debac808 Iustin Pop
    raise errors.OpPrereqError("Command '%s' is not valid." % command,
731 debac808 Iustin Pop
                               errors.ECODE_INVAL)
732 95b2e626 Michael Hanselmann
733 95b2e626 Michael Hanselmann
  return 0
734 95b2e626 Michael Hanselmann
735 95b2e626 Michael Hanselmann
736 a8083063 Iustin Pop
commands = {
737 6ea815cf Iustin Pop
  'init': (
738 6ea815cf Iustin Pop
    InitCluster, [ArgHost(min=1, max=1)],
739 064c21f8 Iustin Pop
    [BACKEND_OPT, CP_SIZE_OPT, ENABLED_HV_OPT, GLOBAL_FILEDIR_OPT,
740 6ea815cf Iustin Pop
     HVLIST_OPT, MAC_PREFIX_OPT, MASTER_NETDEV_OPT, NIC_PARAMS_OPT,
741 b989b9d9 Ken Wehr
     NOLVM_STORAGE_OPT, NOMODIFY_ETCHOSTS_OPT, NOMODIFY_SSH_SETUP_OPT,
742 3953242f Iustin Pop
     SECONDARY_IP_OPT, VG_NAME_OPT, MAINTAIN_NODE_HEALTH_OPT],
743 6ea815cf Iustin Pop
    "[opts...] <cluster_name>", "Initialises a new cluster configuration"),
744 6ea815cf Iustin Pop
  'destroy': (
745 064c21f8 Iustin Pop
    DestroyCluster, ARGS_NONE, [YES_DOIT_OPT],
746 6ea815cf Iustin Pop
    "", "Destroy cluster"),
747 6ea815cf Iustin Pop
  'rename': (
748 6ea815cf Iustin Pop
    RenameCluster, [ArgHost(min=1, max=1)],
749 064c21f8 Iustin Pop
    [FORCE_OPT],
750 6ea815cf Iustin Pop
    "<new_name>",
751 6ea815cf Iustin Pop
    "Renames the cluster"),
752 6ea815cf Iustin Pop
  'redist-conf': (
753 064c21f8 Iustin Pop
    RedistributeConfig, ARGS_NONE, [SUBMIT_OPT],
754 6ea815cf Iustin Pop
    "", "Forces a push of the configuration file and ssconf files"
755 6ea815cf Iustin Pop
    " to the nodes in the cluster"),
756 6ea815cf Iustin Pop
  'verify': (
757 6ea815cf Iustin Pop
    VerifyCluster, ARGS_NONE,
758 064c21f8 Iustin Pop
    [VERBOSE_OPT, DEBUG_SIMERR_OPT, ERROR_CODES_OPT, NONPLUS1_OPT],
759 6ea815cf Iustin Pop
    "", "Does a check on the cluster configuration"),
760 6ea815cf Iustin Pop
  'verify-disks': (
761 064c21f8 Iustin Pop
    VerifyDisks, ARGS_NONE, [],
762 6ea815cf Iustin Pop
    "", "Does a check on the cluster disk status"),
763 6ea815cf Iustin Pop
  'repair-disk-sizes': (
764 064c21f8 Iustin Pop
    RepairDiskSizes, ARGS_MANY_INSTANCES, [],
765 6ea815cf Iustin Pop
    "", "Updates mismatches in recorded disk sizes"),
766 6ea815cf Iustin Pop
  'masterfailover': (
767 064c21f8 Iustin Pop
    MasterFailover, ARGS_NONE, [NOVOTING_OPT],
768 6ea815cf Iustin Pop
    "", "Makes the current node the master"),
769 6ea815cf Iustin Pop
  'version': (
770 064c21f8 Iustin Pop
    ShowClusterVersion, ARGS_NONE, [],
771 6ea815cf Iustin Pop
    "", "Shows the cluster version"),
772 6ea815cf Iustin Pop
  'getmaster': (
773 064c21f8 Iustin Pop
    ShowClusterMaster, ARGS_NONE, [],
774 6ea815cf Iustin Pop
    "", "Shows the cluster master"),
775 6ea815cf Iustin Pop
  'copyfile': (
776 6ea815cf Iustin Pop
    ClusterCopyFile, [ArgFile(min=1, max=1)],
777 74adc100 Iustin Pop
    [NODE_LIST_OPT, USE_REPL_NET_OPT],
778 6ea815cf Iustin Pop
    "[-n node...] <filename>", "Copies a file to all (or only some) nodes"),
779 6ea815cf Iustin Pop
  'command': (
780 6ea815cf Iustin Pop
    RunClusterCommand, [ArgCommand(min=1)],
781 064c21f8 Iustin Pop
    [NODE_LIST_OPT],
782 6ea815cf Iustin Pop
    "[-n node...] <command>", "Runs a command on all (or only some) nodes"),
783 6ea815cf Iustin Pop
  'info': (
784 064c21f8 Iustin Pop
    ShowClusterConfig, ARGS_NONE, [],
785 6ea815cf Iustin Pop
    "", "Show cluster configuration"),
786 6ea815cf Iustin Pop
  'list-tags': (
787 064c21f8 Iustin Pop
    ListTags, ARGS_NONE, [], "", "List the tags of the cluster"),
788 6ea815cf Iustin Pop
  'add-tags': (
789 064c21f8 Iustin Pop
    AddTags, [ArgUnknown()], [TAG_SRC_OPT],
790 6ea815cf Iustin Pop
    "tag...", "Add tags to the cluster"),
791 6ea815cf Iustin Pop
  'remove-tags': (
792 064c21f8 Iustin Pop
    RemoveTags, [ArgUnknown()], [TAG_SRC_OPT],
793 6ea815cf Iustin Pop
    "tag...", "Remove tags from the cluster"),
794 6ea815cf Iustin Pop
  'search-tags': (
795 6ea815cf Iustin Pop
    SearchTags, [ArgUnknown(min=1, max=1)],
796 064c21f8 Iustin Pop
    [], "", "Searches the tags on all objects on"
797 6ea815cf Iustin Pop
    " the cluster for a given pattern (regex)"),
798 6ea815cf Iustin Pop
  'queue': (
799 6ea815cf Iustin Pop
    QueueOps,
800 6ea815cf Iustin Pop
    [ArgChoice(min=1, max=1, choices=["drain", "undrain", "info"])],
801 064c21f8 Iustin Pop
    [], "drain|undrain|info", "Change queue properties"),
802 6ea815cf Iustin Pop
  'watcher': (
803 6ea815cf Iustin Pop
    WatcherOps,
804 6ea815cf Iustin Pop
    [ArgChoice(min=1, max=1, choices=["pause", "continue", "info"]),
805 6ea815cf Iustin Pop
     ArgSuggest(min=0, max=1, choices=["30m", "1h", "4h"])],
806 064c21f8 Iustin Pop
    [],
807 6ea815cf Iustin Pop
    "{pause <timespec>|continue|info}", "Change watcher properties"),
808 6ea815cf Iustin Pop
  'modify': (
809 6ea815cf Iustin Pop
    SetClusterParams, ARGS_NONE,
810 064c21f8 Iustin Pop
    [BACKEND_OPT, CP_SIZE_OPT, ENABLED_HV_OPT, HVLIST_OPT,
811 1338f2b4 Balazs Lecz
     NIC_PARAMS_OPT, NOLVM_STORAGE_OPT, VG_NAME_OPT, MAINTAIN_NODE_HEALTH_OPT,
812 fdad8c4d Balazs Lecz
     UIDPOOL_OPT, ADD_UIDS_OPT, REMOVE_UIDS_OPT],
813 6ea815cf Iustin Pop
    "[opts...]",
814 6ea815cf Iustin Pop
    "Alters the parameters of the cluster"),
815 6d4a1656 Michael Hanselmann
  "renew-crypto": (
816 6d4a1656 Michael Hanselmann
    RenewCrypto, ARGS_NONE,
817 6b7d5878 Michael Hanselmann
    [NEW_CLUSTER_CERT_OPT, NEW_RAPI_CERT_OPT, RAPI_CERT_OPT,
818 6b7d5878 Michael Hanselmann
     NEW_CONFD_HMAC_KEY_OPT, FORCE_OPT],
819 6d4a1656 Michael Hanselmann
    "[opts...]",
820 6d4a1656 Michael Hanselmann
    "Renews cluster certificates, keys and secrets"),
821 a8083063 Iustin Pop
  }
822 a8083063 Iustin Pop
823 6d4a1656 Michael Hanselmann
824 a8083063 Iustin Pop
if __name__ == '__main__':
825 846baef9 Iustin Pop
  sys.exit(GenericMain(commands, override={"tag_type": constants.TAG_CLUSTER}))