Statistics
| Branch: | Tag: | Revision:

root / lib / client / gnt_cluster.py @ 25be0c75

History | View | Annotate | Download (30.7 kB)

1 7b3e7d41 Michael Hanselmann
#
2 a8083063 Iustin Pop
#
3 a8083063 Iustin Pop
4 2f20d07b Manuel Franceschini
# Copyright (C) 2006, 2007, 2010 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 b3989551 Iustin Pop
import os.path
30 95b2e626 Michael Hanselmann
import time
31 6d4a1656 Michael Hanselmann
import OpenSSL
32 a8083063 Iustin Pop
33 a8083063 Iustin Pop
from ganeti.cli import *
34 a8083063 Iustin Pop
from ganeti import opcodes
35 c2a62a33 Michael Hanselmann
from ganeti import constants
36 f4d4e184 Iustin Pop
from ganeti import errors
37 b63ed789 Iustin Pop
from ganeti import utils
38 a0c9f010 Michael Hanselmann
from ganeti import bootstrap
39 b3989551 Iustin Pop
from ganeti import ssh
40 d3cfe525 Guido Trotter
from ganeti import objects
41 1338f2b4 Balazs Lecz
from ganeti import uidpool
42 cea881e5 Michael Hanselmann
from ganeti import compat
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 ed14ed48 Luca Bigliardi
  if not opts.drbd_storage and opts.drbd_helper:
66 ed14ed48 Luca Bigliardi
    ToStderr("Options --no-drbd-storage and --drbd-usermode-helper conflict.")
67 ed14ed48 Luca Bigliardi
    return 1
68 ed14ed48 Luca Bigliardi
69 ed14ed48 Luca Bigliardi
  drbd_helper = opts.drbd_helper
70 ed14ed48 Luca Bigliardi
  if opts.drbd_storage and not opts.drbd_helper:
71 ed14ed48 Luca Bigliardi
    drbd_helper = constants.DEFAULT_DRBD_HELPER
72 ed14ed48 Luca Bigliardi
73 25be0c75 Guido Trotter
  master_netdev = opts.master_netdev
74 25be0c75 Guido Trotter
  if master_netdev is None:
75 25be0c75 Guido Trotter
    master_netdev = constants.DEFAULT_BRIDGE
76 25be0c75 Guido Trotter
77 ea3a925f Alexander Schreiber
  hvlist = opts.enabled_hypervisors
78 383a3591 Iustin Pop
  if hvlist is None:
79 383a3591 Iustin Pop
    hvlist = constants.DEFAULT_ENABLED_HYPERVISOR
80 066f465d Guido Trotter
  hvlist = hvlist.split(",")
81 ea3a925f Alexander Schreiber
82 f8e7ddca Guido Trotter
  hvparams = dict(opts.hvparams)
83 ea3a925f Alexander Schreiber
  beparams = opts.beparams
84 b6a30b0d Guido Trotter
  nicparams = opts.nicparams
85 ea3a925f Alexander Schreiber
86 ea3a925f Alexander Schreiber
  # prepare beparams dict
87 d3cfe525 Guido Trotter
  beparams = objects.FillDict(constants.BEC_DEFAULTS, beparams)
88 a5728081 Guido Trotter
  utils.ForceDictType(beparams, constants.BES_PARAMETER_TYPES)
89 ea3a925f Alexander Schreiber
90 b6a30b0d Guido Trotter
  # prepare nicparams dict
91 b6a30b0d Guido Trotter
  nicparams = objects.FillDict(constants.NICC_DEFAULTS, nicparams)
92 b6a30b0d Guido Trotter
  utils.ForceDictType(nicparams, constants.NICS_PARAMETER_TYPES)
93 b6a30b0d Guido Trotter
94 6204ee71 René Nussbaumer
  # prepare ndparams dict
95 6204ee71 René Nussbaumer
  if opts.ndparams is None:
96 6204ee71 René Nussbaumer
    ndparams = dict(constants.NDC_DEFAULTS)
97 6204ee71 René Nussbaumer
  else:
98 6204ee71 René Nussbaumer
    ndparams = objects.FillDict(constants.NDC_DEFAULTS, opts.ndparams)
99 6204ee71 René Nussbaumer
    utils.ForceDictType(ndparams, constants.NDS_PARAMETER_TYPES)
100 6204ee71 René Nussbaumer
101 ea3a925f Alexander Schreiber
  # prepare hvparams dict
102 ea3a925f Alexander Schreiber
  for hv in constants.HYPER_TYPES:
103 ea3a925f Alexander Schreiber
    if hv not in hvparams:
104 ea3a925f Alexander Schreiber
      hvparams[hv] = {}
105 d3cfe525 Guido Trotter
    hvparams[hv] = objects.FillDict(constants.HVC_DEFAULTS[hv], hvparams[hv])
106 a5728081 Guido Trotter
    utils.ForceDictType(hvparams[hv], constants.HVS_PARAMETER_TYPES)
107 ea3a925f Alexander Schreiber
108 e32df528 Iustin Pop
  if opts.candidate_pool_size is None:
109 e32df528 Iustin Pop
    opts.candidate_pool_size = constants.MASTER_POOL_SIZE_DEFAULT
110 e32df528 Iustin Pop
111 e3646f22 Iustin Pop
  if opts.mac_prefix is None:
112 e3646f22 Iustin Pop
    opts.mac_prefix = constants.DEFAULT_MAC_PREFIX
113 e3646f22 Iustin Pop
114 39b0f0c2 Balazs Lecz
  uid_pool = opts.uid_pool
115 39b0f0c2 Balazs Lecz
  if uid_pool is not None:
116 39b0f0c2 Balazs Lecz
    uid_pool = uidpool.ParseUidPool(uid_pool)
117 39b0f0c2 Balazs Lecz
118 b883637f René Nussbaumer
  if opts.prealloc_wipe_disks is None:
119 b883637f René Nussbaumer
    opts.prealloc_wipe_disks = False
120 b883637f René Nussbaumer
121 e7323b5e Manuel Franceschini
  try:
122 e7323b5e Manuel Franceschini
    primary_ip_version = int(opts.primary_ip_version)
123 e7323b5e Manuel Franceschini
  except (ValueError, TypeError), err:
124 e7323b5e Manuel Franceschini
    ToStderr("Invalid primary ip version value: %s" % str(err))
125 e7323b5e Manuel Franceschini
    return 1
126 e7323b5e Manuel Franceschini
127 a0c9f010 Michael Hanselmann
  bootstrap.InitCluster(cluster_name=args[0],
128 a0c9f010 Michael Hanselmann
                        secondary_ip=opts.secondary_ip,
129 a0c9f010 Michael Hanselmann
                        vg_name=vg_name,
130 a0c9f010 Michael Hanselmann
                        mac_prefix=opts.mac_prefix,
131 25be0c75 Guido Trotter
                        master_netdev=master_netdev,
132 ea3a925f Alexander Schreiber
                        file_storage_dir=opts.file_storage_dir,
133 ea3a925f Alexander Schreiber
                        enabled_hypervisors=hvlist,
134 ea3a925f Alexander Schreiber
                        hvparams=hvparams,
135 ce735215 Guido Trotter
                        beparams=beparams,
136 b6a30b0d Guido Trotter
                        nicparams=nicparams,
137 6204ee71 René Nussbaumer
                        ndparams=ndparams,
138 ce735215 Guido Trotter
                        candidate_pool_size=opts.candidate_pool_size,
139 b86a6bcd Guido Trotter
                        modify_etc_hosts=opts.modify_etc_hosts,
140 b989b9d9 Ken Wehr
                        modify_ssh_setup=opts.modify_ssh_setup,
141 3953242f Iustin Pop
                        maintain_node_health=opts.maintain_node_health,
142 ed14ed48 Luca Bigliardi
                        drbd_helper=drbd_helper,
143 39b0f0c2 Balazs Lecz
                        uid_pool=uid_pool,
144 bf4af505 Apollon Oikonomopoulos
                        default_iallocator=opts.default_iallocator,
145 e7323b5e Manuel Franceschini
                        primary_ip_version=primary_ip_version,
146 b18ecea2 René Nussbaumer
                        prealloc_wipe_disks=opts.prealloc_wipe_disks,
147 ce735215 Guido Trotter
                        )
148 3552cd2e Luca Bigliardi
  op = opcodes.OpPostInitCluster()
149 400ca2f7 Iustin Pop
  SubmitOpCode(op, opts=opts)
150 a8083063 Iustin Pop
  return 0
151 a8083063 Iustin Pop
152 a8083063 Iustin Pop
153 4331f6cd Michael Hanselmann
@UsesRPC
154 a8083063 Iustin Pop
def DestroyCluster(opts, args):
155 a8083063 Iustin Pop
  """Destroy the cluster.
156 a8083063 Iustin Pop

157 469ee405 Iustin Pop
  @param opts: the command line options selected by the user
158 469ee405 Iustin Pop
  @type args: list
159 469ee405 Iustin Pop
  @param args: should be an empty list
160 469ee405 Iustin Pop
  @rtype: int
161 469ee405 Iustin Pop
  @return: the desired exit code
162 098c0958 Michael Hanselmann

163 a8083063 Iustin Pop
  """
