Statistics
| Branch: | Tag: | Revision:

root / lib / client / gnt_cluster.py @ 6204ee71

History | View | Annotate | Download (30.5 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 ea3a925f Alexander Schreiber
  hvlist = opts.enabled_hypervisors
74 383a3591 Iustin Pop
  if hvlist is None:
75 383a3591 Iustin Pop
    hvlist = constants.DEFAULT_ENABLED_HYPERVISOR
76 066f465d Guido Trotter
  hvlist = hvlist.split(",")
77 ea3a925f Alexander Schreiber
78 f8e7ddca Guido Trotter
  hvparams = dict(opts.hvparams)
79 ea3a925f Alexander Schreiber
  beparams = opts.beparams
80 b6a30b0d Guido Trotter
  nicparams = opts.nicparams
81 ea3a925f Alexander Schreiber
82 ea3a925f Alexander Schreiber
  # prepare beparams dict
83 d3cfe525 Guido Trotter
  beparams = objects.FillDict(constants.BEC_DEFAULTS, beparams)
84 a5728081 Guido Trotter
  utils.ForceDictType(beparams, constants.BES_PARAMETER_TYPES)
85 ea3a925f Alexander Schreiber
86 b6a30b0d Guido Trotter
  # prepare nicparams dict
87 b6a30b0d Guido Trotter
  nicparams = objects.FillDict(constants.NICC_DEFAULTS, nicparams)
88 b6a30b0d Guido Trotter
  utils.ForceDictType(nicparams, constants.NICS_PARAMETER_TYPES)
89 b6a30b0d Guido Trotter
90 6204ee71 René Nussbaumer
  # prepare ndparams dict
91 6204ee71 René Nussbaumer
  if opts.ndparams is None:
92 6204ee71 René Nussbaumer
    ndparams = dict(constants.NDC_DEFAULTS)
93 6204ee71 René Nussbaumer
  else:
94 6204ee71 René Nussbaumer
    ndparams = objects.FillDict(constants.NDC_DEFAULTS, opts.ndparams)
95 6204ee71 René Nussbaumer
    utils.ForceDictType(ndparams, constants.NDS_PARAMETER_TYPES)
96 6204ee71 René Nussbaumer
97 ea3a925f Alexander Schreiber
  # prepare hvparams dict
98 ea3a925f Alexander Schreiber
  for hv in constants.HYPER_TYPES:
99 ea3a925f Alexander Schreiber
    if hv not in hvparams:
100 ea3a925f Alexander Schreiber
      hvparams[hv] = {}
101 d3cfe525 Guido Trotter
    hvparams[hv] = objects.FillDict(constants.HVC_DEFAULTS[hv], hvparams[hv])
102 a5728081 Guido Trotter
    utils.ForceDictType(hvparams[hv], constants.HVS_PARAMETER_TYPES)
103 ea3a925f Alexander Schreiber
104 e32df528 Iustin Pop
  if opts.candidate_pool_size is None:
105 e32df528 Iustin Pop
    opts.candidate_pool_size = constants.MASTER_POOL_SIZE_DEFAULT
106 e32df528 Iustin Pop
107 e3646f22 Iustin Pop
  if opts.mac_prefix is None:
108 e3646f22 Iustin Pop
    opts.mac_prefix = constants.DEFAULT_MAC_PREFIX
109 e3646f22 Iustin Pop
110 39b0f0c2 Balazs Lecz
  uid_pool = opts.uid_pool
111 39b0f0c2 Balazs Lecz
  if uid_pool is not None:
112 39b0f0c2 Balazs Lecz
    uid_pool = uidpool.ParseUidPool(uid_pool)
113 39b0f0c2 Balazs Lecz
114 b883637f René Nussbaumer
  if opts.prealloc_wipe_disks is None:
115 b883637f René Nussbaumer
    opts.prealloc_wipe_disks = False
116 b883637f René Nussbaumer
117 e7323b5e Manuel Franceschini
  try:
118 e7323b5e Manuel Franceschini
    primary_ip_version = int(opts.primary_ip_version)
119 e7323b5e Manuel Franceschini
  except (ValueError, TypeError), err:
120 e7323b5e Manuel Franceschini
    ToStderr("Invalid primary ip version value: %s" % str(err))
121 e7323b5e Manuel Franceschini
    return 1
122 e7323b5e Manuel Franceschini
123 a0c9f010 Michael Hanselmann
  bootstrap.InitCluster(cluster_name=args[0],
124 a0c9f010 Michael Hanselmann
                        secondary_ip=opts.secondary_ip,
125 a0c9f010 Michael Hanselmann
                        vg_name=vg_name,
126 a0c9f010 Michael Hanselmann
                        mac_prefix=opts.mac_prefix,
127 a0c9f010 Michael Hanselmann
                        master_netdev=opts.master_netdev,
128 ea3a925f Alexander Schreiber
                        file_storage_dir=opts.file_storage_dir,
129 ea3a925f Alexander Schreiber
                        enabled_hypervisors=hvlist,
130 ea3a925f Alexander Schreiber
                        hvparams=hvparams,
131 ce735215 Guido Trotter
                        beparams=beparams,
132 b6a30b0d Guido Trotter
                        nicparams=nicparams,
133 6204ee71 René Nussbaumer
                        ndparams=ndparams,
134 ce735215 Guido Trotter
                        candidate_pool_size=opts.candidate_pool_size,
135 b86a6bcd Guido Trotter
                        modify_etc_hosts=opts.modify_etc_hosts,
136 b989b9d9 Ken Wehr
                        modify_ssh_setup=opts.modify_ssh_setup,
137 3953242f Iustin Pop
                        maintain_node_health=opts.maintain_node_health,
138 ed14ed48 Luca Bigliardi
                        drbd_helper=drbd_helper,
139 39b0f0c2 Balazs Lecz
                        uid_pool=uid_pool,
140 bf4af505 Apollon Oikonomopoulos
                        default_iallocator=opts.default_iallocator,
141 e7323b5e Manuel Franceschini
                        primary_ip_version=primary_ip_version,
142 b18ecea2 René Nussbaumer
                        prealloc_wipe_disks=opts.prealloc_wipe_disks,
143 ce735215 Guido Trotter
                        )
144 3552cd2e Luca Bigliardi
  op = opcodes.OpPostInitCluster()
145 400ca2f7 Iustin Pop
  SubmitOpCode(op, opts=opts)
146 a8083063 Iustin Pop
  return 0
147 a8083063 Iustin Pop
148 a8083063 Iustin Pop
149 4331f6cd Michael Hanselmann
@UsesRPC
150 a8083063 Iustin Pop
def DestroyCluster(opts, args):
151 a8083063 Iustin Pop
  """Destroy the cluster.
152 a8083063 Iustin Pop

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

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

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

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

209 afee0879 Iustin Pop
  @param opts: the command line options selected by the user
210 afee0879 Iustin Pop
  @type args: list
211 afee0879 Iustin Pop
  @param args: empty list
212 afee0879 Iustin Pop
  @rtype: int
213 afee0879 Iustin Pop
  @return: the desired exit code
214 afee0879 Iustin Pop

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

224 469ee405 Iustin Pop
  @param opts: the command line options selected by the user
225 469ee405 Iustin Pop
  @type args: list
226 469ee405 Iustin Pop
  @param args: should be an empty list
227 469ee405 Iustin Pop
  @rtype: int
228 469ee405 Iustin Pop
  @return: the desired exit code
229 a8083063 Iustin Pop

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

244 469ee405 Iustin Pop
  @param opts: the command line options selected by the user
245 469ee405 Iustin Pop
  @type args: list
246 469ee405 Iustin Pop
  @param args: should be an empty list
247 469ee405 Iustin Pop
  @rtype: int
248 469ee405 Iustin Pop
  @return: the desired exit code
249 a8083063 Iustin Pop

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

259 1094acda Guido Trotter
  @type paramsdict: dict of dicts
260 1094acda Guido Trotter
  @param paramsdict: {group: {param: value, ...}, ...}
261 664a9d73 René Nussbaumer
  @type level: int
262 664a9d73 René Nussbaumer
  @param level: Level of indention
263 1094acda Guido Trotter

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

279 469ee405 Iustin Pop
  @param opts: the command line options selected by the user
280 469ee405 Iustin Pop
  @type args: list
281 469ee405 Iustin Pop
  @param args: should be an empty list
282 469ee405 Iustin Pop
  @rtype: int
283 469ee405 Iustin Pop
  @return: the desired exit code
284 469ee405 Iustin Pop

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

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

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

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

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

421 469ee405 Iustin Pop
  @param opts: the command line options selected by the user
422 469ee405 Iustin Pop
  @type args: list
423 469ee405 Iustin Pop
  @param args: should be an empty list
424 469ee405 Iustin Pop
  @rtype: int
425 469ee405 Iustin Pop
  @return: the desired exit code
426 a8083063 Iustin Pop

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

444 469ee405 Iustin Pop
  @param opts: the command line options selected by the user
445 469ee405 Iustin Pop
  @type args: list
446 469ee405 Iustin Pop
  @param args: should be an empty list
447 469ee405 Iustin Pop
  @rtype: int
448 469ee405 Iustin Pop
  @return: the desired exit code
449 f4d4e184 Iustin Pop

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

509 60975797 Iustin Pop
  @param opts: the command line options selected by the user
510 60975797 Iustin Pop
  @type args: list
511 60975797 Iustin Pop
  @param args: optional list of instances to restrict check to
512 60975797 Iustin Pop
  @rtype: int
513 60975797 Iustin Pop
  @return: the desired exit code
514 60975797 Iustin Pop

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

524 a8083063 Iustin Pop
  This command, when run on a non-master node, will cause the current
525 a8083063 Iustin Pop
  master to cease being master, and the non-master to become new
526 a8083063 Iustin Pop
  master.
527 a8083063 Iustin Pop

528 469ee405 Iustin Pop
  @param opts: the command line options selected by the user
529 469ee405 Iustin Pop
  @type args: list
530 469ee405 Iustin Pop
  @param args: should be an empty list
531 469ee405 Iustin Pop
  @rtype: int
532 469ee405 Iustin Pop
  @return: the desired exit code
533 469ee405 Iustin Pop

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

549 4404ffad Iustin Pop
  @param opts: the command line options selected by the user
550 4404ffad Iustin Pop
  @type args: list
551 4404ffad Iustin Pop
  @param args: should be an empty list
552 4404ffad Iustin Pop
  @rtype: int
553 4404ffad Iustin Pop
  @return: the desired exit code
554 4404ffad Iustin Pop

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

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

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

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

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

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

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

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

807 469ee405 Iustin Pop
  @param opts: the command line options selected by the user
808 469ee405 Iustin Pop
  @type args: list
809 469ee405 Iustin Pop
  @param args: should contain only one element, the subcommand
810 469ee405 Iustin Pop
  @rtype: int
811 469ee405 Iustin Pop
  @return: the desired exit code
812 469ee405 Iustin Pop

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

843 95b2e626 Michael Hanselmann
  @param opts: the command line options selected by the user
844 95b2e626 Michael Hanselmann
  @type args: list
845 95b2e626 Michael Hanselmann
  @param args: should contain only one element, the subcommand
846 95b2e626 Michael Hanselmann
  @rtype: int
847 95b2e626 Michael Hanselmann
  @return: the desired exit code
848 95b2e626 Michael Hanselmann

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