Statistics
| Branch: | Tag: | Revision:

root / scripts / gnt-cluster @ b59252fe

History | View | Annotate | Download (23.5 kB)

1 a8083063 Iustin Pop
#!/usr/bin/python
2 a8083063 Iustin Pop
#
3 a8083063 Iustin Pop
4 a8083063 Iustin Pop
# Copyright (C) 2006, 2007 Google Inc.
5 a8083063 Iustin Pop
#
6 a8083063 Iustin Pop
# This program is free software; you can redistribute it and/or modify
7 a8083063 Iustin Pop
# it under the terms of the GNU General Public License as published by
8 a8083063 Iustin Pop
# the Free Software Foundation; either version 2 of the License, or
9 a8083063 Iustin Pop
# (at your option) any later version.
10 a8083063 Iustin Pop
#
11 a8083063 Iustin Pop
# This program is distributed in the hope that it will be useful, but
12 a8083063 Iustin Pop
# WITHOUT ANY WARRANTY; without even the implied warranty of
13 a8083063 Iustin Pop
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 a8083063 Iustin Pop
# General Public License for more details.
15 a8083063 Iustin Pop
#
16 a8083063 Iustin Pop
# You should have received a copy of the GNU General Public License
17 a8083063 Iustin Pop
# along with this program; if not, write to the Free Software
18 a8083063 Iustin Pop
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 a8083063 Iustin Pop
# 02110-1301, USA.
20 a8083063 Iustin Pop
21 a8083063 Iustin Pop
22 2f79bd34 Iustin Pop
# pylint: disable-msg=W0401,W0614
23 2f79bd34 Iustin Pop
# W0401: Wildcard import ganeti.cli
24 2f79bd34 Iustin Pop
# W0614: Unused import %s from wildcard import (since we need cli)
25 2f79bd34 Iustin Pop
26 a8083063 Iustin Pop
import sys
27 a8083063 Iustin Pop
from optparse import make_option
28 b3989551 Iustin Pop
import os.path
29 a8083063 Iustin Pop
30 a8083063 Iustin Pop
from ganeti.cli import *
31 a8083063 Iustin Pop
from ganeti import opcodes
32 c2a62a33 Michael Hanselmann
from ganeti import constants
33 f4d4e184 Iustin Pop
from ganeti import errors
34 b63ed789 Iustin Pop
from ganeti import utils
35 a0c9f010 Michael Hanselmann
from ganeti import bootstrap
36 b3989551 Iustin Pop
from ganeti import ssh
37 a8083063 Iustin Pop
38 a8083063 Iustin Pop
39 4331f6cd Michael Hanselmann
@UsesRPC
40 a8083063 Iustin Pop
def InitCluster(opts, args):
41 a8083063 Iustin Pop
  """Initialize the cluster.
42 a8083063 Iustin Pop
43 469ee405 Iustin Pop
  @param opts: the command line options selected by the user
44 469ee405 Iustin Pop
  @type args: list
45 469ee405 Iustin Pop
  @param args: should contain only one element, the desired
46 469ee405 Iustin Pop
      cluster name
47 469ee405 Iustin Pop
  @rtype: int
48 469ee405 Iustin Pop
  @return: the desired exit code
49 a8083063 Iustin Pop
50 a8083063 Iustin Pop
  """
51 90b6aa3a Manuel Franceschini
  if not opts.lvm_storage and opts.vg_name:
52 3a24c527 Iustin Pop
    ToStderr("Options --no-lvm-storage and --vg-name conflict.")
53 90b6aa3a Manuel Franceschini
    return 1
54 90b6aa3a Manuel Franceschini
55 90b6aa3a Manuel Franceschini
  vg_name = opts.vg_name
56 90b6aa3a Manuel Franceschini
  if opts.lvm_storage and not opts.vg_name:
57 90b6aa3a Manuel Franceschini
    vg_name = constants.DEFAULT_VG
58 90b6aa3a Manuel Franceschini
59 ea3a925f Alexander Schreiber
  hvlist = opts.enabled_hypervisors
60 ea3a925f Alexander Schreiber
  if hvlist is not None:
61 ea3a925f Alexander Schreiber
    hvlist = hvlist.split(",")
62 ea3a925f Alexander Schreiber
  else:
63 8f348e36 Guido Trotter
    hvlist = [opts.default_hypervisor]
64 02691904 Alexander Schreiber
65 02691904 Alexander Schreiber
  # avoid an impossible situation
66 8f348e36 Guido Trotter
  if opts.default_hypervisor not in hvlist:
67 8f348e36 Guido Trotter
    ToStderr("The default hypervisor requested (%s) is not"
68 8f348e36 Guido Trotter
             " within the enabled hypervisor list (%s)" %
69 8f348e36 Guido Trotter
             (opts.default_hypervisor, hvlist))
70 8f348e36 Guido Trotter
    return 1
71 ea3a925f Alexander Schreiber
72 f8e7ddca Guido Trotter
  hvparams = dict(opts.hvparams)
73 ea3a925f Alexander Schreiber
74 ea3a925f Alexander Schreiber
  beparams = opts.beparams
75 ea3a925f Alexander Schreiber
  # check for invalid parameters
76 ea3a925f Alexander Schreiber
  for parameter in beparams:
77 ea3a925f Alexander Schreiber
    if parameter not in constants.BES_PARAMETERS:
78 1f9611b1 Alexander Schreiber
      ToStderr("Invalid backend parameter: %s", parameter)
79 ea3a925f Alexander Schreiber
      return 1
80 ea3a925f Alexander Schreiber
81 ea3a925f Alexander Schreiber
  # prepare beparams dict
82 ea3a925f Alexander Schreiber
  for parameter in constants.BES_PARAMETERS:
83 ea3a925f Alexander Schreiber
    if parameter not in beparams:
84 ea3a925f Alexander Schreiber
      beparams[parameter] = constants.BEC_DEFAULTS[parameter]
85 a5728081 Guido Trotter
  utils.ForceDictType(beparams, constants.BES_PARAMETER_TYPES)
86 ea3a925f Alexander Schreiber
87 ea3a925f Alexander Schreiber
  # prepare hvparams dict
88 ea3a925f Alexander Schreiber
  for hv in constants.HYPER_TYPES:
89 ea3a925f Alexander Schreiber
    if hv not in hvparams:
90 ea3a925f Alexander Schreiber
      hvparams[hv] = {}
91 ea3a925f Alexander Schreiber
    for parameter in constants.HVC_DEFAULTS[hv]:
92 ea3a925f Alexander Schreiber
      if parameter not in hvparams[hv]:
93 ea3a925f Alexander Schreiber
        hvparams[hv][parameter] = constants.HVC_DEFAULTS[hv][parameter]
94 a5728081 Guido Trotter
    utils.ForceDictType(hvparams[hv], constants.HVS_PARAMETER_TYPES)
95 ea3a925f Alexander Schreiber
96 a0c9f010 Michael Hanselmann
  bootstrap.InitCluster(cluster_name=args[0],
97 a0c9f010 Michael Hanselmann
                        secondary_ip=opts.secondary_ip,
98 a0c9f010 Michael Hanselmann
                        vg_name=vg_name,
99 a0c9f010 Michael Hanselmann
                        mac_prefix=opts.mac_prefix,
100 a0c9f010 Michael Hanselmann
                        def_bridge=opts.def_bridge,
101 a0c9f010 Michael Hanselmann
                        master_netdev=opts.master_netdev,
102 ea3a925f Alexander Schreiber
                        file_storage_dir=opts.file_storage_dir,
103 ea3a925f Alexander Schreiber
                        enabled_hypervisors=hvlist,
104 8f348e36 Guido Trotter
                        default_hypervisor=opts.default_hypervisor,
105 ea3a925f Alexander Schreiber
                        hvparams=hvparams,
106 ce735215 Guido Trotter
                        beparams=beparams,
107 ce735215 Guido Trotter
                        candidate_pool_size=opts.candidate_pool_size,
108 ce735215 Guido Trotter
                        )
109 a8083063 Iustin Pop
  return 0
110 a8083063 Iustin Pop
111 a8083063 Iustin Pop
112 4331f6cd Michael Hanselmann
@UsesRPC
113 a8083063 Iustin Pop
def DestroyCluster(opts, args):
114 a8083063 Iustin Pop
  """Destroy the cluster.
115 a8083063 Iustin Pop
116 469ee405 Iustin Pop
  @param opts: the command line options selected by the user
117 469ee405 Iustin Pop
  @type args: list
118 469ee405 Iustin Pop
  @param args: should be an empty list
119 469ee405 Iustin Pop
  @rtype: int
120 469ee405 Iustin Pop
  @return: the desired exit code
121 098c0958 Michael Hanselmann
122 a8083063 Iustin Pop
  """
123 a8083063 Iustin Pop
  if not opts.yes_do_it:
124 3a24c527 Iustin Pop
    ToStderr("Destroying a cluster is irreversible. If you really want"
125 3a24c527 Iustin Pop
             " destroy this cluster, supply the --yes-do-it option.")
126 a8083063 Iustin Pop
    return 1
127 a8083063 Iustin Pop
128 a8083063 Iustin Pop
  op = opcodes.OpDestroyCluster()
129 140aa4a8 Iustin Pop
  master = SubmitOpCode(op)
130 140aa4a8 Iustin Pop
  # if we reached this, the opcode didn't fail; we can proceed to
131 140aa4a8 Iustin Pop
  # shutdown all the daemons
132 140aa4a8 Iustin Pop
  bootstrap.FinalizeClusterDestroy(master)
133 a8083063 Iustin Pop
  return 0
134 a8083063 Iustin Pop
135 a8083063 Iustin Pop
136 07bd8a51 Iustin Pop
def RenameCluster(opts, args):
137 07bd8a51 Iustin Pop
  """Rename the cluster.
138 07bd8a51 Iustin Pop
139 469ee405 Iustin Pop
  @param opts: the command line options selected by the user
140 469ee405 Iustin Pop
  @type args: list
141 469ee405 Iustin Pop
  @param args: should contain only one element, the new cluster name
142 469ee405 Iustin Pop
  @rtype: int
143 469ee405 Iustin Pop
  @return: the desired exit code
144 07bd8a51 Iustin Pop
145 07bd8a51 Iustin Pop
  """
146 07bd8a51 Iustin Pop
  name = args[0]
147 07bd8a51 Iustin Pop
  if not opts.force:
148 07bd8a51 Iustin Pop
    usertext = ("This will rename the cluster to '%s'. If you are connected"
149 07bd8a51 Iustin Pop
                " over the network to the cluster name, the operation is very"
150 07bd8a51 Iustin Pop
                " dangerous as the IP address will be removed from the node"
151 07bd8a51 Iustin Pop
                " and the change may not go through. Continue?") % name
152 47988778 Iustin Pop
    if not AskUser(usertext):
153 07bd8a51 Iustin Pop
      return 1
154 07bd8a51 Iustin Pop
155 07bd8a51 Iustin Pop
  op = opcodes.OpRenameCluster(name=name)
156 07bd8a51 Iustin Pop
  SubmitOpCode(op)
157 07bd8a51 Iustin Pop
  return 0
158 07bd8a51 Iustin Pop
159 07bd8a51 Iustin Pop
160 afee0879 Iustin Pop
def RedistributeConfig(opts, args):
161 afee0879 Iustin Pop
  """Forces push of the cluster configuration.
162 afee0879 Iustin Pop
163 afee0879 Iustin Pop
  @param opts: the command line options selected by the user
164 afee0879 Iustin Pop
  @type args: list
165 afee0879 Iustin Pop
  @param args: empty list
166 afee0879 Iustin Pop
  @rtype: int
167 afee0879 Iustin Pop
  @return: the desired exit code
168 afee0879 Iustin Pop
169 afee0879 Iustin Pop
  """
170 81a49123 Iustin Pop
  op = opcodes.OpRedistributeConfig()
171 afee0879 Iustin Pop
  SubmitOrSend(op, opts)
172 afee0879 Iustin Pop
  return 0
173 afee0879 Iustin Pop
174 afee0879 Iustin Pop
175 a8083063 Iustin Pop
def ShowClusterVersion(opts, args):
176 a8083063 Iustin Pop
  """Write version of ganeti software to the standard output.
177 a8083063 Iustin Pop
178 469ee405 Iustin Pop
  @param opts: the command line options selected by the user
179 469ee405 Iustin Pop
  @type args: list
180 469ee405 Iustin Pop
  @param args: should be an empty list
181 469ee405 Iustin Pop
  @rtype: int
182 469ee405 Iustin Pop
  @return: the desired exit code
183 a8083063 Iustin Pop
184 a8083063 Iustin Pop
  """