164 a8083063 Iustin Pop
  if not opts.yes_do_it:
165 3a24c527 Iustin Pop
    ToStderr("Destroying a cluster is irreversible. If you really want"
166 3a24c527 Iustin Pop
             " destroy this cluster, supply the --yes-do-it option.")
167 a8083063 Iustin Pop
    return 1
168 a8083063 Iustin Pop
169 a8083063 Iustin Pop
  op = opcodes.OpDestroyCluster()
170 400ca2f7 Iustin Pop
  master = SubmitOpCode(op, opts=opts)
171 140aa4a8 Iustin Pop
  # if we reached this, the opcode didn't fail; we can proceed to
172 140aa4a8 Iustin Pop
  # shutdown all the daemons
173 140aa4a8 Iustin Pop
  bootstrap.FinalizeClusterDestroy(master)
174 a8083063 Iustin Pop
  return 0
175 a8083063 Iustin Pop
176 a8083063 Iustin Pop
177 07bd8a51 Iustin Pop
def RenameCluster(opts, args):
178 07bd8a51 Iustin Pop
  """Rename the cluster.
179 07bd8a51 Iustin Pop

180 469ee405 Iustin Pop
  @param opts: the command line options selected by the user
181 469ee405 Iustin Pop
  @type args: list
182 469ee405 Iustin Pop
  @param args: should contain only one element, the new cluster name
183 469ee405 Iustin Pop
  @rtype: int
184 469ee405 Iustin Pop
  @return: the desired exit code
185 07bd8a51 Iustin Pop

186 07bd8a51 Iustin Pop
  """
187 6a016df9 Michael Hanselmann
  cl = GetClient()
188 6a016df9 Michael Hanselmann
189 6a016df9 Michael Hanselmann
  (cluster_name, ) = cl.QueryConfigValues(["cluster_name"])
190 6a016df9 Michael Hanselmann
191 6a016df9 Michael Hanselmann
  new_name = args[0]
192 07bd8a51 Iustin Pop
  if not opts.force:
193 6a016df9 Michael Hanselmann
    usertext = ("This will rename the cluster from '%s' to '%s'. If you are"
194 6a016df9 Michael Hanselmann
                " connected over the network to the cluster name, the"
195 6a016df9 Michael Hanselmann
                " operation is very dangerous as the IP address will be"
196 6a016df9 Michael Hanselmann
                " removed from the node and the change may not go through."
197 6a016df9 Michael Hanselmann
                " Continue?") % (cluster_name, new_name)
198 47988778 Iustin Pop
    if not AskUser(usertext):
199 07bd8a51 Iustin Pop
      return 1
200 07bd8a51 Iustin Pop
201 6a016df9 Michael Hanselmann
  op = opcodes.OpRenameCluster(name=new_name)
202 6a016df9 Michael Hanselmann
  result = SubmitOpCode(op, opts=opts, cl=cl)
203 6a016df9 Michael Hanselmann
204 48418fea Iustin Pop
  if result:
205 48418fea Iustin Pop
    ToStdout("Cluster renamed from '%s' to '%s'", cluster_name, result)
206 6a016df9 Michael Hanselmann
207 07bd8a51 Iustin Pop
  return 0
208 07bd8a51 Iustin Pop
209 07bd8a51 Iustin Pop
210 afee0879 Iustin Pop
def RedistributeConfig(opts, args):
211 afee0879 Iustin Pop
  """Forces push of the cluster configuration.
212 afee0879 Iustin Pop

213 afee0879 Iustin Pop
  @param opts: the command line options selected by the user
214 afee0879 Iustin Pop
  @type args: list
215 afee0879 Iustin Pop
  @param args: empty list
216 afee0879 Iustin Pop
  @rtype: int
217 afee0879 Iustin Pop
  @return: the desired exit code
218 afee0879 Iustin Pop

219 afee0879 Iustin Pop
  """
220 81a49123 Iustin Pop
  op = opcodes.OpRedistributeConfig()
221 afee0879 Iustin Pop
  SubmitOrSend(op, opts)
222 afee0879 Iustin Pop
  return 0
223 afee0879 Iustin Pop
224 afee0879 Iustin Pop
225 a8083063 Iustin Pop
def ShowClusterVersion(opts, args):
226 a8083063 Iustin Pop
  """Write version of ganeti software to the standard output.
227 a8083063 Iustin Pop

228 469ee405 Iustin Pop
  @param opts: the command line options selected by the user
229 469ee405 Iustin Pop
  @type args: list
230 469ee405 Iustin Pop
  @param args: should be an empty list
231 469ee405 Iustin Pop
  @rtype: int
232 469ee405 Iustin Pop
  @return: the desired exit code
233 a8083063 Iustin Pop

234 a8083063 Iustin Pop
  """
235 2e7b8369 Iustin Pop
  cl = GetClient()
236 2e7b8369 Iustin Pop
  result = cl.QueryClusterInfo()
237 3a24c527 Iustin Pop
  ToStdout("Software version: %s", result["software_version"])
238 3a24c527 Iustin Pop
  ToStdout("Internode protocol: %s", result["protocol_version"])
239 3a24c527 Iustin Pop
  ToStdout("Configuration format: %s", result["config_version"])
240 3a24c527 Iustin Pop
  ToStdout("OS api version: %s", result["os_api_version"])
241 3a24c527 Iustin Pop
  ToStdout("Export interface: %s", result["export_version"])
242 a8083063 Iustin Pop
  return 0
243 a8083063 Iustin Pop
244 a8083063 Iustin Pop
245 a8083063 Iustin Pop
def ShowClusterMaster(opts, args):
246 a8083063 Iustin Pop
  """Write name of master node to the standard output.
247 a8083063 Iustin Pop

248 469ee405 Iustin Pop
  @param opts: the command line options selected by the user
249 469ee405 Iustin Pop
  @type args: list
250 469ee405 Iustin Pop
  @param args: should be an empty list
251 469ee405 Iustin Pop
  @rtype: int
252 469ee405 Iustin Pop
  @return: the desired exit code
253 a8083063 Iustin Pop

254 a8083063 Iustin Pop
  """
255 8eb148ae Iustin Pop
  master = bootstrap.GetMaster()
256 8eb148ae Iustin Pop
  ToStdout(master)
257 a8083063 Iustin Pop
  return 0
258 a8083063 Iustin Pop
259 cac599f1 Michael Hanselmann
260 d729e03a Guido Trotter
def _PrintGroupedParams(paramsdict, level=1, roman=False):
261 1094acda Guido Trotter
  """Print Grouped parameters (be, nic, disk) by group.
262 1094acda Guido Trotter

263 1094acda Guido Trotter
  @type paramsdict: dict of dicts
264 1094acda Guido Trotter
  @param paramsdict: {group: {param: value, ...}, ...}
265 664a9d73 René Nussbaumer
  @type level: int
266 664a9d73 René Nussbaumer
  @param level: Level of indention
267 1094acda Guido Trotter

268 1094acda Guido Trotter
  """
269 664a9d73 René Nussbaumer
  indent = "  " * level
270 9d91c6ab Guido Trotter
  for item, val in sorted(paramsdict.items()):
271 664a9d73 René Nussbaumer
    if isinstance(val, dict):
272 664a9d73 René Nussbaumer
      ToStdout("%s- %s:", indent, item)
273 d729e03a Guido Trotter
      _PrintGroupedParams(val, level=level + 1, roman=roman)
274 d729e03a Guido Trotter
    elif roman and isinstance(val, int):
275 d729e03a Guido Trotter
      ToStdout("%s  %s: %s", indent, item, compat.TryToRoman(val))
276 664a9d73 René Nussbaumer
    else:
277 664a9d73 René Nussbaumer
      ToStdout("%s  %s: %s", indent, item, val)
278 a8083063 Iustin Pop
279 cac599f1 Michael Hanselmann
280 a8083063 Iustin Pop
def ShowClusterConfig(opts, args):
281 a8083063 Iustin Pop
  """Shows cluster information.
282 a8083063 Iustin Pop

283 469ee405 Iustin Pop
  @param opts: the command line options selected by the user
284 469ee405 Iustin Pop
  @type args: list
285 469ee405 Iustin Pop
  @param args: should be an empty list
286 469ee405 Iustin Pop
  @rtype: int
287 469ee405 Iustin Pop
  @return: the desired exit code
288 469ee405 Iustin Pop

289 a8083063 Iustin Pop
  """
290 2e7b8369 Iustin Pop
  cl = GetClient()
291 2e7b8369 Iustin Pop
  result = cl.QueryClusterInfo()
