Statistics
| Branch: | Tag: | Revision:

root / scripts / gnt-cluster @ 467ae11e

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