Statistics
| Branch: | Tag: | Revision:

root / scripts / gnt-cluster @ 8f348e36

History | View | Annotate | Download (22.1 kB)

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