292 a8083063 Iustin Pop
293 3a24c527 Iustin Pop
  ToStdout("Cluster name: %s", result["name"])
294 259578eb Iustin Pop
  ToStdout("Cluster UUID: %s", result["uuid"])
295 a8083063 Iustin Pop
296 90f72445 Iustin Pop
  ToStdout("Creation time: %s", utils.FormatTime(result["ctime"]))
297 90f72445 Iustin Pop
  ToStdout("Modification time: %s", utils.FormatTime(result["mtime"]))
298 90f72445 Iustin Pop
299 3a24c527 Iustin Pop
  ToStdout("Master node: %s", result["master"])
300 a8083063 Iustin Pop
301 3a24c527 Iustin Pop
  ToStdout("Architecture (this node): %s (%s)",
302 3a24c527 Iustin Pop
           result["architecture"][0], result["architecture"][1])
303 a8083063 Iustin Pop
304 c118d1f4 Michael Hanselmann
  if result["tags"]:
305 1f864b60 Iustin Pop
    tags = utils.CommaJoin(utils.NiceSort(result["tags"]))
306 c118d1f4 Michael Hanselmann
  else:
307 c118d1f4 Michael Hanselmann
    tags = "(none)"
308 c118d1f4 Michael Hanselmann
309 c118d1f4 Michael Hanselmann
  ToStdout("Tags: %s", tags)
310 c118d1f4 Michael Hanselmann
311 02691904 Alexander Schreiber
  ToStdout("Default hypervisor: %s", result["default_hypervisor"])
312 1f864b60 Iustin Pop
  ToStdout("Enabled hypervisors: %s",
313 1f864b60 Iustin Pop
           utils.CommaJoin(result["enabled_hypervisors"]))
314 469f88e1 Iustin Pop
315 3a24c527 Iustin Pop
  ToStdout("Hypervisor parameters:")
316 1094acda Guido Trotter
  _PrintGroupedParams(result["hvparams"])
317 469f88e1 Iustin Pop
318 dbb24ec7 Iustin Pop
  ToStdout("OS-specific hypervisor parameters:")
319 664a9d73 René Nussbaumer
  _PrintGroupedParams(result["os_hvp"])
320 664a9d73 René Nussbaumer
321 dbb24ec7 Iustin Pop
  ToStdout("OS parameters:")
322 dbb24ec7 Iustin Pop
  _PrintGroupedParams(result["osparams"])
323 dbb24ec7 Iustin Pop
324 3a24c527 Iustin Pop
  ToStdout("Cluster parameters:")
325 d729e03a Guido Trotter
  ToStdout("  - candidate pool size: %s",
326 d729e03a Guido Trotter
            compat.TryToRoman(result["candidate_pool_size"],
327 d729e03a Guido Trotter
                              convert=opts.roman_integers))
328 a8001106 Guido Trotter
  ToStdout("  - master netdev: %s", result["master_netdev"])
329 a8001106 Guido Trotter
  ToStdout("  - lvm volume group: %s", result["volume_group_name"])
330 5a3ab484 Iustin Pop
  if result["reserved_lvs"]:
331 5a3ab484 Iustin Pop
    reserved_lvs = utils.CommaJoin(result["reserved_lvs"])
332 5a3ab484 Iustin Pop
  else:
333 5a3ab484 Iustin Pop
    reserved_lvs = "(none)"
334 5a3ab484 Iustin Pop
  ToStdout("  - lvm reserved volumes: %s", reserved_lvs)
335 ed14ed48 Luca Bigliardi
  ToStdout("  - drbd usermode helper: %s", result["drbd_usermode_helper"])
336 a8001106 Guido Trotter
  ToStdout("  - file storage path: %s", result["file_storage_dir"])
337 3953242f Iustin Pop
  ToStdout("  - maintenance of node health: %s",
338 3953242f Iustin Pop
           result["maintain_node_health"])
339 d729e03a Guido Trotter
  ToStdout("  - uid pool: %s",
340 d729e03a Guido Trotter
            uidpool.FormatUidPool(result["uid_pool"],
341 d729e03a Guido Trotter
                                  roman=opts.roman_integers))
342 bf4af505 Apollon Oikonomopoulos
  ToStdout("  - default instance allocator: %s", result["default_iallocator"])
343 e7323b5e Manuel Franceschini
  ToStdout("  - primary ip version: %d", result["primary_ip_version"])
344 b18ecea2 René Nussbaumer
  ToStdout("  - preallocation wipe disks: %s", result["prealloc_wipe_disks"])
345 4b7735f9 Iustin Pop
346 4b7735f9 Iustin Pop
  ToStdout("Default instance parameters:")
347 d729e03a Guido Trotter
  _PrintGroupedParams(result["beparams"], roman=opts.roman_integers)
348 1094acda Guido Trotter
349 1094acda Guido Trotter
  ToStdout("Default nic parameters:")
350 d729e03a Guido Trotter
  _PrintGroupedParams(result["nicparams"], roman=opts.roman_integers)
351 8a12ce45 Iustin Pop
352 a8083063 Iustin Pop
  return 0
353 a8083063 Iustin Pop
354 a8083063 Iustin Pop
355 a8083063 Iustin Pop
def ClusterCopyFile(opts, args):
356 a8083063 Iustin Pop
  """Copy a file from master to some nodes.
357 a8083063 Iustin Pop

358 469ee405 Iustin Pop
  @param opts: the command line options selected by the user
359 469ee405 Iustin Pop
  @type args: list
360 469ee405 Iustin Pop
  @param args: should contain only one element, the path of
361 469ee405 Iustin Pop
      the file to be copied
362 469ee405 Iustin Pop
  @rtype: int
363 469ee405 Iustin Pop
  @return: the desired exit code
364 a8083063 Iustin Pop

365 a8083063 Iustin Pop
  """
366 b3989551 Iustin Pop
  filename = args[0]
367 b3989551 Iustin Pop
  if not os.path.exists(filename):
368 debac808 Iustin Pop
    raise errors.OpPrereqError("No such filename '%s'" % filename,
369 debac808 Iustin Pop
                               errors.ECODE_INVAL)
370 b3989551 Iustin Pop
371 56bece1f Iustin Pop
  cl = GetClient()
372 56bece1f Iustin Pop
373 56bece1f Iustin Pop
  cluster_name = cl.QueryConfigValues(["cluster_name"])[0]
374 56bece1f Iustin Pop
375 74adc100 Iustin Pop
  results = GetOnlineNodes(nodes=opts.nodes, cl=cl, filter_master=True,
376 74adc100 Iustin Pop
                           secondary_ips=opts.use_replication_network)
377 e00ea635 Michael Hanselmann
378 56bece1f Iustin Pop
  srun = ssh.SshRunner(cluster_name=cluster_name)
379 b3989551 Iustin Pop
  for node in results:
380 b3989551 Iustin Pop
    if not srun.CopyFileToNode(node, filename):
381 3a24c527 Iustin Pop
      ToStderr("Copy of file %s to node %s failed", filename, node)
382 b3989551 Iustin Pop
383 a8083063 Iustin Pop
  return 0
384 a8083063 Iustin Pop
385 a8083063 Iustin Pop
386 a8083063 Iustin Pop
def RunClusterCommand(opts, args):
387 a8083063 Iustin Pop
  """Run a command on some nodes.
388 a8083063 Iustin Pop

389 469ee405 Iustin Pop
  @param opts: the command line options selected by the user
390 469ee405 Iustin Pop
  @type args: list
391 469ee405 Iustin Pop
  @param args: should contain the command to be run and its arguments
392 469ee405 Iustin Pop
  @rtype: int
393 469ee405 Iustin Pop
  @return: the desired exit code
394 a8083063 Iustin Pop

395 a8083063 Iustin Pop
  """
396 56bece1f Iustin Pop
  cl = GetClient()
397 7688d0d3 Michael Hanselmann
398 a8083063 Iustin Pop
  command = " ".join(args)
399 4040a784 Iustin Pop
400 4040a784 Iustin Pop
  nodes = GetOnlineNodes(nodes=opts.nodes, cl=cl)
401 56bece1f Iustin Pop
402 56bece1f Iustin Pop
  cluster_name, master_node = cl.QueryConfigValues(["cluster_name",
403 56bece1f Iustin Pop
                                                    "master_node"])
404 b3989551 Iustin Pop
405 56bece1f Iustin Pop
  srun = ssh.SshRunner(cluster_name=cluster_name)
406 b3989551 Iustin Pop
407 7688d0d3 Michael Hanselmann
  # Make sure master node is at list end
408 b3989551 Iustin Pop
  if master_node in nodes:
409 b3989551 Iustin Pop
    nodes.remove(master_node)
410 b3989551 Iustin Pop
    nodes.append(master_node)
411 b3989551 Iustin Pop
412 b3989551 Iustin Pop
  for name in nodes:
413 b3989551 Iustin Pop
    result = srun.Run(name, "root", command)