185 2e7b8369 Iustin Pop
  cl = GetClient()
186 2e7b8369 Iustin Pop
  result = cl.QueryClusterInfo()
187 3a24c527 Iustin Pop
  ToStdout("Software version: %s", result["software_version"])
188 3a24c527 Iustin Pop
  ToStdout("Internode protocol: %s", result["protocol_version"])
189 3a24c527 Iustin Pop
  ToStdout("Configuration format: %s", result["config_version"])
190 3a24c527 Iustin Pop
  ToStdout("OS api version: %s", result["os_api_version"])
191 3a24c527 Iustin Pop
  ToStdout("Export interface: %s", result["export_version"])
192 a8083063 Iustin Pop
  return 0
193 a8083063 Iustin Pop
194 a8083063 Iustin Pop
195 a8083063 Iustin Pop
def ShowClusterMaster(opts, args):
196 a8083063 Iustin Pop
  """Write name of master node to the standard output.
197 a8083063 Iustin Pop
198 469ee405 Iustin Pop
  @param opts: the command line options selected by the user
199 469ee405 Iustin Pop
  @type args: list
200 469ee405 Iustin Pop
  @param args: should be an empty list
201 469ee405 Iustin Pop
  @rtype: int
202 469ee405 Iustin Pop
  @return: the desired exit code
203 a8083063 Iustin Pop
204 a8083063 Iustin Pop
  """
205 8eb148ae Iustin Pop
  master = bootstrap.GetMaster()
206 8eb148ae Iustin Pop
  ToStdout(master)
207 a8083063 Iustin Pop
  return 0
208 a8083063 Iustin Pop
209 a8083063 Iustin Pop
210 a8083063 Iustin Pop
def ShowClusterConfig(opts, args):
211 a8083063 Iustin Pop
  """Shows cluster information.
212 a8083063 Iustin Pop
213 469ee405 Iustin Pop
  @param opts: the command line options selected by the user
214 469ee405 Iustin Pop
  @type args: list
215 469ee405 Iustin Pop
  @param args: should be an empty list
216 469ee405 Iustin Pop
  @rtype: int
217 469ee405 Iustin Pop
  @return: the desired exit code
218 469ee405 Iustin Pop
219 a8083063 Iustin Pop
  """
220 2e7b8369 Iustin Pop
  cl = GetClient()
221 2e7b8369 Iustin Pop
  result = cl.QueryClusterInfo()
222 a8083063 Iustin Pop
223 3a24c527 Iustin Pop
  ToStdout("Cluster name: %s", result["name"])
224 a8083063 Iustin Pop
225 3a24c527 Iustin Pop
  ToStdout("Master node: %s", result["master"])
226 a8083063 Iustin Pop
227 3a24c527 Iustin Pop
  ToStdout("Architecture (this node): %s (%s)",
228 3a24c527 Iustin Pop
           result["architecture"][0], result["architecture"][1])
229 a8083063 Iustin Pop
230 02691904 Alexander Schreiber
  ToStdout("Default hypervisor: %s", result["default_hypervisor"])
231 3a24c527 Iustin Pop
  ToStdout("Enabled hypervisors: %s", ", ".join(result["enabled_hypervisors"]))
232 469f88e1 Iustin Pop
233 3a24c527 Iustin Pop
  ToStdout("Hypervisor parameters:")
234 469f88e1 Iustin Pop
  for hv_name, hv_dict in result["hvparams"].items():
235 3a24c527 Iustin Pop
    ToStdout("  - %s:", hv_name)
236 469f88e1 Iustin Pop
    for item, val in hv_dict.iteritems():
237 3a24c527 Iustin Pop
      ToStdout("      %s: %s", item, val)
238 469f88e1 Iustin Pop
239 3a24c527 Iustin Pop
  ToStdout("Cluster parameters:")
240 4b7735f9 Iustin Pop
  ToStdout("  - candidate pool size: %s", result["candidate_pool_size"])
241 a8001106 Guido Trotter
  ToStdout("  - master netdev: %s", result["master_netdev"])
242 a8001106 Guido Trotter
  ToStdout("  - default bridge: %s", result["default_bridge"])
243 a8001106 Guido Trotter
  ToStdout("  - lvm volume group: %s", result["volume_group_name"])
244 a8001106 Guido Trotter
  ToStdout("  - file storage path: %s", result["file_storage_dir"])
245 4b7735f9 Iustin Pop
246 4b7735f9 Iustin Pop
  ToStdout("Default instance parameters:")
247 469f88e1 Iustin Pop
  for gr_name, gr_dict in result["beparams"].items():
248 3a24c527 Iustin Pop
    ToStdout("  - %s:", gr_name)
249 469f88e1 Iustin Pop
    for item, val in gr_dict.iteritems():
250 3a24c527 Iustin Pop
      ToStdout("      %s: %s", item, val)
251 8a12ce45 Iustin Pop
252 a8083063 Iustin Pop
  return 0
253 a8083063 Iustin Pop
254 a8083063 Iustin Pop
255 a8083063 Iustin Pop
def ClusterCopyFile(opts, args):
256 a8083063 Iustin Pop
  """Copy a file from master to some nodes.
257 a8083063 Iustin Pop
258 469ee405 Iustin Pop
  @param opts: the command line options selected by the user
259 469ee405 Iustin Pop
  @type args: list
260 469ee405 Iustin Pop
  @param args: should contain only one element, the path of
261 469ee405 Iustin Pop
      the file to be copied
262 469ee405 Iustin Pop
  @rtype: int
263 469ee405 Iustin Pop
  @return: the desired exit code
264 a8083063 Iustin Pop
265 a8083063 Iustin Pop
  """
266 b3989551 Iustin Pop
  filename = args[0]
267 b3989551 Iustin Pop
  if not os.path.exists(filename):
268 b3989551 Iustin Pop
    raise errors.OpPrereqError("No such filename '%s'" % filename)
269 b3989551 Iustin Pop
270 56bece1f Iustin Pop
  cl = GetClient()
