Statistics
| Branch: | Tag: | Revision:

root / scripts / gnt-cluster @ 39b0f0c2

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