414 3a24c527 Iustin Pop
    ToStdout("------------------------------------------------")
415 3a24c527 Iustin Pop
    ToStdout("node: %s", name)
416 3a24c527 Iustin Pop
    ToStdout("%s", result.output)
417 3a24c527 Iustin Pop
    ToStdout("return code = %s", result.exit_code)
418 b3989551 Iustin Pop
419 b3989551 Iustin Pop
  return 0
420 a8083063 Iustin Pop
421 a8083063 Iustin Pop
422 a8083063 Iustin Pop
def VerifyCluster(opts, args):
423 a8083063 Iustin Pop
  """Verify integrity of cluster, performing various test on nodes.
424 a8083063 Iustin Pop

425 469ee405 Iustin Pop
  @param opts: the command line options selected by the user
426 469ee405 Iustin Pop
  @type args: list
427 469ee405 Iustin Pop
  @param args: should be an empty list
428 469ee405 Iustin Pop
  @rtype: int
429 469ee405 Iustin Pop
  @return: the desired exit code
430 a8083063 Iustin Pop

431 a8083063 Iustin Pop
  """
432 8d59409f Iustin Pop
  skip_checks = []
433 e54c4c5e Guido Trotter
  if opts.skip_nplusone_mem:
434 e54c4c5e Guido Trotter
    skip_checks.append(constants.VERIFY_NPLUSONE_MEM)
435 7c874ee1 Iustin Pop
  op = opcodes.OpVerifyCluster(skip_checks=skip_checks,
436 7c874ee1 Iustin Pop
                               verbose=opts.verbose,
437 a0c9776a Iustin Pop
                               error_codes=opts.error_codes,
438 a0c9776a Iustin Pop
                               debug_simulate_errors=opts.simulate_errors)
439 400ca2f7 Iustin Pop
  if SubmitOpCode(op, opts=opts):
440 34290825 Michael Hanselmann
    return 0
441 34290825 Michael Hanselmann
  else:
442 34290825 Michael Hanselmann
    return 1
443 a8083063 Iustin Pop
444 a8083063 Iustin Pop
445 f4d4e184 Iustin Pop
def VerifyDisks(opts, args):
446 f4d4e184 Iustin Pop
  """Verify integrity of cluster disks.
447 f4d4e184 Iustin Pop

448 469ee405 Iustin Pop
  @param opts: the command line options selected by the user
449 469ee405 Iustin Pop
  @type args: list
450 469ee405 Iustin Pop
  @param args: should be an empty list
451 469ee405 Iustin Pop
  @rtype: int
452 469ee405 Iustin Pop
  @return: the desired exit code
453 f4d4e184 Iustin Pop

454 f4d4e184 Iustin Pop
  """
455 f1b083ce Michael Hanselmann
  cl = GetClient()
456 f1b083ce Michael Hanselmann
457 f4d4e184 Iustin Pop
  op = opcodes.OpVerifyDisks()
458 f1b083ce Michael Hanselmann
  result = SubmitOpCode(op, opts=opts, cl=cl)
459 29d376ec Iustin Pop
  if not isinstance(result, (list, tuple)) or len(result) != 3:
460 f4d4e184 Iustin Pop
    raise errors.ProgrammerError("Unknown result type for OpVerifyDisks")
461 f4d4e184 Iustin Pop
462 29d376ec Iustin Pop
  bad_nodes, instances, missing = result
463 b63ed789 Iustin Pop
464 f4d4e184 Iustin Pop
  retcode = constants.EXIT_SUCCESS
465 b63ed789 Iustin Pop
466 29d376ec Iustin Pop
  if bad_nodes:
467 29d376ec Iustin Pop
    for node, text in bad_nodes.items():
468 29d376ec Iustin Pop
      ToStdout("Error gathering data on node %s: %s",
469 26f15862 Iustin Pop
               node, utils.SafeEncode(text[-400:]))
470 b63ed789 Iustin Pop
      retcode |= 1
471 3a24c527 Iustin Pop
      ToStdout("You need to fix these nodes first before fixing instances")
472 b63ed789 Iustin Pop
473 f4d4e184 Iustin Pop
  if instances:
474 f4d4e184 Iustin Pop
    for iname in instances:
475 b63ed789 Iustin Pop
      if iname in missing:
476 b63ed789 Iustin Pop
        continue
477 f4d4e184 Iustin Pop
      op = opcodes.OpActivateInstanceDisks(instance_name=iname)
478 f4d4e184 Iustin Pop
      try:
479 3a24c527 Iustin Pop
        ToStdout("Activating disks for instance '%s'", iname)
480 f1b083ce Michael Hanselmann
        SubmitOpCode(op, opts=opts, cl=cl)
481 f4d4e184 Iustin Pop
      except errors.GenericError, err:
482 f4d4e184 Iustin Pop
        nret, msg = FormatError(err)
483 f4d4e184 Iustin Pop
        retcode |= nret
484 3a24c527 Iustin Pop
        ToStderr("Error activating disks for instance %s: %s", iname, msg)
485 b63ed789 Iustin Pop
486 b63ed789 Iustin Pop
  if missing:
487 f1b083ce Michael Hanselmann
    (vg_name, ) = cl.QueryConfigValues(["volume_group_name"])
488 f1b083ce Michael Hanselmann
489 b63ed789 Iustin Pop
    for iname, ival in missing.iteritems():
490 403f5172 Guido Trotter
      all_missing = compat.all(x[0] in bad_nodes for x in ival)
491 b63ed789 Iustin Pop
      if all_missing:
492 3a24c527 Iustin Pop
        ToStdout("Instance %s cannot be verified as it lives on"
493 3a24c527 Iustin Pop
                 " broken nodes", iname)
494 b63ed789 Iustin Pop
      else:
495 3a24c527 Iustin Pop
        ToStdout("Instance %s has missing logical volumes:", iname)
496 b63ed789 Iustin Pop
        ival.sort()
497 b63ed789 Iustin Pop
        for node, vol in ival:
498 29d376ec Iustin Pop
          if node in bad_nodes:
499 f1b083ce Michael Hanselmann
            ToStdout("\tbroken node %s /dev/%s/%s", node, vg_name, vol)
500 b63ed789 Iustin Pop
          else:
501 f1b083ce Michael Hanselmann
            ToStdout("\t%s /dev/%s/%s", node, vg_name, vol)
502 f1b083ce Michael Hanselmann
503 3a24c527 Iustin Pop
    ToStdout("You need to run replace_disks for all the above"
504 f1b083ce Michael Hanselmann
             " instances, if this message persist after fixing nodes.")
505 b63ed789 Iustin Pop
    retcode |= 1
506 f4d4e184 Iustin Pop
507 f4d4e184 Iustin Pop
  return retcode
508 f4d4e184 Iustin Pop
509 f4d4e184 Iustin Pop
510 60975797 Iustin Pop
def RepairDiskSizes(opts, args):
511 60975797 Iustin Pop
  """Verify sizes of cluster disks.
512 60975797 Iustin Pop

513 60975797 Iustin Pop
  @param opts: the command line options selected by the user
514 60975797 Iustin Pop
  @type args: list
515 60975797 Iustin Pop
  @param args: optional list of instances to restrict check to
516 60975797 Iustin Pop
  @rtype: int
517 60975797 Iustin Pop
  @return: the desired exit code
518 60975797 Iustin Pop

519 60975797 Iustin Pop
  """
520 60975797 Iustin Pop
  op = opcodes.OpRepairDiskSizes(instances=args)
521 400ca2f7 Iustin Pop
  SubmitOpCode(op, opts=opts)
522 60975797 Iustin Pop
523 60975797 Iustin Pop
524 4331f6cd Michael Hanselmann
@UsesRPC
525 a8083063 Iustin Pop
def MasterFailover(opts, args):
526 a8083063 Iustin Pop
  """Failover the master node.
527 a8083063 Iustin Pop

528 a8083063 Iustin Pop
  This command, when run on a non-master node, will cause the current
529 a8083063 Iustin Pop
  master to cease being master, and the non-master to become new
530 a8083063 Iustin Pop
  master.
531 a8083063 Iustin Pop

532 469ee405 Iustin Pop
  @param opts: the command line options selected by the user
533 469ee405 Iustin Pop
  @type args: list
534 469ee405 Iustin Pop
  @param args: should be an empty list
535 469ee405 Iustin Pop
  @rtype: int
536 469ee405 Iustin Pop
  @return: the desired exit code
537 469ee405 Iustin Pop

538 a8083063 Iustin Pop
  """
539 8e2524c3 Guido Trotter
  if opts.no_voting:
540 8e2524c3 Guido Trotter
    usertext = ("This will perform the failover even if most other nodes"
541 8e2524c3 Guido Trotter
                " are down, or if this node is outdated. This is dangerous"
542 8e2524c3 Guido Trotter
                " as it can lead to a non-consistent cluster. Check the"
543 8e2524c3 Guido Trotter
                " gnt-cluster(8) man page before proceeding. Continue?")