271 56bece1f Iustin Pop
272 b3989551 Iustin Pop
  myname = utils.HostInfo().name
273 b3989551 Iustin Pop
274 56bece1f Iustin Pop
  cluster_name = cl.QueryConfigValues(["cluster_name"])[0]
275 56bece1f Iustin Pop
276 4040a784 Iustin Pop
  results = GetOnlineNodes(nodes=opts.nodes, cl=cl)
277 4040a784 Iustin Pop
  results = [name for name in results if name != myname]
278 e00ea635 Michael Hanselmann
279 56bece1f Iustin Pop
  srun = ssh.SshRunner(cluster_name=cluster_name)
280 b3989551 Iustin Pop
  for node in results:
281 b3989551 Iustin Pop
    if not srun.CopyFileToNode(node, filename):
282 3a24c527 Iustin Pop
      ToStderr("Copy of file %s to node %s failed", filename, node)
283 b3989551 Iustin Pop
284 a8083063 Iustin Pop
  return 0
285 a8083063 Iustin Pop
286 a8083063 Iustin Pop
287 a8083063 Iustin Pop
def RunClusterCommand(opts, args):
288 a8083063 Iustin Pop
  """Run a command on some nodes.
289 a8083063 Iustin Pop
290 469ee405 Iustin Pop
  @param opts: the command line options selected by the user
291 469ee405 Iustin Pop
  @type args: list
292 469ee405 Iustin Pop
  @param args: should contain the command to be run and its arguments
293 469ee405 Iustin Pop
  @rtype: int
294 469ee405 Iustin Pop
  @return: the desired exit code
295 a8083063 Iustin Pop
296 a8083063 Iustin Pop
  """
297 56bece1f Iustin Pop
  cl = GetClient()
298 7688d0d3 Michael Hanselmann
299 a8083063 Iustin Pop
  command = " ".join(args)
300 4040a784 Iustin Pop
301 4040a784 Iustin Pop
  nodes = GetOnlineNodes(nodes=opts.nodes, cl=cl)
302 56bece1f Iustin Pop
303 56bece1f Iustin Pop
  cluster_name, master_node = cl.QueryConfigValues(["cluster_name",
304 56bece1f Iustin Pop
                                                    "master_node"])
305 b3989551 Iustin Pop
306 56bece1f Iustin Pop
  srun = ssh.SshRunner(cluster_name=cluster_name)
307 b3989551 Iustin Pop
308 7688d0d3 Michael Hanselmann
  # Make sure master node is at list end
309 b3989551 Iustin Pop
  if master_node in nodes:
310 b3989551 Iustin Pop
    nodes.remove(master_node)
311 b3989551 Iustin Pop
    nodes.append(master_node)
312 b3989551 Iustin Pop
313 b3989551 Iustin Pop
  for name in nodes:
314 b3989551 Iustin Pop
    result = srun.Run(name, "root", command)
315 3a24c527 Iustin Pop
    ToStdout("------------------------------------------------")
316 3a24c527 Iustin Pop
    ToStdout("node: %s", name)
317 3a24c527 Iustin Pop
    ToStdout("%s", result.output)
318 3a24c527 Iustin Pop
    ToStdout("return code = %s", result.exit_code)
319 b3989551 Iustin Pop
320 b3989551 Iustin Pop
  return 0
321 a8083063 Iustin Pop
322 a8083063 Iustin Pop
323 a8083063 Iustin Pop
def VerifyCluster(opts, args):
324 a8083063 Iustin Pop
  """Verify integrity of cluster, performing various test on nodes.
325 a8083063 Iustin Pop
326 469ee405 Iustin Pop
  @param opts: the command line options selected by the user
327 469ee405 Iustin Pop
  @type args: list
328 469ee405 Iustin Pop
  @param args: should be an empty list
329 469ee405 Iustin Pop
  @rtype: int
330 469ee405 Iustin Pop
  @return: the desired exit code
331 a8083063 Iustin Pop
332 a8083063 Iustin Pop
  """
333 8d59409f Iustin Pop
  skip_checks = []
334 e54c4c5e Guido Trotter
  if opts.skip_nplusone_mem:
335 e54c4c5e Guido Trotter
    skip_checks.append(constants.VERIFY_NPLUSONE_MEM)
336 e54c4c5e Guido Trotter
  op = opcodes.OpVerifyCluster(skip_checks=skip_checks)
337 34290825 Michael Hanselmann
  if SubmitOpCode(op):
338 34290825 Michael Hanselmann
    return 0
339 34290825 Michael Hanselmann
  else:
340 34290825 Michael Hanselmann
    return 1
341 a8083063 Iustin Pop
342 a8083063 Iustin Pop
343 f4d4e184 Iustin Pop
def VerifyDisks(opts, args):
344 f4d4e184 Iustin Pop
  """Verify integrity of cluster disks.
345 f4d4e184 Iustin Pop
346 469ee405 Iustin Pop
  @param opts: the command line options selected by the user
347 469ee405 Iustin Pop
  @type args: list
348 469ee405 Iustin Pop
  @param args: should be an empty list
349 469ee405 Iustin Pop
  @rtype: int
350 469ee405 Iustin Pop
  @return: the desired exit code
351 f4d4e184 Iustin Pop
352 f4d4e184 Iustin Pop
  """
353 f4d4e184 Iustin Pop
  op = opcodes.OpVerifyDisks()
354 f4d4e184 Iustin Pop
  result = SubmitOpCode(op)
355 dcde0241 Guido Trotter
  if not isinstance(result, (list, tuple)) or len(result) != 4:
356 f4d4e184 Iustin Pop
    raise errors.ProgrammerError("Unknown result type for OpVerifyDisks")
357 f4d4e184 Iustin Pop
358 b63ed789 Iustin Pop
  nodes, nlvm, instances, missing = result
359 b63ed789 Iustin Pop
360 f4d4e184 Iustin Pop
  if nodes:
361 3a24c527 Iustin Pop
    ToStdout("Nodes unreachable or with bad data:")
362 f4d4e184 Iustin Pop
    for name in nodes:
363 3a24c527 Iustin Pop
      ToStdout("\t%s", name)
364 f4d4e184 Iustin Pop
  retcode = constants.EXIT_SUCCESS
