Statistics
| Branch: | Tag: | Revision:

root / scripts / gnt-cluster @ a5728081

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