544 8e2524c3 Guido Trotter
    if not AskUser(usertext):
545 8e2524c3 Guido Trotter
      return 1
546 8e2524c3 Guido Trotter
547 8e2524c3 Guido Trotter
  return bootstrap.MasterFailover(no_voting=opts.no_voting)
548 a8083063 Iustin Pop
549 a8083063 Iustin Pop
550 4404ffad Iustin Pop
def MasterPing(opts, args):
551 4404ffad Iustin Pop
  """Checks if the master is alive.
552 4404ffad Iustin Pop

553 4404ffad Iustin Pop
  @param opts: the command line options selected by the user
554 4404ffad Iustin Pop
  @type args: list
555 4404ffad Iustin Pop
  @param args: should be an empty list
556 4404ffad Iustin Pop
  @rtype: int
557 4404ffad Iustin Pop
  @return: the desired exit code
558 4404ffad Iustin Pop

559 4404ffad Iustin Pop
  """
560 4404ffad Iustin Pop
  try:
561 4404ffad Iustin Pop
    cl = GetClient()
562 4404ffad Iustin Pop
    cl.QueryClusterInfo()
563 4404ffad Iustin Pop
    return 0
564 4404ffad Iustin Pop
  except Exception: # pylint: disable-msg=W0703
565 4404ffad Iustin Pop
    return 1
566 4404ffad Iustin Pop
567 4404ffad Iustin Pop
568 73415719 Iustin Pop
def SearchTags(opts, args):
569 73415719 Iustin Pop
  """Searches the tags on all the cluster.
570 73415719 Iustin Pop

571 469ee405 Iustin Pop
  @param opts: the command line options selected by the user
572 469ee405 Iustin Pop
  @type args: list
573 469ee405 Iustin Pop
  @param args: should contain only one element, the tag pattern
574 469ee405 Iustin Pop
  @rtype: int
575 469ee405 Iustin Pop
  @return: the desired exit code
576 469ee405 Iustin Pop

577 73415719 Iustin Pop
  """
578 73415719 Iustin Pop
  op = opcodes.OpSearchTags(pattern=args[0])
579 400ca2f7 Iustin Pop
  result = SubmitOpCode(op, opts=opts)
580 73415719 Iustin Pop
  if not result:
581 73415719 Iustin Pop
    return 1
582 73415719 Iustin Pop
  result = list(result)
583 73415719 Iustin Pop
  result.sort()
584 73415719 Iustin Pop
  for path, tag in result:
585 3a24c527 Iustin Pop
    ToStdout("%s %s", path, tag)
586 73415719 Iustin Pop
587 73415719 Iustin Pop
588 6d4a1656 Michael Hanselmann
def _RenewCrypto(new_cluster_cert, new_rapi_cert, rapi_cert_filename,
589 3db3eb2a Michael Hanselmann
                 new_confd_hmac_key, new_cds, cds_filename,
590 3db3eb2a Michael Hanselmann
                 force):
591 6d4a1656 Michael Hanselmann
  """Renews cluster certificates, keys and secrets.
592 6d4a1656 Michael Hanselmann

593 6d4a1656 Michael Hanselmann
  @type new_cluster_cert: bool
594 6d4a1656 Michael Hanselmann
  @param new_cluster_cert: Whether to generate a new cluster certificate
595 6d4a1656 Michael Hanselmann
  @type new_rapi_cert: bool
596 6d4a1656 Michael Hanselmann
  @param new_rapi_cert: Whether to generate a new RAPI certificate
597 6d4a1656 Michael Hanselmann
  @type rapi_cert_filename: string
598 6d4a1656 Michael Hanselmann
  @param rapi_cert_filename: Path to file containing new RAPI certificate
599 6b7d5878 Michael Hanselmann
  @type new_confd_hmac_key: bool
600 6b7d5878 Michael Hanselmann
  @param new_confd_hmac_key: Whether to generate a new HMAC key
601 3db3eb2a Michael Hanselmann
  @type new_cds: bool
602 3db3eb2a Michael Hanselmann
  @param new_cds: Whether to generate a new cluster domain secret
603 3db3eb2a Michael Hanselmann
  @type cds_filename: string
604 3db3eb2a Michael Hanselmann
  @param cds_filename: Path to file containing new cluster domain secret
605 6d4a1656 Michael Hanselmann
  @type force: bool
606 6d4a1656 Michael Hanselmann
  @param force: Whether to ask user for confirmation
607 6d4a1656 Michael Hanselmann

608 6d4a1656 Michael Hanselmann
  """
609 6d4a1656 Michael Hanselmann
  if new_rapi_cert and rapi_cert_filename:
610 6d4a1656 Michael Hanselmann
    ToStderr("Only one of the --new-rapi-certficate and --rapi-certificate"
611 6d4a1656 Michael Hanselmann
             " options can be specified at the same time.")
612 6d4a1656 Michael Hanselmann
    return 1
613 6d4a1656 Michael Hanselmann
614 3db3eb2a Michael Hanselmann
  if new_cds and cds_filename:
615 3db3eb2a Michael Hanselmann
    ToStderr("Only one of the --new-cluster-domain-secret and"
616 3db3eb2a Michael Hanselmann
             " --cluster-domain-secret options can be specified at"
617 3db3eb2a Michael Hanselmann
             " the same time.")
618 3db3eb2a Michael Hanselmann
    return 1
619 3db3eb2a Michael Hanselmann
620 6d4a1656 Michael Hanselmann
  if rapi_cert_filename:
621 6d4a1656 Michael Hanselmann
    # Read and verify new certificate
622 6d4a1656 Michael Hanselmann
    try:
623 6d4a1656 Michael Hanselmann
      rapi_cert_pem = utils.ReadFile(rapi_cert_filename)
624 6d4a1656 Michael Hanselmann
625 6d4a1656 Michael Hanselmann
      OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM,
626 6d4a1656 Michael Hanselmann
                                      rapi_cert_pem)
627 6d4a1656 Michael Hanselmann
    except Exception, err: # pylint: disable-msg=W0703
628 6d4a1656 Michael Hanselmann
      ToStderr("Can't load new RAPI certificate from %s: %s" %
629 6d4a1656 Michael Hanselmann
               (rapi_cert_filename, str(err)))
630 6d4a1656 Michael Hanselmann
      return 1
631 6d4a1656 Michael Hanselmann
632 6d4a1656 Michael Hanselmann
    try:
633 6d4a1656 Michael Hanselmann
      OpenSSL.crypto.load_privatekey(OpenSSL.crypto.FILETYPE_PEM, rapi_cert_pem)
634 6d4a1656 Michael Hanselmann
    except Exception, err: # pylint: disable-msg=W0703
635 6d4a1656 Michael Hanselmann
      ToStderr("Can't load new RAPI private key from %s: %s" %
636 6d4a1656 Michael Hanselmann
               (rapi_cert_filename, str(err)))
637 6d4a1656 Michael Hanselmann
      return 1
638 6d4a1656 Michael Hanselmann
639 6d4a1656 Michael Hanselmann
  else:
640 6d4a1656 Michael Hanselmann
    rapi_cert_pem = None
641 6d4a1656 Michael Hanselmann
642 3db3eb2a Michael Hanselmann
  if cds_filename:
643 3db3eb2a Michael Hanselmann
    try:
644 3db3eb2a Michael Hanselmann
      cds = utils.ReadFile(cds_filename)
645 3db3eb2a Michael Hanselmann
    except Exception, err: # pylint: disable-msg=W0703
646 3db3eb2a Michael Hanselmann
      ToStderr("Can't load new cluster domain secret from %s: %s" %
647 3db3eb2a Michael Hanselmann
               (cds_filename, str(err)))
648 3db3eb2a Michael Hanselmann
      return 1
649 3db3eb2a Michael Hanselmann
  else:
650 3db3eb2a Michael Hanselmann
    cds = None
651 3db3eb2a Michael Hanselmann
652 6d4a1656 Michael Hanselmann
  if not force:
653 6d4a1656 Michael Hanselmann
    usertext = ("This requires all daemons on all nodes to be restarted and"
654 6d4a1656 Michael Hanselmann
                " may take some time. Continue?")
655 6d4a1656 Michael Hanselmann
    if not AskUser(usertext):
656 6d4a1656 Michael Hanselmann
      return 1
657 6d4a1656 Michael Hanselmann
658 6d4a1656 Michael Hanselmann
  def _RenewCryptoInner(ctx):
659 6d4a1656 Michael Hanselmann
    ctx.feedback_fn("Updating certificates and keys")
660 6d4a1656 Michael Hanselmann
    bootstrap.GenerateClusterCrypto(new_cluster_cert, new_rapi_cert,
661 6b7d5878 Michael Hanselmann
                                    new_confd_hmac_key,
662 3db3eb2a Michael Hanselmann
                                    new_cds,
663 3db3eb2a Michael Hanselmann
                                    rapi_cert_pem=rapi_cert_pem,
664 3db3eb2a Michael Hanselmann
                                    cds=cds)