365 b63ed789 Iustin Pop
366 b63ed789 Iustin Pop
  if nlvm:
367 b63ed789 Iustin Pop
    for node, text in nlvm.iteritems():
368 3a24c527 Iustin Pop
      ToStdout("Error on node %s: LVM error: %s",
369 26f15862 Iustin Pop
               node, utils.SafeEncode(text[-400:]))
370 b63ed789 Iustin Pop
      retcode |= 1
371 3a24c527 Iustin Pop
      ToStdout("You need to fix these nodes first before fixing instances")
372 b63ed789 Iustin Pop
373 f4d4e184 Iustin Pop
  if instances:
374 f4d4e184 Iustin Pop
    for iname in instances:
375 b63ed789 Iustin Pop
      if iname in missing:
376 b63ed789 Iustin Pop
        continue
377 f4d4e184 Iustin Pop
      op = opcodes.OpActivateInstanceDisks(instance_name=iname)
378 f4d4e184 Iustin Pop
      try:
379 3a24c527 Iustin Pop
        ToStdout("Activating disks for instance '%s'", iname)
380 f4d4e184 Iustin Pop
        SubmitOpCode(op)
381 f4d4e184 Iustin Pop
      except errors.GenericError, err:
382 f4d4e184 Iustin Pop
        nret, msg = FormatError(err)
383 f4d4e184 Iustin Pop
        retcode |= nret
384 3a24c527 Iustin Pop
        ToStderr("Error activating disks for instance %s: %s", iname, msg)
385 b63ed789 Iustin Pop
386 b63ed789 Iustin Pop
  if missing:
387 b63ed789 Iustin Pop
    for iname, ival in missing.iteritems():
388 b63ed789 Iustin Pop
      all_missing = utils.all(ival, lambda x: x[0] in nlvm)
389 b63ed789 Iustin Pop
      if all_missing:
390 3a24c527 Iustin Pop
        ToStdout("Instance %s cannot be verified as it lives on"
391 3a24c527 Iustin Pop
                 " broken nodes", iname)
392 b63ed789 Iustin Pop
      else:
393 3a24c527 Iustin Pop
        ToStdout("Instance %s has missing logical volumes:", iname)
394 b63ed789 Iustin Pop
        ival.sort()
395 b63ed789 Iustin Pop
        for node, vol in ival:
396 b63ed789 Iustin Pop
          if node in nlvm:
397 3a24c527 Iustin Pop
            ToStdout("\tbroken node %s /dev/xenvg/%s", node, vol)
398 b63ed789 Iustin Pop
          else:
399 3a24c527 Iustin Pop
            ToStdout("\t%s /dev/xenvg/%s", node, vol)
400 3a24c527 Iustin Pop
    ToStdout("You need to run replace_disks for all the above"
401 b63ed789 Iustin Pop
           " instances, if this message persist after fixing nodes.")
402 b63ed789 Iustin Pop
    retcode |= 1
403 f4d4e184 Iustin Pop
404 f4d4e184 Iustin Pop
  return retcode
405 f4d4e184 Iustin Pop
406 f4d4e184 Iustin Pop
407 4331f6cd Michael Hanselmann
@UsesRPC
408 a8083063 Iustin Pop
def MasterFailover(opts, args):
409 a8083063 Iustin Pop
  """Failover the master node.
410 a8083063 Iustin Pop
411 a8083063 Iustin Pop
  This command, when run on a non-master node, will cause the current
412 a8083063 Iustin Pop
  master to cease being master, and the non-master to become new
413 a8083063 Iustin Pop
  master.
414 a8083063 Iustin Pop
415 469ee405 Iustin Pop
  @param opts: the command line options selected by the user
416 469ee405 Iustin Pop
  @type args: list
417 469ee405 Iustin Pop
  @param args: should be an empty list
418 469ee405 Iustin Pop
  @rtype: int
419 469ee405 Iustin Pop
  @return: the desired exit code
420 469ee405 Iustin Pop
421 a8083063 Iustin Pop
  """
422 8e2524c3 Guido Trotter
  if opts.no_voting:
423 8e2524c3 Guido Trotter
    usertext = ("This will perform the failover even if most other nodes"
424 8e2524c3 Guido Trotter
                " are down, or if this node is outdated. This is dangerous"
425 8e2524c3 Guido Trotter
                " as it can lead to a non-consistent cluster. Check the"
426 8e2524c3 Guido Trotter
                " gnt-cluster(8) man page before proceeding. Continue?")
427 8e2524c3 Guido Trotter
    if not AskUser(usertext):
428 8e2524c3 Guido Trotter
      return 1
429 8e2524c3 Guido Trotter
430 8e2524c3 Guido Trotter
  return bootstrap.MasterFailover(no_voting=opts.no_voting)
431 a8083063 Iustin Pop
432 a8083063 Iustin Pop
433 73415719 Iustin Pop
def SearchTags(opts, args):
434 73415719 Iustin Pop
  """Searches the tags on all the cluster.
435 73415719 Iustin Pop
436 469ee405 Iustin Pop
  @param opts: the command line options selected by the user
437 469ee405 Iustin Pop
  @type args: list
438 469ee405 Iustin Pop
  @param args: should contain only one element, the tag pattern
439 469ee405 Iustin Pop
  @rtype: int
440 469ee405 Iustin Pop
  @return: the desired exit code
441 469ee405 Iustin Pop
442 73415719 Iustin Pop
  """
443 73415719 Iustin Pop
  op = opcodes.OpSearchTags(pattern=args[0])
444 73415719 Iustin Pop
  result = SubmitOpCode(op)
445 73415719 Iustin Pop
  if not result:
446 73415719 Iustin Pop
    return 1
447 73415719 Iustin Pop
  result = list(result)
448 73415719 Iustin Pop
  result.sort()
449 73415719 Iustin Pop
  for path, tag in result:
450 3a24c527 Iustin Pop
    ToStdout("%s %s", path, tag)
451 73415719 Iustin Pop
452 73415719 Iustin Pop
453 90b6aa3a Manuel Franceschini
def SetClusterParams(opts, args):
454 90b6aa3a Manuel Franceschini
  """Modify the cluster.
455 90b6aa3a Manuel Franceschini
456 469ee405 Iustin Pop
  @param opts: the command line options selected by the user
457 469ee405 Iustin Pop
  @type args: list
458 469ee405 Iustin Pop
  @param args: should be an empty list
459 469ee405 Iustin Pop
  @rtype: int
460 469ee405 Iustin Pop
  @return: the desired exit code
461 90b6aa3a Manuel Franceschini
462 90b6aa3a Manuel Franceschini
  """
