Statistics
| Branch: | Tag: | Revision:

root / scripts / gnt-cluster @ 3a24c527

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