665 6d4a1656 Michael Hanselmann
666 6d4a1656 Michael Hanselmann
    files_to_copy = []
667 6d4a1656 Michael Hanselmann
668 6d4a1656 Michael Hanselmann
    if new_cluster_cert:
669 168c1de2 Michael Hanselmann
      files_to_copy.append(constants.NODED_CERT_FILE)
670 6d4a1656 Michael Hanselmann
671 6d4a1656 Michael Hanselmann
    if new_rapi_cert or rapi_cert_pem:
672 6d4a1656 Michael Hanselmann
      files_to_copy.append(constants.RAPI_CERT_FILE)
673 6d4a1656 Michael Hanselmann
674 6b7d5878 Michael Hanselmann
    if new_confd_hmac_key:
675 6b7d5878 Michael Hanselmann
      files_to_copy.append(constants.CONFD_HMAC_KEY)
676 6d4a1656 Michael Hanselmann
677 3db3eb2a Michael Hanselmann
    if new_cds or cds:
678 3db3eb2a Michael Hanselmann
      files_to_copy.append(constants.CLUSTER_DOMAIN_SECRET_FILE)
679 3db3eb2a Michael Hanselmann
680 6d4a1656 Michael Hanselmann
    if files_to_copy:
681 6d4a1656 Michael Hanselmann
      for node_name in ctx.nonmaster_nodes:
682 6d4a1656 Michael Hanselmann
        ctx.feedback_fn("Copying %s to %s" %
683 6d4a1656 Michael Hanselmann
                        (", ".join(files_to_copy), node_name))
684 6d4a1656 Michael Hanselmann
        for file_name in files_to_copy:
685 6d4a1656 Michael Hanselmann
          ctx.ssh.CopyFileToNode(node_name, file_name)
686 6d4a1656 Michael Hanselmann
687 6d4a1656 Michael Hanselmann
  RunWhileClusterStopped(ToStdout, _RenewCryptoInner)
688 6d4a1656 Michael Hanselmann
689 6d4a1656 Michael Hanselmann
  ToStdout("All requested certificates and keys have been replaced."
690 6d4a1656 Michael Hanselmann
           " Running \"gnt-cluster verify\" now is recommended.")
691 6d4a1656 Michael Hanselmann
692 6d4a1656 Michael Hanselmann
  return 0
693 6d4a1656 Michael Hanselmann
694 6d4a1656 Michael Hanselmann
695 6d4a1656 Michael Hanselmann
def RenewCrypto(opts, args):
696 6d4a1656 Michael Hanselmann
  """Renews cluster certificates, keys and secrets.
697 6d4a1656 Michael Hanselmann

698 6d4a1656 Michael Hanselmann
  """
699 6d4a1656 Michael Hanselmann
  return _RenewCrypto(opts.new_cluster_cert,
700 6d4a1656 Michael Hanselmann
                      opts.new_rapi_cert,
701 6d4a1656 Michael Hanselmann
                      opts.rapi_cert,
702 6b7d5878 Michael Hanselmann
                      opts.new_confd_hmac_key,
703 3db3eb2a Michael Hanselmann
                      opts.new_cluster_domain_secret,
704 3db3eb2a Michael Hanselmann
                      opts.cluster_domain_secret,
705 6d4a1656 Michael Hanselmann
                      opts.force)
706 6d4a1656 Michael Hanselmann
707 6d4a1656 Michael Hanselmann
708 90b6aa3a Manuel Franceschini
def SetClusterParams(opts, args):
709 90b6aa3a Manuel Franceschini
  """Modify the cluster.
710 90b6aa3a Manuel Franceschini

711 469ee405 Iustin Pop
  @param opts: the command line options selected by the user
712 469ee405 Iustin Pop
  @type args: list
713 469ee405 Iustin Pop
  @param args: should be an empty list
714 469ee405 Iustin Pop
  @rtype: int
715 469ee405 Iustin Pop
  @return: the desired exit code
716 90b6aa3a Manuel Franceschini

717 90b6aa3a Manuel Franceschini
  """
718 779c15bb Iustin Pop
  if not (not opts.lvm_storage or opts.vg_name or
719 ed14ed48 Luca Bigliardi
          not opts.drbd_storage or opts.drbd_helper or
720 779c15bb Iustin Pop
          opts.enabled_hypervisors or opts.hvparams or
721 6204ee71 René Nussbaumer
          opts.beparams or opts.nicparams or opts.ndparams or
722 3953242f Iustin Pop
          opts.candidate_pool_size is not None or
723 1338f2b4 Balazs Lecz
          opts.uid_pool is not None or
724 fdad8c4d Balazs Lecz
          opts.maintain_node_health is not None or
725 fdad8c4d Balazs Lecz
          opts.add_uids is not None or
726 bf4af505 Apollon Oikonomopoulos
          opts.remove_uids is not None or
727 f38ea602 Iustin Pop
          opts.default_iallocator is not None or
728 b883637f René Nussbaumer
          opts.reserved_lvs is not None or
729 38f9d2cf Guido Trotter
          opts.master_netdev is not None or
730 b883637f René Nussbaumer
          opts.prealloc_wipe_disks is not None):
731 3a24c527 Iustin Pop
    ToStderr("Please give at least one of the parameters.")
732 90b6aa3a Manuel Franceschini
    return 1
733 90b6aa3a Manuel Franceschini
734 90b6aa3a Manuel Franceschini
  vg_name = opts.vg_name
735 90b6aa3a Manuel Franceschini
  if not opts.lvm_storage and opts.vg_name:
736 6d4a1656 Michael Hanselmann
    ToStderr("Options --no-lvm-storage and --vg-name conflict.")
737 90b6aa3a Manuel Franceschini
    return 1
738 6d4a1656 Michael Hanselmann
739 6d4a1656 Michael Hanselmann
  if not opts.lvm_storage:
740 6d4a1656 Michael Hanselmann
    vg_name = ""
741 90b6aa3a Manuel Franceschini
742 ed14ed48 Luca Bigliardi
  drbd_helper = opts.drbd_helper
743 ed14ed48 Luca Bigliardi
  if not opts.drbd_storage and opts.drbd_helper:
744 ed14ed48 Luca Bigliardi
    ToStderr("Options --no-drbd-storage and --drbd-usermode-helper conflict.")
745 ed14ed48 Luca Bigliardi
    return 1
746 ed14ed48 Luca Bigliardi
747 ed14ed48 Luca Bigliardi
  if not opts.drbd_storage:
748 ed14ed48 Luca Bigliardi
    drbd_helper = ""
749 ed14ed48 Luca Bigliardi
750 779c15bb Iustin Pop
  hvlist = opts.enabled_hypervisors
751 779c15bb Iustin Pop
  if hvlist is not None:
752 779c15bb Iustin Pop
    hvlist = hvlist.split(",")
753 779c15bb Iustin Pop
754 f8e7ddca Guido Trotter
  # a list of (name, dict) we can pass directly to dict() (or [])
755 f8e7ddca Guido Trotter
  hvparams = dict(opts.hvparams)
756 f4ad2ef0 Iustin Pop
  for hv_params in hvparams.values():
757 a5728081 Guido Trotter
    utils.ForceDictType(hv_params, constants.HVS_PARAMETER_TYPES)
758 779c15bb Iustin Pop
759 779c15bb Iustin Pop
  beparams = opts.beparams
760 a5728081 Guido Trotter
  utils.ForceDictType(beparams, constants.BES_PARAMETER_TYPES)
761 779c15bb Iustin Pop
762 5af3da74 Guido Trotter
  nicparams = opts.nicparams
763 5af3da74 Guido Trotter
  utils.ForceDictType(nicparams, constants.NICS_PARAMETER_TYPES)
764 5af3da74 Guido Trotter
765 6204ee71 René Nussbaumer
  ndparams = opts.ndparams
766 6204ee71 René Nussbaumer
  if ndparams is not None:
767 6204ee71 René Nussbaumer
    utils.ForceDictType(ndparams, constants.NDS_PARAMETER_TYPES)
768 1338f2b4 Balazs Lecz
769 3953242f Iustin Pop
  mnh = opts.maintain_node_health
770 3953242f Iustin Pop
771 1338f2b4 Balazs Lecz
  uid_pool = opts.uid_pool
772 1338f2b4 Balazs Lecz
  if uid_pool is not None:
773 1338f2b4 Balazs Lecz
    uid_pool = uidpool.ParseUidPool(uid_pool)
774 1338f2b4 Balazs Lecz
775 fdad8c4d Balazs Lecz
  add_uids = opts.add_uids
776 fdad8c4d Balazs Lecz
  if add_uids is not None:
777 fdad8c4d Balazs Lecz
    add_uids = uidpool.ParseUidPool(add_uids)