463 779c15bb Iustin Pop
  if not (not opts.lvm_storage or opts.vg_name or
464 779c15bb Iustin Pop
          opts.enabled_hypervisors or opts.hvparams or
465 4b7735f9 Iustin Pop
          opts.beparams or opts.candidate_pool_size is not None):
466 3a24c527 Iustin Pop
    ToStderr("Please give at least one of the parameters.")
467 90b6aa3a Manuel Franceschini
    return 1
468 90b6aa3a Manuel Franceschini
469 90b6aa3a Manuel Franceschini
  vg_name = opts.vg_name
470 90b6aa3a Manuel Franceschini
  if not opts.lvm_storage and opts.vg_name:
471 3a24c527 Iustin Pop
    ToStdout("Options --no-lvm-storage and --vg-name conflict.")
472 90b6aa3a Manuel Franceschini
    return 1
473 b8a8fbe1 Guido Trotter
  elif not opts.lvm_storage:
474 b8a8fbe1 Guido Trotter
    vg_name = ''
475 90b6aa3a Manuel Franceschini
476 779c15bb Iustin Pop
  hvlist = opts.enabled_hypervisors
477 779c15bb Iustin Pop
  if hvlist is not None:
478 779c15bb Iustin Pop
    hvlist = hvlist.split(",")
479 779c15bb Iustin Pop
480 f8e7ddca Guido Trotter
  # a list of (name, dict) we can pass directly to dict() (or [])
481 f8e7ddca Guido Trotter
  hvparams = dict(opts.hvparams)
482 a5728081 Guido Trotter
  for hv, hv_params in hvparams.iteritems():
483 a5728081 Guido Trotter
    utils.ForceDictType(hv_params, constants.HVS_PARAMETER_TYPES)
484 779c15bb Iustin Pop
485 779c15bb Iustin Pop
  beparams = opts.beparams
486 a5728081 Guido Trotter
  utils.ForceDictType(beparams, constants.BES_PARAMETER_TYPES)
487 779c15bb Iustin Pop
488 b8a8fbe1 Guido Trotter
  op = opcodes.OpSetClusterParams(vg_name=vg_name,
489 779c15bb Iustin Pop
                                  enabled_hypervisors=hvlist,
490 779c15bb Iustin Pop
                                  hvparams=hvparams,
491 4b7735f9 Iustin Pop
                                  beparams=beparams,
492 4b7735f9 Iustin Pop
                                  candidate_pool_size=opts.candidate_pool_size)
493 90b6aa3a Manuel Franceschini
  SubmitOpCode(op)
494 90b6aa3a Manuel Franceschini
  return 0
495 90b6aa3a Manuel Franceschini
496 90b6aa3a Manuel Franceschini
497 3ccafd0e Iustin Pop
def QueueOps(opts, args):
498 3ccafd0e Iustin Pop
  """Queue operations.
499 3ccafd0e Iustin Pop
500 469ee405 Iustin Pop
  @param opts: the command line options selected by the user
501 469ee405 Iustin Pop
  @type args: list
502 469ee405 Iustin Pop
  @param args: should contain only one element, the subcommand
503 469ee405 Iustin Pop
  @rtype: int
504 469ee405 Iustin Pop
  @return: the desired exit code
505 469ee405 Iustin Pop
506 3ccafd0e Iustin Pop
  """
507 3ccafd0e Iustin Pop
  command = args[0]
508 3ccafd0e Iustin Pop
  client = GetClient()
509 3ccafd0e Iustin Pop
  if command in ("drain", "undrain"):
510 3ccafd0e Iustin Pop
    drain_flag = command == "drain"
511 3ccafd0e Iustin Pop
    client.SetQueueDrainFlag(drain_flag)
512 3ccafd0e Iustin Pop
  elif command == "info":
513 3ccafd0e Iustin Pop
    result = client.QueryConfigValues(["drain_flag"])
514 3ccafd0e Iustin Pop
    if result[0]:
515 3a24c527 Iustin Pop
      val = "set"
516 3ccafd0e Iustin Pop
    else:
517 3a24c527 Iustin Pop
      val = "unset"
518 3a24c527 Iustin Pop
    ToStdout("The drain flag is %s" % val)
519 2e668b38 Guido Trotter
  else:
520 2e668b38 Guido Trotter
    raise errors.OpPrereqError("Command '%s' is not valid." % command)
521 2e668b38 Guido Trotter
522 3ccafd0e Iustin Pop
  return 0
523 3ccafd0e Iustin Pop
524 a8083063 Iustin Pop
# this is an option common to more than one command, so we declare
525 a8083063 Iustin Pop
# it here and reuse it
526 a8083063 Iustin Pop
node_option = make_option("-n", "--node", action="append", dest="nodes",
527 f4bc1f2c Michael Hanselmann
                          help="Node to copy to (if not given, all nodes),"
528 f4bc1f2c Michael Hanselmann
                               " can be given multiple times",
529 f4bc1f2c Michael Hanselmann
                          metavar="<node>", default=[])
