Statistics
| Branch: | Tag: | Revision:

root / scripts / gnt-cluster @ d4dd4b74

History | View | Annotate | Download (23 kB)

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