778 fdad8c4d Balazs Lecz
779 fdad8c4d Balazs Lecz
  remove_uids = opts.remove_uids
780 fdad8c4d Balazs Lecz
  if remove_uids is not None:
781 fdad8c4d Balazs Lecz
    remove_uids = uidpool.ParseUidPool(remove_uids)
782 fdad8c4d Balazs Lecz
783 f38ea602 Iustin Pop
  if opts.reserved_lvs is not None:
784 f38ea602 Iustin Pop
    if opts.reserved_lvs == "":
785 f38ea602 Iustin Pop
      opts.reserved_lvs = []
786 f38ea602 Iustin Pop
    else:
787 f38ea602 Iustin Pop
      opts.reserved_lvs = utils.UnescapeAndSplit(opts.reserved_lvs, sep=",")
788 f38ea602 Iustin Pop
789 b8a8fbe1 Guido Trotter
  op = opcodes.OpSetClusterParams(vg_name=vg_name,
790 ed14ed48 Luca Bigliardi
                                  drbd_helper=drbd_helper,
791 779c15bb Iustin Pop
                                  enabled_hypervisors=hvlist,
792 779c15bb Iustin Pop
                                  hvparams=hvparams,
793 17463d22 René Nussbaumer
                                  os_hvp=None,
794 4b7735f9 Iustin Pop
                                  beparams=beparams,
795 5af3da74 Guido Trotter
                                  nicparams=nicparams,
796 6204ee71 René Nussbaumer
                                  ndparams=ndparams,
797 3953242f Iustin Pop
                                  candidate_pool_size=opts.candidate_pool_size,
798 1338f2b4 Balazs Lecz
                                  maintain_node_health=mnh,
799 fdad8c4d Balazs Lecz
                                  uid_pool=uid_pool,
800 fdad8c4d Balazs Lecz
                                  add_uids=add_uids,
801 bf4af505 Apollon Oikonomopoulos
                                  remove_uids=remove_uids,
802 f38ea602 Iustin Pop
                                  default_iallocator=opts.default_iallocator,
803 b883637f René Nussbaumer
                                  prealloc_wipe_disks=opts.prealloc_wipe_disks,
804 38f9d2cf Guido Trotter
                                  master_netdev=opts.master_netdev,
805 f38ea602 Iustin Pop
                                  reserved_lvs=opts.reserved_lvs)
806 400ca2f7 Iustin Pop
  SubmitOpCode(op, opts=opts)
807 90b6aa3a Manuel Franceschini
  return 0
808 90b6aa3a Manuel Franceschini
809 90b6aa3a Manuel Franceschini
810 3ccafd0e Iustin Pop
def QueueOps(opts, args):
811 3ccafd0e Iustin Pop
  """Queue operations.
812 3ccafd0e Iustin Pop

813 469ee405 Iustin Pop
  @param opts: the command line options selected by the user
814 469ee405 Iustin Pop
  @type args: list
815 469ee405 Iustin Pop
  @param args: should contain only one element, the subcommand
816 469ee405 Iustin Pop
  @rtype: int
817 469ee405 Iustin Pop
  @return: the desired exit code
818 469ee405 Iustin Pop

819 3ccafd0e Iustin Pop
  """
820 3ccafd0e Iustin Pop
  command = args[0]
821 3ccafd0e Iustin Pop
  client = GetClient()
822 3ccafd0e Iustin Pop
  if command in ("drain", "undrain"):
823 3ccafd0e Iustin Pop
    drain_flag = command == "drain"
824 3ccafd0e Iustin Pop
    client.SetQueueDrainFlag(drain_flag)
825 3ccafd0e Iustin Pop
  elif command == "info":
826 3ccafd0e Iustin Pop
    result = client.QueryConfigValues(["drain_flag"])
827 3ccafd0e Iustin Pop
    if result[0]:
828 3a24c527 Iustin Pop
      val = "set"
829 3ccafd0e Iustin Pop
    else:
830 3a24c527 Iustin Pop
      val = "unset"
831 3a24c527 Iustin Pop
    ToStdout("The drain flag is %s" % val)
832 2e668b38 Guido Trotter
  else:
833 debac808 Iustin Pop
    raise errors.OpPrereqError("Command '%s' is not valid." % command,
834 debac808 Iustin Pop
                               errors.ECODE_INVAL)
835 2e668b38 Guido Trotter
836 3ccafd0e Iustin Pop
  return 0
837 3ccafd0e Iustin Pop
838 95b2e626 Michael Hanselmann
839 28b498cd Michael Hanselmann
def _ShowWatcherPause(until):
840 28b498cd Michael Hanselmann
  if until is None or until < time.time():
841 28b498cd Michael Hanselmann
    ToStdout("The watcher is not paused.")
842 28b498cd Michael Hanselmann
  else:
843 28b498cd Michael Hanselmann
    ToStdout("The watcher is paused until %s.", time.ctime(until))
844 28b498cd Michael Hanselmann
845 28b498cd Michael Hanselmann
846 95b2e626 Michael Hanselmann
def WatcherOps(opts, args):
847 95b2e626 Michael Hanselmann
  """Watcher operations.
848 95b2e626 Michael Hanselmann

849 95b2e626 Michael Hanselmann
  @param opts: the command line options selected by the user
850 95b2e626 Michael Hanselmann
  @type args: list
851 95b2e626 Michael Hanselmann
  @param args: should contain only one element, the subcommand
852 95b2e626 Michael Hanselmann
  @rtype: int
853 95b2e626 Michael Hanselmann
  @return: the desired exit code
854 95b2e626 Michael Hanselmann

855 95b2e626 Michael Hanselmann
  """
856 95b2e626 Michael Hanselmann
  command = args[0]
857 95b2e626 Michael Hanselmann
  client = GetClient()
858 95b2e626 Michael Hanselmann
859 95b2e626 Michael Hanselmann
  if command == "continue":
860 95b2e626 Michael Hanselmann
    client.SetWatcherPause(None)
861 28b498cd Michael Hanselmann
    ToStdout("The watcher is no longer paused.")
862 95b2e626 Michael Hanselmann
863 95b2e626 Michael Hanselmann
  elif command == "pause":
864 95b2e626 Michael Hanselmann
    if len(args) < 2:
865 debac808 Iustin Pop
      raise errors.OpPrereqError("Missing pause duration", errors.ECODE_INVAL)
866 95b2e626 Michael Hanselmann
867 28b498cd Michael Hanselmann
    result = client.SetWatcherPause(time.time() + ParseTimespec(args[1]))
868 28b498cd Michael Hanselmann
    _ShowWatcherPause(result)
869 95b2e626 Michael Hanselmann
870 95b2e626 Michael Hanselmann
  elif command == "info":
871 95b2e626 Michael Hanselmann
    result = client.QueryConfigValues(["watcher_pause"])
872 cac599f1 Michael Hanselmann
    _ShowWatcherPause(result[0])
873 95b2e626 Michael Hanselmann
874 95b2e626 Michael Hanselmann
  else:
875 debac808 Iustin Pop
    raise errors.OpPrereqError("Command '%s' is not valid." % command,
876 debac808 Iustin Pop
                               errors.ECODE_INVAL)
877 95b2e626 Michael Hanselmann
878 95b2e626 Michael Hanselmann
  return 0