530 a8083063 Iustin Pop
531 a8083063 Iustin Pop
commands = {
532 a8083063 Iustin Pop
  'init': (InitCluster, ARGS_ONE,
533 a8083063 Iustin Pop
           [DEBUG_OPT,
534 a8083063 Iustin Pop
            make_option("-s", "--secondary-ip", dest="secondary_ip",
535 a8083063 Iustin Pop
                        help="Specify the secondary ip for this node;"
536 a8083063 Iustin Pop
                        " if given, the entire cluster must have secondary"
537 a8083063 Iustin Pop
                        " addresses",
538 a8083063 Iustin Pop
                        metavar="ADDRESS", default=None),
539 a8083063 Iustin Pop
            make_option("-m", "--mac-prefix", dest="mac_prefix",
540 a8083063 Iustin Pop
                        help="Specify the mac prefix for the instance IP"
541 a8083063 Iustin Pop
                        " addresses, in the format XX:XX:XX",
542 a8083063 Iustin Pop
                        metavar="PREFIX",
543 c5e489f7 Iustin Pop
                        default=constants.DEFAULT_MAC_PREFIX,),
544 a8083063 Iustin Pop
            make_option("-g", "--vg-name", dest="vg_name",
545 a8083063 Iustin Pop
                        help="Specify the volume group name "
546 a8083063 Iustin Pop
                        " (cluster-wide) for disk allocation [xenvg]",
547 a8083063 Iustin Pop
                        metavar="VG",
548 90b6aa3a Manuel Franceschini
                        default=None,),
549 a8083063 Iustin Pop
            make_option("-b", "--bridge", dest="def_bridge",
550 a8083063 Iustin Pop
                        help="Specify the default bridge name (cluster-wide)"
551 cf62a272 Michael Hanselmann
                          " to connect the instances to [%s]" %
552 cf62a272 Michael Hanselmann
                          constants.DEFAULT_BRIDGE,
553 a8083063 Iustin Pop
                        metavar="BRIDGE",
554 cf62a272 Michael Hanselmann
                        default=constants.DEFAULT_BRIDGE,),
555 880478f8 Iustin Pop
            make_option("--master-netdev", dest="master_netdev",
556 880478f8 Iustin Pop
                        help="Specify the node interface (cluster-wide)"
557 cf62a272 Michael Hanselmann
                          " on which the master IP address will be added "
558 cf62a272 Michael Hanselmann
                          " [%s]" % constants.DEFAULT_BRIDGE,
559 880478f8 Iustin Pop
                        metavar="NETDEV",
560 cf62a272 Michael Hanselmann
                        default=constants.DEFAULT_BRIDGE,),
561 79e82404 Manuel Franceschini
            make_option("--file-storage-dir", dest="file_storage_dir",
562 79e82404 Manuel Franceschini
                        help="Specify the default directory (cluster-wide)"
563 79e82404 Manuel Franceschini
                             " for storing the file-based disks [%s]" %
564 79e82404 Manuel Franceschini
                             constants.DEFAULT_FILE_STORAGE_DIR,
565 79e82404 Manuel Franceschini
                        metavar="DIR",
566 79e82404 Manuel Franceschini
                        default=constants.DEFAULT_FILE_STORAGE_DIR,),
567 90b6aa3a Manuel Franceschini
            make_option("--no-lvm-storage", dest="lvm_storage",
568 90b6aa3a Manuel Franceschini
                        help="No support for lvm based instances"
569 90b6aa3a Manuel Franceschini
                             " (cluster-wide)",
570 90b6aa3a Manuel Franceschini
                        action="store_false", default=True,),
571 ea3a925f Alexander Schreiber
            make_option("--enabled-hypervisors", dest="enabled_hypervisors",
572 ea3a925f Alexander Schreiber
                        help="Comma-separated list of hypervisors",
573 ea3a925f Alexander Schreiber
                        type="string", default=None),
574 02691904 Alexander Schreiber
            make_option("-t", "--default-hypervisor",
575 02691904 Alexander Schreiber
                        dest="default_hypervisor",
576 02691904 Alexander Schreiber
                        help="Default hypervisor to use for instance creation",
577 02691904 Alexander Schreiber
                        choices=list(constants.HYPER_TYPES),
578 02691904 Alexander Schreiber
                        default=constants.DEFAULT_ENABLED_HYPERVISOR),
579 ea3a925f Alexander Schreiber
            ikv_option("-H", "--hypervisor-parameters", dest="hvparams",
580 ea3a925f Alexander Schreiber
                       help="Hypervisor and hypervisor options, in the"
581 ea3a925f Alexander Schreiber
                         " format"
582 ea3a925f Alexander Schreiber
                       " hypervisor:option=value,option=value,...",
583 ea3a925f Alexander Schreiber
                       default=[],
584 ea3a925f Alexander Schreiber
                       action="append",
585 ea3a925f Alexander Schreiber
                       type="identkeyval"),
586 ea3a925f Alexander Schreiber
            keyval_option("-B", "--backend-parameters", dest="beparams",
587 ea3a925f Alexander Schreiber
                          type="keyval", default={},
588 ea3a925f Alexander Schreiber
                          help="Backend parameters"),
589 ce735215 Guido Trotter
            make_option("-C", "--candidate-pool-size",
590 ce735215 Guido Trotter
                        default=constants.MASTER_POOL_SIZE_DEFAULT,
591 ce735215 Guido Trotter
                        help="Set the candidate pool size",
592 ce735215 Guido Trotter
                        dest="candidate_pool_size", type="int"),
593 a8083063 Iustin Pop
            ],
594 9a033156 Iustin Pop
           "[opts...] <cluster_name>",
595 a8083063 Iustin Pop
           "Initialises a new cluster configuration"),
596 a8083063 Iustin Pop
  'destroy': (DestroyCluster, ARGS_NONE,
597 a8083063 Iustin Pop
              [DEBUG_OPT,
598 a8083063 Iustin Pop
               make_option("--yes-do-it", dest="yes_do_it",
599 a8083063 Iustin Pop
                           help="Destroy cluster",
600 a8083063 Iustin Pop
                           action="store_true"),
601 a8083063 Iustin Pop
              ],
602 9a033156 Iustin Pop
              "", "Destroy cluster"),
603 07bd8a51 Iustin Pop
  'rename': (RenameCluster, ARGS_ONE, [DEBUG_OPT, FORCE_OPT],
604 9a033156 Iustin Pop
               "<new_name>",
605 07bd8a51 Iustin Pop
               "Renames the cluster"),
606 afee0879 Iustin Pop
  'redist-conf': (RedistributeConfig, ARGS_NONE, [DEBUG_OPT, SUBMIT_OPT],
607 afee0879 Iustin Pop
                  "",
608 afee0879 Iustin Pop
                  "Forces a push of the configuration file and ssconf files"
609 afee0879 Iustin Pop
                  " to the nodes in the cluster"),
610 e54c4c5e Guido Trotter
  'verify': (VerifyCluster, ARGS_NONE, [DEBUG_OPT,
611 e54c4c5e Guido Trotter
             make_option("--no-nplus1-mem", dest="skip_nplusone_mem",
612 e54c4c5e Guido Trotter
                         help="Skip N+1 memory redundancy tests",
613 e54c4c5e Guido Trotter
                         action="store_true",
614 e54c4c5e Guido Trotter
                         default=False,),
615 e54c4c5e Guido Trotter
             ],
616 9a033156 Iustin Pop
             "", "Does a check on the cluster configuration"),
617 f4d4e184 Iustin Pop
  'verify-disks': (VerifyDisks, ARGS_NONE, [DEBUG_OPT],
618 9a033156 Iustin Pop
                   "", "Does a check on the cluster disk status"),
619 8e2524c3 Guido Trotter
  'masterfailover': (MasterFailover, ARGS_NONE, [DEBUG_OPT,
620 8e2524c3 Guido Trotter
                     make_option("--no-voting", dest="no_voting",
621 8e2524c3 Guido Trotter
                                 help="Skip node agreement check (dangerous)",
622 8e2524c3 Guido Trotter
                                 action="store_true",
623 8e2524c3 Guido Trotter
                                 default=False,),
624 8e2524c3 Guido Trotter
                     ],
625 9a033156 Iustin Pop
                     "", "Makes the current node the master"),
626 a8083063 Iustin Pop
  'version': (ShowClusterVersion, ARGS_NONE, [DEBUG_OPT],
627 9a033156 Iustin Pop
              "", "Shows the cluster version"),
628 a8083063 Iustin Pop
  'getmaster': (ShowClusterMaster, ARGS_NONE, [DEBUG_OPT],
629 9a033156 Iustin Pop
                "", "Shows the cluster master"),
630 a8083063 Iustin Pop
  'copyfile': (ClusterCopyFile, ARGS_ONE, [DEBUG_OPT, node_option],
631 9a033156 Iustin Pop
               "[-n node...] <filename>",
632 a8083063 Iustin Pop
               "Copies a file to all (or only some) nodes"),
633 a8083063 Iustin Pop
  'command': (RunClusterCommand, ARGS_ATLEAST(1), [DEBUG_OPT, node_option],
634 9a033156 Iustin Pop
              "[-n node...] <command>",
635 a8083063 Iustin Pop
              "Runs a command on all (or only some) nodes"),
636 a8083063 Iustin Pop
  'info': (ShowClusterConfig, ARGS_NONE, [DEBUG_OPT],
637 9a033156 Iustin Pop
                 "", "Show cluster configuration"),
638 846baef9 Iustin Pop
  'list-tags': (ListTags, ARGS_NONE,
639 9a033156 Iustin Pop
                [DEBUG_OPT], "", "List the tags of the cluster"),
640 810c50b7 Iustin Pop
  'add-tags': (AddTags, ARGS_ANY, [DEBUG_OPT, TAG_SRC_OPT],
641 9a033156 Iustin Pop
               "tag...", "Add tags to the cluster"),
642 810c50b7 Iustin Pop
  'remove-tags': (RemoveTags, ARGS_ANY, [DEBUG_OPT, TAG_SRC_OPT],
643 9a033156 Iustin Pop
                  "tag...", "Remove tags from the cluster"),
644 73415719 Iustin Pop
  'search-tags': (SearchTags, ARGS_ONE,
645 9a033156 Iustin Pop
                  [DEBUG_OPT], "", "Searches the tags on all objects on"
646 73415719 Iustin Pop
                  " the cluster for a given pattern (regex)"),
647 3ccafd0e Iustin Pop
  'queue': (QueueOps, ARGS_ONE, [DEBUG_OPT],
648 3ccafd0e Iustin Pop
            "drain|undrain|info", "Change queue properties"),
649 90b6aa3a Manuel Franceschini
  'modify': (SetClusterParams, ARGS_NONE,
650 90b6aa3a Manuel Franceschini
             [DEBUG_OPT,
651 90b6aa3a Manuel Franceschini
              make_option("-g", "--vg-name", dest="vg_name",
652 90b6aa3a Manuel Franceschini
                          help="Specify the volume group name "
653 90b6aa3a Manuel Franceschini
                          " (cluster-wide) for disk allocation "
654 90b6aa3a Manuel Franceschini
                          "and enable lvm based storage",
655 90b6aa3a Manuel Franceschini
                          metavar="VG",),
656 90b6aa3a Manuel Franceschini
              make_option("--no-lvm-storage", dest="lvm_storage",
657 90b6aa3a Manuel Franceschini
                          help="Disable support for lvm based instances"
658 90b6aa3a Manuel Franceschini
                               " (cluster-wide)",
659 90b6aa3a Manuel Franceschini
                          action="store_false", default=True,),
660 779c15bb Iustin Pop
              make_option("--enabled-hypervisors", dest="enabled_hypervisors",
661 779c15bb Iustin Pop
                          help="Comma-separated list of hypervisors",
662 779c15bb Iustin Pop
                          type="string", default=None),
663 779c15bb Iustin Pop
              ikv_option("-H", "--hypervisor-parameters", dest="hvparams",
664 779c15bb Iustin Pop
                         help="Hypervisor and hypervisor options, in the"
665 779c15bb Iustin Pop
                         " format"
666 779c15bb Iustin Pop
                         " hypervisor:option=value,option=value,...",
667 779c15bb Iustin Pop
                         default=[],
668 779c15bb Iustin Pop
                         action="append",
669 779c15bb Iustin Pop
                         type="identkeyval"),
670 779c15bb Iustin Pop
              keyval_option("-B", "--backend-parameters", dest="beparams",
671 779c15bb Iustin Pop
                            type="keyval", default={},
672 779c15bb Iustin Pop
                            help="Backend parameters"),
673 4b7735f9 Iustin Pop
              make_option("-C", "--candidate-pool-size", default=None,
674 4b7735f9 Iustin Pop
                          help="Set the candidate pool size",
675 4b7735f9 Iustin Pop
                          dest="candidate_pool_size", type="int"),
676 90b6aa3a Manuel Franceschini
              ],
677 90b6aa3a Manuel Franceschini
             "[opts...]",
678 90b6aa3a Manuel Franceschini
             "Alters the parameters of the cluster"),
679 a8083063 Iustin Pop
  }
680 a8083063 Iustin Pop
681 a8083063 Iustin Pop
if __name__ == '__main__':
682 846baef9 Iustin Pop
  sys.exit(GenericMain(commands, override={"tag_type": constants.TAG_CLUSTER}))