879 95b2e626 Michael Hanselmann
880 95b2e626 Michael Hanselmann
881 a8083063 Iustin Pop
commands = {
882 6ea815cf Iustin Pop
  'init': (
883 6ea815cf Iustin Pop
    InitCluster, [ArgHost(min=1, max=1)],
884 064c21f8 Iustin Pop
    [BACKEND_OPT, CP_SIZE_OPT, ENABLED_HV_OPT, GLOBAL_FILEDIR_OPT,
885 6ea815cf Iustin Pop
     HVLIST_OPT, MAC_PREFIX_OPT, MASTER_NETDEV_OPT, NIC_PARAMS_OPT,
886 b989b9d9 Ken Wehr
     NOLVM_STORAGE_OPT, NOMODIFY_ETCHOSTS_OPT, NOMODIFY_SSH_SETUP_OPT,
887 39b0f0c2 Balazs Lecz
     SECONDARY_IP_OPT, VG_NAME_OPT, MAINTAIN_NODE_HEALTH_OPT,
888 bf4af505 Apollon Oikonomopoulos
     UIDPOOL_OPT, DRBD_HELPER_OPT, NODRBD_STORAGE_OPT,
889 6204ee71 René Nussbaumer
     DEFAULT_IALLOCATOR_OPT, PRIMARY_IP_VERSION_OPT, PREALLOC_WIPE_DISKS_OPT,
890 6204ee71 René Nussbaumer
     NODE_PARAMS_OPT],
891 6ea815cf Iustin Pop
    "[opts...] <cluster_name>", "Initialises a new cluster configuration"),
892 6ea815cf Iustin Pop
  'destroy': (
893 064c21f8 Iustin Pop
    DestroyCluster, ARGS_NONE, [YES_DOIT_OPT],
894 6ea815cf Iustin Pop
    "", "Destroy cluster"),
895 6ea815cf Iustin Pop
  'rename': (
896 6ea815cf Iustin Pop
    RenameCluster, [ArgHost(min=1, max=1)],
897 db5a8a2d Iustin Pop
    [FORCE_OPT, DRY_RUN_OPT],
898 6ea815cf Iustin Pop
    "<new_name>",
899 6ea815cf Iustin Pop
    "Renames the cluster"),
900 6ea815cf Iustin Pop
  'redist-conf': (
901 aa06f8c6 Michael Hanselmann
    RedistributeConfig, ARGS_NONE, [SUBMIT_OPT, DRY_RUN_OPT, PRIORITY_OPT],
902 6ea815cf Iustin Pop
    "", "Forces a push of the configuration file and ssconf files"
903 6ea815cf Iustin Pop
    " to the nodes in the cluster"),
904 6ea815cf Iustin Pop
  'verify': (
905 6ea815cf Iustin Pop
    VerifyCluster, ARGS_NONE,
906 db5a8a2d Iustin Pop
    [VERBOSE_OPT, DEBUG_SIMERR_OPT, ERROR_CODES_OPT, NONPLUS1_OPT,
907 aa06f8c6 Michael Hanselmann
     DRY_RUN_OPT, PRIORITY_OPT],
908 6ea815cf Iustin Pop
    "", "Does a check on the cluster configuration"),
909 6ea815cf Iustin Pop
  'verify-disks': (
910 aa06f8c6 Michael Hanselmann
    VerifyDisks, ARGS_NONE, [PRIORITY_OPT],
911 6ea815cf Iustin Pop
    "", "Does a check on the cluster disk status"),
912 6ea815cf Iustin Pop
  'repair-disk-sizes': (
913 aa06f8c6 Michael Hanselmann
    RepairDiskSizes, ARGS_MANY_INSTANCES, [DRY_RUN_OPT, PRIORITY_OPT],
914 6ea815cf Iustin Pop
    "", "Updates mismatches in recorded disk sizes"),
915 c28502b1 Iustin Pop
  'master-failover': (
916 064c21f8 Iustin Pop
    MasterFailover, ARGS_NONE, [NOVOTING_OPT],
917 6ea815cf Iustin Pop
    "", "Makes the current node the master"),
918 4404ffad Iustin Pop
  'master-ping': (
919 4404ffad Iustin Pop
    MasterPing, ARGS_NONE, [],
920 4404ffad Iustin Pop
    "", "Checks if the master is alive"),
921 6ea815cf Iustin Pop
  'version': (
922 064c21f8 Iustin Pop
    ShowClusterVersion, ARGS_NONE, [],
923 6ea815cf Iustin Pop
    "", "Shows the cluster version"),
924 6ea815cf Iustin Pop
  'getmaster': (
925 064c21f8 Iustin Pop
    ShowClusterMaster, ARGS_NONE, [],
926 6ea815cf Iustin Pop
    "", "Shows the cluster master"),
927 6ea815cf Iustin Pop
  'copyfile': (
928 6ea815cf Iustin Pop
    ClusterCopyFile, [ArgFile(min=1, max=1)],
929 74adc100 Iustin Pop
    [NODE_LIST_OPT, USE_REPL_NET_OPT],
930 6ea815cf Iustin Pop
    "[-n node...] <filename>", "Copies a file to all (or only some) nodes"),
931 6ea815cf Iustin Pop
  'command': (
932 6ea815cf Iustin Pop
    RunClusterCommand, [ArgCommand(min=1)],
933 064c21f8 Iustin Pop
    [NODE_LIST_OPT],
934 6ea815cf Iustin Pop
    "[-n node...] <command>", "Runs a command on all (or only some) nodes"),
935 6ea815cf Iustin Pop
  'info': (
936 d729e03a Guido Trotter
    ShowClusterConfig, ARGS_NONE, [ROMAN_OPT],
937 d729e03a Guido Trotter
    "[--roman]", "Show cluster configuration"),
938 6ea815cf Iustin Pop
  'list-tags': (
939 064c21f8 Iustin Pop
    ListTags, ARGS_NONE, [], "", "List the tags of the cluster"),
940 6ea815cf Iustin Pop
  'add-tags': (
941 aa06f8c6 Michael Hanselmann
    AddTags, [ArgUnknown()], [TAG_SRC_OPT, PRIORITY_OPT],
942 6ea815cf Iustin Pop
    "tag...", "Add tags to the cluster"),
943 6ea815cf Iustin Pop
  'remove-tags': (
944 aa06f8c6 Michael Hanselmann
    RemoveTags, [ArgUnknown()], [TAG_SRC_OPT, PRIORITY_OPT],
945 6ea815cf Iustin Pop
    "tag...", "Remove tags from the cluster"),
946 6ea815cf Iustin Pop
  'search-tags': (
947 aa06f8c6 Michael Hanselmann
    SearchTags, [ArgUnknown(min=1, max=1)], [PRIORITY_OPT], "",
948 aa06f8c6 Michael Hanselmann
    "Searches the tags on all objects on"
949 6ea815cf Iustin Pop
    " the cluster for a given pattern (regex)"),
950 6ea815cf Iustin Pop
  'queue': (
951 6ea815cf Iustin Pop
    QueueOps,
952 6ea815cf Iustin Pop
    [ArgChoice(min=1, max=1, choices=["drain", "undrain", "info"])],
953 064c21f8 Iustin Pop
    [], "drain|undrain|info", "Change queue properties"),
954 6ea815cf Iustin Pop
  'watcher': (
955 6ea815cf Iustin Pop
    WatcherOps,
956 6ea815cf Iustin Pop
    [ArgChoice(min=1, max=1, choices=["pause", "continue", "info"]),
957 6ea815cf Iustin Pop
     ArgSuggest(min=0, max=1, choices=["30m", "1h", "4h"])],
958 064c21f8 Iustin Pop
    [],
959 6ea815cf Iustin Pop
    "{pause <timespec>|continue|info}", "Change watcher properties"),
960 6ea815cf Iustin Pop
  'modify': (
961 6ea815cf Iustin Pop
    SetClusterParams, ARGS_NONE,
962 38f9d2cf Guido Trotter
    [BACKEND_OPT, CP_SIZE_OPT, ENABLED_HV_OPT, HVLIST_OPT, MASTER_NETDEV_OPT,
963 1338f2b4 Balazs Lecz
     NIC_PARAMS_OPT, NOLVM_STORAGE_OPT, VG_NAME_OPT, MAINTAIN_NODE_HEALTH_OPT,
964 ed14ed48 Luca Bigliardi
     UIDPOOL_OPT, ADD_UIDS_OPT, REMOVE_UIDS_OPT, DRBD_HELPER_OPT,
965 db5a8a2d Iustin Pop
     NODRBD_STORAGE_OPT, DEFAULT_IALLOCATOR_OPT, RESERVED_LVS_OPT,
966 6204ee71 René Nussbaumer
     DRY_RUN_OPT, PRIORITY_OPT, PREALLOC_WIPE_DISKS_OPT, NODE_PARAMS_OPT],
967 6ea815cf Iustin Pop
    "[opts...]",
968 6ea815cf Iustin Pop
    "Alters the parameters of the cluster"),
969 6d4a1656 Michael Hanselmann
  "renew-crypto": (
970 6d4a1656 Michael Hanselmann
    RenewCrypto, ARGS_NONE,
971 6b7d5878 Michael Hanselmann
    [NEW_CLUSTER_CERT_OPT, NEW_RAPI_CERT_OPT, RAPI_CERT_OPT,
972 3db3eb2a Michael Hanselmann
     NEW_CONFD_HMAC_KEY_OPT, FORCE_OPT,
973 3db3eb2a Michael Hanselmann
     NEW_CLUSTER_DOMAIN_SECRET_OPT, CLUSTER_DOMAIN_SECRET_OPT],
974 6d4a1656 Michael Hanselmann
    "[opts...]",
975 6d4a1656 Michael Hanselmann
    "Renews cluster certificates, keys and secrets"),
976 a8083063 Iustin Pop
  }
977 a8083063 Iustin Pop
978 6d4a1656 Michael Hanselmann
979 c28502b1 Iustin Pop
#: dictionary with aliases for commands
980 c28502b1 Iustin Pop
aliases = {
981 c28502b1 Iustin Pop
  'masterfailover': 'master-failover',
982 c28502b1 Iustin Pop
}
983 c28502b1 Iustin Pop
984 c28502b1 Iustin Pop
985 7b3e7d41 Michael Hanselmann
def Main():
986 7b3e7d41 Michael Hanselmann
  return GenericMain(commands, override={"tag_type": constants.TAG_CLUSTER},
987 7b3e7d41 Michael Hanselmann
                     aliases=aliases)