Statistics
| Branch: | Tag: | Revision:

root / lib / client / gnt_node.py @ 792af3ad

History | View | Annotate | Download (24.2 kB)

1 37494fa4 Michael Hanselmann
#
2 a8083063 Iustin Pop
#
3 a8083063 Iustin Pop
4 783a6c0b Iustin Pop
# Copyright (C) 2006, 2007, 2008, 2009, 2010 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 7260cfbe Iustin Pop
"""Node related commands"""
22 a8083063 Iustin Pop
23 2d54e29c Iustin Pop
# pylint: disable-msg=W0401,W0613,W0614,C0103
24 2f79bd34 Iustin Pop
# W0401: Wildcard import ganeti.cli
25 2d54e29c Iustin Pop
# W0613: Unused argument, since all functions follow the same API
26 2f79bd34 Iustin Pop
# W0614: Unused import %s from wildcard import (since we need cli)
27 7260cfbe Iustin Pop
# C0103: Invalid name gnt-node
28 2f79bd34 Iustin Pop
29 a8083063 Iustin Pop
from ganeti.cli import *
30 3ef51126 René Nussbaumer
from ganeti import bootstrap
31 a8083063 Iustin Pop
from ganeti import opcodes
32 a8083063 Iustin Pop
from ganeti import utils
33 846baef9 Iustin Pop
from ganeti import constants
34 c450e9b0 Iustin Pop
from ganeti import errors
35 a744b676 Manuel Franceschini
from ganeti import netutils
36 a8083063 Iustin Pop
37 a8083063 Iustin Pop
38 ebf366ee Iustin Pop
#: default list of field for L{ListNodes}
39 48c4dfa8 Iustin Pop
_LIST_DEF_FIELDS = [
40 48c4dfa8 Iustin Pop
  "name", "dtotal", "dfree",
41 48c4dfa8 Iustin Pop
  "mtotal", "mnode", "mfree",
42 48c4dfa8 Iustin Pop
  "pinst_cnt", "sinst_cnt",
43 48c4dfa8 Iustin Pop
  ]
44 48c4dfa8 Iustin Pop
45 620a85fd Iustin Pop
46 a4ebd726 Michael Hanselmann
#: Default field list for L{ListVolumes}
47 a4ebd726 Michael Hanselmann
_LIST_VOL_DEF_FIELDS = ["node", "phys", "vg", "name", "size", "instance"]
48 a4ebd726 Michael Hanselmann
49 a4ebd726 Michael Hanselmann
50 620a85fd Iustin Pop
#: default list of field for L{ListStorage}
51 620a85fd Iustin Pop
_LIST_STOR_DEF_FIELDS = [
52 620a85fd Iustin Pop
  constants.SF_NODE,
53 620a85fd Iustin Pop
  constants.SF_TYPE,
54 620a85fd Iustin Pop
  constants.SF_NAME,
55 620a85fd Iustin Pop
  constants.SF_SIZE,
56 620a85fd Iustin Pop
  constants.SF_USED,
57 620a85fd Iustin Pop
  constants.SF_FREE,
58 620a85fd Iustin Pop
  constants.SF_ALLOCATABLE,
59 620a85fd Iustin Pop
  ]
60 620a85fd Iustin Pop
61 620a85fd Iustin Pop
62 abefdcff René Nussbaumer
#: default list of power commands
63 abefdcff René Nussbaumer
_LIST_POWER_COMMANDS = ["on", "off", "cycle", "status"]
64 abefdcff René Nussbaumer
65 abefdcff René Nussbaumer
66 982ed68e Adeodato Simo
#: headers (and full field list) for L{ListStorage}
67 620a85fd Iustin Pop
_LIST_STOR_HEADERS = {
68 620a85fd Iustin Pop
  constants.SF_NODE: "Node",
69 620a85fd Iustin Pop
  constants.SF_TYPE: "Type",
70 620a85fd Iustin Pop
  constants.SF_NAME: "Name",
71 620a85fd Iustin Pop
  constants.SF_SIZE: "Size",
72 620a85fd Iustin Pop
  constants.SF_USED: "Used",
73 620a85fd Iustin Pop
  constants.SF_FREE: "Free",
74 620a85fd Iustin Pop
  constants.SF_ALLOCATABLE: "Allocatable",
75 620a85fd Iustin Pop
  }
76 620a85fd Iustin Pop
77 620a85fd Iustin Pop
78 0e89fc2d Michael Hanselmann
#: User-facing storage unit types
79 0e89fc2d Michael Hanselmann
_USER_STORAGE_TYPE = {
80 0e89fc2d Michael Hanselmann
  constants.ST_FILE: "file",
81 0e89fc2d Michael Hanselmann
  constants.ST_LVM_PV: "lvm-pv",
82 0e89fc2d Michael Hanselmann
  constants.ST_LVM_VG: "lvm-vg",
83 0e89fc2d Michael Hanselmann
  }
84 0e89fc2d Michael Hanselmann
85 a8005e17 Michael Hanselmann
_STORAGE_TYPE_OPT = \
86 aeaefce8 Iustin Pop
  cli_option("-t", "--storage-type",
87 a8005e17 Michael Hanselmann
             dest="user_storage_type",
88 a8005e17 Michael Hanselmann
             choices=_USER_STORAGE_TYPE.keys(),
89 a8005e17 Michael Hanselmann
             default=None,
90 a8005e17 Michael Hanselmann
             metavar="STORAGE_TYPE",
91 ab3e6da8 Iustin Pop
             help=("Storage type (%s)" %
92 ab3e6da8 Iustin Pop
                   utils.CommaJoin(_USER_STORAGE_TYPE.keys())))
93 a8005e17 Michael Hanselmann
94 a8005e17 Michael Hanselmann
_REPAIRABLE_STORAGE_TYPES = \
95 a8005e17 Michael Hanselmann
  [st for st, so in constants.VALID_STORAGE_OPERATIONS.iteritems()
96 a8005e17 Michael Hanselmann
   if constants.SO_FIX_CONSISTENCY in so]
97 a8005e17 Michael Hanselmann
98 a8005e17 Michael Hanselmann
_MODIFIABLE_STORAGE_TYPES = constants.MODIFIABLE_STORAGE_FIELDS.keys()
99 a8005e17 Michael Hanselmann
100 51144e33 Michael Hanselmann
101 2e6469a1 René Nussbaumer
NONODE_SETUP_OPT = cli_option("--no-node-setup", default=True,
102 2e6469a1 René Nussbaumer
                              action="store_false", dest="node_setup",
103 2e6469a1 René Nussbaumer
                              help=("Do not make initial SSH setup on remote"
104 2e6469a1 René Nussbaumer
                                    " node (needs to be done manually)"))
105 2e6469a1 René Nussbaumer
106 2e6469a1 René Nussbaumer
107 86f5eae3 Michael Hanselmann
def ConvertStorageType(user_storage_type):
108 86f5eae3 Michael Hanselmann
  """Converts a user storage type to its internal name.
109 86f5eae3 Michael Hanselmann

110 86f5eae3 Michael Hanselmann
  """
111 86f5eae3 Michael Hanselmann
  try:
112 86f5eae3 Michael Hanselmann
    return _USER_STORAGE_TYPE[user_storage_type]
113 86f5eae3 Michael Hanselmann
  except KeyError:
114 debac808 Iustin Pop
    raise errors.OpPrereqError("Unknown storage type: %s" % user_storage_type,
115 debac808 Iustin Pop
                               errors.ECODE_INVAL)
116 86f5eae3 Michael Hanselmann
117 86f5eae3 Michael Hanselmann
118 2e6469a1 René Nussbaumer
def _RunSetupSSH(options, nodes):
119 2e6469a1 René Nussbaumer
  """Wrapper around utils.RunCmd to call setup-ssh
120 2e6469a1 René Nussbaumer

121 2e6469a1 René Nussbaumer
  @param options: The command line options
122 2e6469a1 René Nussbaumer
  @param nodes: The nodes to setup
123 2e6469a1 René Nussbaumer

124 2e6469a1 René Nussbaumer
  """
125 2e6469a1 René Nussbaumer
  cmd = [constants.SETUP_SSH]
126 2e6469a1 René Nussbaumer
127 2e6469a1 René Nussbaumer
  # Pass --debug|--verbose to the external script if set on our invocation
128 2e6469a1 René Nussbaumer
  # --debug overrides --verbose
129 2e6469a1 René Nussbaumer
  if options.debug:
130 2e6469a1 René Nussbaumer
    cmd.append("--debug")
131 2e6469a1 René Nussbaumer
  elif options.verbose:
132 2e6469a1 René Nussbaumer
    cmd.append("--verbose")
133 e81edf72 Manuel Franceschini
  if not options.ssh_key_check:
134 3ef51126 René Nussbaumer
    cmd.append("--no-ssh-key-check")
135 2e6469a1 René Nussbaumer
136 2e6469a1 René Nussbaumer
  cmd.extend(nodes)
137 2e6469a1 René Nussbaumer
138 2e6469a1 René Nussbaumer
  result = utils.RunCmd(cmd, interactive=True)
139 2e6469a1 René Nussbaumer
140 2e6469a1 René Nussbaumer
  if result.failed:
141 2e6469a1 René Nussbaumer
    errmsg = ("Command '%s' failed with exit code %s; output %r" %
142 2e6469a1 René Nussbaumer
              (result.cmd, result.exit_code, result.output))
143 2e6469a1 René Nussbaumer
    raise errors.OpExecError(errmsg)
144 2e6469a1 René Nussbaumer
145 2e6469a1 René Nussbaumer
146 4331f6cd Michael Hanselmann
@UsesRPC
147 a8083063 Iustin Pop
def AddNode(opts, args):
148 ebf366ee Iustin Pop
  """Add a node to the cluster.
149 ebf366ee Iustin Pop

150 ebf366ee Iustin Pop
  @param opts: the command line options selected by the user
151 ebf366ee Iustin Pop
  @type args: list
152 ebf366ee Iustin Pop
  @param args: should contain only one element, the new node name
153 ebf366ee Iustin Pop
  @rtype: int
154 ebf366ee Iustin Pop
  @return: the desired exit code
155 05ccd983 Guido Trotter

156 05ccd983 Guido Trotter
  """
157 87622829 Iustin Pop
  cl = GetClient()
158 b705c7a6 Manuel Franceschini
  node = netutils.GetHostname(name=args[0]).name
159 82e12743 Iustin Pop
  readd = opts.readd
160 82e12743 Iustin Pop
161 82e12743 Iustin Pop
  try:
162 82e12743 Iustin Pop
    output = cl.QueryNodes(names=[node], fields=['name', 'sip'],
163 77921a95 Iustin Pop
                           use_locking=False)
164 82e12743 Iustin Pop
    node_exists, sip = output[0]
165 82e12743 Iustin Pop
  except (errors.OpPrereqError, errors.OpExecError):
166 82e12743 Iustin Pop
    node_exists = ""
167 82e12743 Iustin Pop
    sip = None
168 82e12743 Iustin Pop
169 82e12743 Iustin Pop
  if readd:
170 82e12743 Iustin Pop
    if not node_exists:
171 82e12743 Iustin Pop
      ToStderr("Node %s not in the cluster"
172 82e12743 Iustin Pop
               " - please retry without '--readd'", node)
173 82e12743 Iustin Pop
      return 1
174 82e12743 Iustin Pop
  else:
175 82e12743 Iustin Pop
    if node_exists:
176 3a24c527 Iustin Pop
      ToStderr("Node %s already in the cluster (as %s)"
177 82e12743 Iustin Pop
               " - please retry with '--readd'", node, node_exists)
178 05ccd983 Guido Trotter
      return 1
179 82e12743 Iustin Pop
    sip = opts.secondary_ip
180 05ccd983 Guido Trotter
181 87622829 Iustin Pop
  # read the cluster name from the master
182 87622829 Iustin Pop
  output = cl.QueryConfigValues(['cluster_name'])
183 3ef51126 René Nussbaumer
  cluster_name = output[0]
184 87622829 Iustin Pop
185 3ef51126 René Nussbaumer
  if not readd and opts.node_setup:
186 82e12743 Iustin Pop
    ToStderr("-- WARNING -- \n"
187 82e12743 Iustin Pop
             "Performing this operation is going to replace the ssh daemon"
188 82e12743 Iustin Pop
             " keypair\n"
189 82e12743 Iustin Pop
             "on the target machine (%s) with the ones of the"
190 82e12743 Iustin Pop
             " current one\n"
191 82e12743 Iustin Pop
             "and grant full intra-cluster ssh root access to/from it\n", node)
192 05ccd983 Guido Trotter
193 2e6469a1 René Nussbaumer
  if opts.node_setup:
194 2e6469a1 René Nussbaumer
    _RunSetupSSH(opts, [node])
195 827f753e Guido Trotter
196 3ef51126 René Nussbaumer
  bootstrap.SetupNodeDaemon(cluster_name, node, opts.ssh_key_check)
197 3ef51126 René Nussbaumer
198 82e12743 Iustin Pop
  op = opcodes.OpAddNode(node_name=args[0], secondary_ip=sip,
199 fd3d37b6 Iustin Pop
                         readd=opts.readd, group=opts.nodegroup,
200 4e37f591 René Nussbaumer
                         vm_capable=opts.vm_capable, ndparams=opts.ndparams,
201 fd3d37b6 Iustin Pop
                         master_capable=opts.master_capable)
202 400ca2f7 Iustin Pop
  SubmitOpCode(op, opts=opts)
203 a8083063 Iustin Pop
204 a8083063 Iustin Pop
205 a8083063 Iustin Pop
def ListNodes(opts, args):
206 a8083063 Iustin Pop
  """List nodes and their properties.
207 a8083063 Iustin Pop

208 ebf366ee Iustin Pop
  @param opts: the command line options selected by the user
209 ebf366ee Iustin Pop
  @type args: list
210 982ed68e Adeodato Simo
  @param args: nodes to list, or empty for all
211 ebf366ee Iustin Pop
  @rtype: int
212 ebf366ee Iustin Pop
  @return: the desired exit code
213 ebf366ee Iustin Pop

214 a8083063 Iustin Pop
  """
215 a4ebd726 Michael Hanselmann
  selected_fields = ParseFields(opts.output, _LIST_DEF_FIELDS)
216 a8083063 Iustin Pop
217 7f5443a0 Michael Hanselmann
  fmtoverride = dict.fromkeys(["pinst_list", "sinst_list", "tags"],
218 a36f605d Michael Hanselmann
                              (",".join, False))
219 a8083063 Iustin Pop
220 7f5443a0 Michael Hanselmann
  return GenericList(constants.QR_NODE, selected_fields, args, opts.units,
221 7f5443a0 Michael Hanselmann
                     opts.separator, not opts.no_headers,
222 7f5443a0 Michael Hanselmann
                     format_override=fmtoverride)
223 137161c9 Michael Hanselmann
224 137161c9 Michael Hanselmann
225 7f5443a0 Michael Hanselmann
def ListNodeFields(opts, args):
226 7f5443a0 Michael Hanselmann
  """List node fields.
227 ec223efb Iustin Pop

228 7f5443a0 Michael Hanselmann
  @param opts: the command line options selected by the user
229 7f5443a0 Michael Hanselmann
  @type args: list
230 7f5443a0 Michael Hanselmann
  @param args: fields to list, or empty for all
231 7f5443a0 Michael Hanselmann
  @rtype: int
232 7f5443a0 Michael Hanselmann
  @return: the desired exit code
233 a8083063 Iustin Pop

234 7f5443a0 Michael Hanselmann
  """
235 7f5443a0 Michael Hanselmann
  return GenericListFields(constants.QR_NODE, args, opts.separator,
236 7f5443a0 Michael Hanselmann
                           not opts.no_headers)
237 a8083063 Iustin Pop
238 a8083063 Iustin Pop
239 a5bc662a Iustin Pop
def EvacuateNode(opts, args):
240 a5bc662a Iustin Pop
  """Relocate all secondary instance from a node.
241 a5bc662a Iustin Pop

242 ebf366ee Iustin Pop
  @param opts: the command line options selected by the user
243 ebf366ee Iustin Pop
  @type args: list
244 ebf366ee Iustin Pop
  @param args: should be an empty list
245 ebf366ee Iustin Pop
  @rtype: int
246 ebf366ee Iustin Pop
  @return: the desired exit code
247 ebf366ee Iustin Pop

248 a5bc662a Iustin Pop
  """
249 479636a3 Iustin Pop
  cl = GetClient()
250 a5bc662a Iustin Pop
  force = opts.force
251 c4ed32cb Iustin Pop
252 c4ed32cb Iustin Pop
  dst_node = opts.dst_node
253 c4ed32cb Iustin Pop
  iallocator = opts.iallocator
254 c4ed32cb Iustin Pop
255 f8c9fa5c Iustin Pop
  op = opcodes.OpNodeEvacuationStrategy(nodes=args,
256 f8c9fa5c Iustin Pop
                                        iallocator=iallocator,
257 f8c9fa5c Iustin Pop
                                        remote_node=dst_node)
258 f8c9fa5c Iustin Pop
259 f8c9fa5c Iustin Pop
  result = SubmitOpCode(op, cl=cl, opts=opts)
260 f8c9fa5c Iustin Pop
  if not result:
261 f8c9fa5c Iustin Pop
    # no instances to migrate
262 f8c9fa5c Iustin Pop
    ToStderr("No secondary instances on node(s) %s, exiting.",
263 f8c9fa5c Iustin Pop
             utils.CommaJoin(args))
264 a5bc662a Iustin Pop
    return constants.EXIT_SUCCESS
265 a5bc662a Iustin Pop
266 f8c9fa5c Iustin Pop
  if not force and not AskUser("Relocate instance(s) %s from node(s) %s?" %
267 f8c9fa5c Iustin Pop
                               (",".join("'%s'" % name[0] for name in result),
268 f8c9fa5c Iustin Pop
                               utils.CommaJoin(args))):
269 a5bc662a Iustin Pop
    return constants.EXIT_CONFIRMATION
270 a5bc662a Iustin Pop
271 f8c9fa5c Iustin Pop
  jex = JobExecutor(cl=cl, opts=opts)
272 f8c9fa5c Iustin Pop
  for row in result:
273 f8c9fa5c Iustin Pop
    iname = row[0]
274 f8c9fa5c Iustin Pop
    node = row[1]
275 f8c9fa5c Iustin Pop
    ToStdout("Will relocate instance %s to node %s", iname, node)
276 f8c9fa5c Iustin Pop
    op = opcodes.OpReplaceDisks(instance_name=iname,
277 f8c9fa5c Iustin Pop
                                remote_node=node, disks=[],
278 f8c9fa5c Iustin Pop
                                mode=constants.REPLACE_DISK_CHG,
279 f8c9fa5c Iustin Pop
                                early_release=opts.early_release)
280 f8c9fa5c Iustin Pop
    jex.QueueJob(iname, op)
281 f8c9fa5c Iustin Pop
  results = jex.GetResults()
282 f8c9fa5c Iustin Pop
  bad_cnt = len([row for row in results if not row[0]])
283 f8c9fa5c Iustin Pop
  if bad_cnt == 0:
284 f8c9fa5c Iustin Pop
    ToStdout("All %d instance(s) failed over successfully.", len(results))
285 f8c9fa5c Iustin Pop
    rcode = constants.EXIT_SUCCESS
286 f8c9fa5c Iustin Pop
  else:
287 f8c9fa5c Iustin Pop
    ToStdout("There were errors during the failover:\n"
288 f8c9fa5c Iustin Pop
             "%d error(s) out of %d instance(s).", bad_cnt, len(results))
289 f8c9fa5c Iustin Pop
    rcode = constants.EXIT_FAILURE
290 f8c9fa5c Iustin Pop
  return rcode
291 a5bc662a Iustin Pop
292 a5bc662a Iustin Pop
293 c450e9b0 Iustin Pop
def FailoverNode(opts, args):
294 c450e9b0 Iustin Pop
  """Failover all primary instance on a node.
295 c450e9b0 Iustin Pop

296 ebf366ee Iustin Pop
  @param opts: the command line options selected by the user
297 ebf366ee Iustin Pop
  @type args: list
298 ebf366ee Iustin Pop
  @param args: should be an empty list
299 ebf366ee Iustin Pop
  @rtype: int
300 ebf366ee Iustin Pop
  @return: the desired exit code
301 ebf366ee Iustin Pop

302 c450e9b0 Iustin Pop
  """
303 479636a3 Iustin Pop
  cl = GetClient()
304 c450e9b0 Iustin Pop
  force = opts.force
305 c450e9b0 Iustin Pop
  selected_fields = ["name", "pinst_list"]
306 c450e9b0 Iustin Pop
307 2e7b8369 Iustin Pop
  # these fields are static data anyway, so it doesn't matter, but
308 2e7b8369 Iustin Pop
  # locking=True should be safer
309 2e7b8369 Iustin Pop
  result = cl.QueryNodes(names=args, fields=selected_fields,
310 77921a95 Iustin Pop
                         use_locking=False)
311 c450e9b0 Iustin Pop
  node, pinst = result[0]
312 c450e9b0 Iustin Pop
313 c450e9b0 Iustin Pop
  if not pinst:
314 3a24c527 Iustin Pop
    ToStderr("No primary instances on node %s, exiting.", node)
315 c450e9b0 Iustin Pop
    return 0
316 c450e9b0 Iustin Pop
317 c450e9b0 Iustin Pop
  pinst = utils.NiceSort(pinst)
318 c450e9b0 Iustin Pop
319 c450e9b0 Iustin Pop
  retcode = 0
320 c450e9b0 Iustin Pop
321 c450e9b0 Iustin Pop
  if not force and not AskUser("Fail over instance(s) %s?" %
322 c450e9b0 Iustin Pop
                               (",".join("'%s'" % name for name in pinst))):
323 c450e9b0 Iustin Pop
    return 2
324 c450e9b0 Iustin Pop
325 cb573a31 Iustin Pop
  jex = JobExecutor(cl=cl, opts=opts)
326 c450e9b0 Iustin Pop
  for iname in pinst:
327 c450e9b0 Iustin Pop
    op = opcodes.OpFailoverInstance(instance_name=iname,
328 c450e9b0 Iustin Pop
                                    ignore_consistency=opts.ignore_consistency)
329 479636a3 Iustin Pop
    jex.QueueJob(iname, op)
330 479636a3 Iustin Pop
  results = jex.GetResults()
331 479636a3 Iustin Pop
  bad_cnt = len([row for row in results if not row[0]])
332 479636a3 Iustin Pop
  if bad_cnt == 0:
333 479636a3 Iustin Pop
    ToStdout("All %d instance(s) failed over successfully.", len(results))
334 c450e9b0 Iustin Pop
  else:
335 3a24c527 Iustin Pop
    ToStdout("There were errors during the failover:\n"
336 479636a3 Iustin Pop
             "%d error(s) out of %d instance(s).", bad_cnt, len(results))
337 c450e9b0 Iustin Pop
  return retcode
338 c450e9b0 Iustin Pop
339 c450e9b0 Iustin Pop
340 40ef0ed6 Iustin Pop
def MigrateNode(opts, args):
341 40ef0ed6 Iustin Pop
  """Migrate all primary instance on a node.
342 40ef0ed6 Iustin Pop

343 40ef0ed6 Iustin Pop
  """
344 40ef0ed6 Iustin Pop
  cl = GetClient()
345 40ef0ed6 Iustin Pop
  force = opts.force
346 40ef0ed6 Iustin Pop
  selected_fields = ["name", "pinst_list"]
347 40ef0ed6 Iustin Pop
348 77921a95 Iustin Pop
  result = cl.QueryNodes(names=args, fields=selected_fields, use_locking=False)
349 40ef0ed6 Iustin Pop
  node, pinst = result[0]
350 40ef0ed6 Iustin Pop
351 40ef0ed6 Iustin Pop
  if not pinst:
352 40ef0ed6 Iustin Pop
    ToStdout("No primary instances on node %s, exiting." % node)
353 40ef0ed6 Iustin Pop
    return 0
354 40ef0ed6 Iustin Pop
355 40ef0ed6 Iustin Pop
  pinst = utils.NiceSort(pinst)
356 40ef0ed6 Iustin Pop
357 40ef0ed6 Iustin Pop
  if not force and not AskUser("Migrate instance(s) %s?" %
358 40ef0ed6 Iustin Pop
                               (",".join("'%s'" % name for name in pinst))):
359 40ef0ed6 Iustin Pop
    return 2
360 40ef0ed6 Iustin Pop
361 e71b9ef4 Iustin Pop
  # this should be removed once --non-live is deprecated
362 783a6c0b Iustin Pop
  if not opts.live and opts.migration_mode is not None:
363 e71b9ef4 Iustin Pop
    raise errors.OpPrereqError("Only one of the --non-live and "
364 783a6c0b Iustin Pop
                               "--migration-mode options can be passed",
365 e71b9ef4 Iustin Pop
                               errors.ECODE_INVAL)
366 e71b9ef4 Iustin Pop
  if not opts.live: # --non-live passed
367 8c35561f Iustin Pop
    mode = constants.HT_MIGRATION_NONLIVE
368 e71b9ef4 Iustin Pop
  else:
369 8c35561f Iustin Pop
    mode = opts.migration_mode
370 8c35561f Iustin Pop
  op = opcodes.OpMigrateNode(node_name=args[0], mode=mode)
371 400ca2f7 Iustin Pop
  SubmitOpCode(op, cl=cl, opts=opts)
372 40ef0ed6 Iustin Pop
373 40ef0ed6 Iustin Pop
374 a8083063 Iustin Pop
def ShowNodeConfig(opts, args):
375 a8083063 Iustin Pop
  """Show node information.
376 a8083063 Iustin Pop

377 ebf366ee Iustin Pop
  @param opts: the command line options selected by the user
378 ebf366ee Iustin Pop
  @type args: list
379 ebf366ee Iustin Pop
  @param args: should either be an empty list, in which case
380 ebf366ee Iustin Pop
      we show information about all nodes, or should contain
381 ebf366ee Iustin Pop
      a list of nodes to be queried for information
382 ebf366ee Iustin Pop
  @rtype: int
383 ebf366ee Iustin Pop
  @return: the desired exit code
384 ebf366ee Iustin Pop

385 a8083063 Iustin Pop
  """
386 2e7b8369 Iustin Pop
  cl = GetClient()
387 2e7b8369 Iustin Pop
  result = cl.QueryNodes(fields=["name", "pip", "sip",
388 0b2454b9 Iustin Pop
                                 "pinst_list", "sinst_list",
389 7b4978ad Iustin Pop
                                 "master_candidate", "drained", "offline",
390 7b4978ad Iustin Pop
                                 "master_capable", "vm_capable"],
391 77921a95 Iustin Pop
                         names=args, use_locking=False)
392 a8083063 Iustin Pop
393 0b2454b9 Iustin Pop
  for (name, primary_ip, secondary_ip, pinst, sinst,
394 7b4978ad Iustin Pop
       is_mc, drained, offline, master_capable, vm_capable) in result:
395 3a24c527 Iustin Pop
    ToStdout("Node name: %s", name)
396 3a24c527 Iustin Pop
    ToStdout("  primary ip: %s", primary_ip)
397 3a24c527 Iustin Pop
    ToStdout("  secondary ip: %s", secondary_ip)
398 0b2454b9 Iustin Pop
    ToStdout("  master candidate: %s", is_mc)
399 0b2454b9 Iustin Pop
    ToStdout("  drained: %s", drained)
400 0b2454b9 Iustin Pop
    ToStdout("  offline: %s", offline)
401 7b4978ad Iustin Pop
    ToStdout("  master_capable: %s", master_capable)
402 7b4978ad Iustin Pop
    ToStdout("  vm_capable: %s", vm_capable)
403 7b4978ad Iustin Pop
    if vm_capable:
404 7b4978ad Iustin Pop
      if pinst:
405 7b4978ad Iustin Pop
        ToStdout("  primary for instances:")
406 7b4978ad Iustin Pop
        for iname in utils.NiceSort(pinst):
407 7b4978ad Iustin Pop
          ToStdout("    - %s", iname)
408 7b4978ad Iustin Pop
      else:
409 7b4978ad Iustin Pop
        ToStdout("  primary for no instances")
410 7b4978ad Iustin Pop
      if sinst:
411 7b4978ad Iustin Pop
        ToStdout("  secondary for instances:")
412 7b4978ad Iustin Pop
        for iname in utils.NiceSort(sinst):
413 7b4978ad Iustin Pop
          ToStdout("    - %s", iname)
414 7b4978ad Iustin Pop
      else:
415 7b4978ad Iustin Pop
        ToStdout("  secondary for no instances")
416 a8083063 Iustin Pop
417 a8083063 Iustin Pop
  return 0
418 a8083063 Iustin Pop
419 a8083063 Iustin Pop
420 a8083063 Iustin Pop
def RemoveNode(opts, args):
421 ebf366ee Iustin Pop
  """Remove a node from the cluster.
422 ebf366ee Iustin Pop

423 ebf366ee Iustin Pop
  @param opts: the command line options selected by the user
424 ebf366ee Iustin Pop
  @type args: list
425 ebf366ee Iustin Pop
  @param args: should contain only one element, the name of
426 ebf366ee Iustin Pop
      the node to be removed
427 ebf366ee Iustin Pop
  @rtype: int
428 ebf366ee Iustin Pop
  @return: the desired exit code
429 ebf366ee Iustin Pop

430 ebf366ee Iustin Pop
  """
431 a8083063 Iustin Pop
  op = opcodes.OpRemoveNode(node_name=args[0])
432 400ca2f7 Iustin Pop
  SubmitOpCode(op, opts=opts)
433 ebf366ee Iustin Pop
  return 0
434 a8083063 Iustin Pop
435 a8083063 Iustin Pop
436 f5118ade Iustin Pop
def PowercycleNode(opts, args):
437 f5118ade Iustin Pop
  """Remove a node from the cluster.
438 f5118ade Iustin Pop

439 f5118ade Iustin Pop
  @param opts: the command line options selected by the user
440 f5118ade Iustin Pop
  @type args: list
441 f5118ade Iustin Pop
  @param args: should contain only one element, the name of
442 f5118ade Iustin Pop
      the node to be removed
443 f5118ade Iustin Pop
  @rtype: int
444 f5118ade Iustin Pop
  @return: the desired exit code
445 f5118ade Iustin Pop

446 f5118ade Iustin Pop
  """
447 f5118ade Iustin Pop
  node = args[0]
448 f5118ade Iustin Pop
  if (not opts.confirm and
449 f5118ade Iustin Pop
      not AskUser("Are you sure you want to hard powercycle node %s?" % node)):
450 f5118ade Iustin Pop
    return 2
451 f5118ade Iustin Pop
452 f5118ade Iustin Pop
  op = opcodes.OpPowercycleNode(node_name=node, force=opts.force)
453 400ca2f7 Iustin Pop
  result = SubmitOpCode(op, opts=opts)
454 48418fea Iustin Pop
  if result:
455 48418fea Iustin Pop
    ToStderr(result)
456 f5118ade Iustin Pop
  return 0
457 f5118ade Iustin Pop
458 f5118ade Iustin Pop
459 abefdcff René Nussbaumer
def PowerNode(opts, args):
460 abefdcff René Nussbaumer
  """Change/ask power state of a node.
461 abefdcff René Nussbaumer

462 abefdcff René Nussbaumer
  @param opts: the command line options selected by the user
463 abefdcff René Nussbaumer
  @type args: list
464 abefdcff René Nussbaumer
  @param args: should contain only one element, the name of
465 abefdcff René Nussbaumer
      the node to be removed
466 abefdcff René Nussbaumer
  @rtype: int
467 abefdcff René Nussbaumer
  @return: the desired exit code
468 abefdcff René Nussbaumer

469 abefdcff René Nussbaumer
  """
470 abefdcff René Nussbaumer
  command = args[0]
471 abefdcff René Nussbaumer
  node = args[1]
472 abefdcff René Nussbaumer
473 abefdcff René Nussbaumer
  if command not in _LIST_POWER_COMMANDS:
474 abefdcff René Nussbaumer
    ToStderr("power subcommand %s not supported." % command)
475 abefdcff René Nussbaumer
    return constants.EXIT_FAILURE
476 abefdcff René Nussbaumer
477 abefdcff René Nussbaumer
  oob_command = "power-%s" % command
478 abefdcff René Nussbaumer
479 792af3ad René Nussbaumer
  op = opcodes.OpOobCommand(node_name=node, command=oob_command)
480 abefdcff René Nussbaumer
  result = SubmitOpCode(op, opts=opts)
481 abefdcff René Nussbaumer
  if result:
482 abefdcff René Nussbaumer
    if oob_command == constants.OOB_POWER_STATUS:
483 abefdcff René Nussbaumer
      text = "The machine is %spowered"
484 abefdcff René Nussbaumer
      if result[constants.OOB_POWER_STATUS_POWERED]:
485 abefdcff René Nussbaumer
        result = text % ""
486 abefdcff René Nussbaumer
      else:
487 abefdcff René Nussbaumer
        result = text % "not "
488 abefdcff René Nussbaumer
    ToStderr(result)
489 abefdcff René Nussbaumer
490 abefdcff René Nussbaumer
  return constants.EXIT_SUCCESS
491 abefdcff René Nussbaumer
492 abefdcff René Nussbaumer
493 dcb93971 Michael Hanselmann
def ListVolumes(opts, args):
494 dcb93971 Michael Hanselmann
  """List logical volumes on node(s).
495 dcb93971 Michael Hanselmann

496 ebf366ee Iustin Pop
  @param opts: the command line options selected by the user
497 ebf366ee Iustin Pop
  @type args: list
498 ebf366ee Iustin Pop
  @param args: should either be an empty list, in which case
499 ebf366ee Iustin Pop
      we list data for all nodes, or contain a list of nodes
500 ebf366ee Iustin Pop
      to display data only for those
501 ebf366ee Iustin Pop
  @rtype: int
502 ebf366ee Iustin Pop
  @return: the desired exit code
503 ebf366ee Iustin Pop

504 dcb93971 Michael Hanselmann
  """
505 a4ebd726 Michael Hanselmann
  selected_fields = ParseFields(opts.output, _LIST_VOL_DEF_FIELDS)
506 dcb93971 Michael Hanselmann
507 dcb93971 Michael Hanselmann
  op = opcodes.OpQueryNodeVolumes(nodes=args, output_fields=selected_fields)
508 400ca2f7 Iustin Pop
  output = SubmitOpCode(op, opts=opts)
509 dcb93971 Michael Hanselmann
510 dcb93971 Michael Hanselmann
  if not opts.no_headers:
511 137161c9 Michael Hanselmann
    headers = {"node": "Node", "phys": "PhysDev",
512 137161c9 Michael Hanselmann
               "vg": "VG", "name": "Name",
513 137161c9 Michael Hanselmann
               "size": "Size", "instance": "Instance"}
514 137161c9 Michael Hanselmann
  else:
515 137161c9 Michael Hanselmann
    headers = None
516 137161c9 Michael Hanselmann
517 9fbfbb7b Iustin Pop
  unitfields = ["size"]
518 137161c9 Michael Hanselmann
519 137161c9 Michael Hanselmann
  numfields = ["size"]
520 137161c9 Michael Hanselmann
521 16be8703 Iustin Pop
  data = GenerateTable(separator=opts.separator, headers=headers,
522 16be8703 Iustin Pop
                       fields=selected_fields, unitfields=unitfields,
523 9fbfbb7b Iustin Pop
                       numfields=numfields, data=output, units=opts.units)
524 16be8703 Iustin Pop
525 16be8703 Iustin Pop
  for line in data:
526 3a24c527 Iustin Pop
    ToStdout(line)
527 dcb93971 Michael Hanselmann
528 dcb93971 Michael Hanselmann
  return 0
529 dcb93971 Michael Hanselmann
530 dcb93971 Michael Hanselmann
531 9b94905f Iustin Pop
def ListStorage(opts, args):
532 4007f57d Michael Hanselmann
  """List physical volumes on node(s).
533 4007f57d Michael Hanselmann

534 4007f57d Michael Hanselmann
  @param opts: the command line options selected by the user
535 4007f57d Michael Hanselmann
  @type args: list
536 4007f57d Michael Hanselmann
  @param args: should either be an empty list, in which case
537 4007f57d Michael Hanselmann
      we list data for all nodes, or contain a list of nodes
538 4007f57d Michael Hanselmann
      to display data only for those
539 4007f57d Michael Hanselmann
  @rtype: int
540 4007f57d Michael Hanselmann
  @return: the desired exit code
541 4007f57d Michael Hanselmann

542 4007f57d Michael Hanselmann
  """
543 53548798 Michael Hanselmann
  # TODO: Default to ST_FILE if LVM is disabled on the cluster
544 53548798 Michael Hanselmann
  if opts.user_storage_type is None:
545 53548798 Michael Hanselmann
    opts.user_storage_type = constants.ST_LVM_PV
546 53548798 Michael Hanselmann
547 86f5eae3 Michael Hanselmann
  storage_type = ConvertStorageType(opts.user_storage_type)
548 53548798 Michael Hanselmann
549 a4ebd726 Michael Hanselmann
  selected_fields = ParseFields(opts.output, _LIST_STOR_DEF_FIELDS)
550 4007f57d Michael Hanselmann
551 4007f57d Michael Hanselmann
  op = opcodes.OpQueryNodeStorage(nodes=args,
552 53548798 Michael Hanselmann
                                  storage_type=storage_type,
553 4007f57d Michael Hanselmann
                                  output_fields=selected_fields)
554 400ca2f7 Iustin Pop
  output = SubmitOpCode(op, opts=opts)
555 4007f57d Michael Hanselmann
556 4007f57d Michael Hanselmann
  if not opts.no_headers:
557 4007f57d Michael Hanselmann
    headers = {
558 620a85fd Iustin Pop
      constants.SF_NODE: "Node",
559 620a85fd Iustin Pop
      constants.SF_TYPE: "Type",
560 4007f57d Michael Hanselmann
      constants.SF_NAME: "Name",
561 4007f57d Michael Hanselmann
      constants.SF_SIZE: "Size",
562 4007f57d Michael Hanselmann
      constants.SF_USED: "Used",
563 4007f57d Michael Hanselmann
      constants.SF_FREE: "Free",
564 4007f57d Michael Hanselmann
      constants.SF_ALLOCATABLE: "Allocatable",
565 4007f57d Michael Hanselmann
      }
566 4007f57d Michael Hanselmann
  else:
567 4007f57d Michael Hanselmann
    headers = None
568 4007f57d Michael Hanselmann
569 4007f57d Michael Hanselmann
  unitfields = [constants.SF_SIZE, constants.SF_USED, constants.SF_FREE]
570 4007f57d Michael Hanselmann
  numfields = [constants.SF_SIZE, constants.SF_USED, constants.SF_FREE]
571 4007f57d Michael Hanselmann
572 dc09c3cf Iustin Pop
  # change raw values to nicer strings
573 dc09c3cf Iustin Pop
  for row in output:
574 dc09c3cf Iustin Pop
    for idx, field in enumerate(selected_fields):
575 dc09c3cf Iustin Pop
      val = row[idx]
576 dc09c3cf Iustin Pop
      if field == constants.SF_ALLOCATABLE:
577 dc09c3cf Iustin Pop
        if val:
578 dc09c3cf Iustin Pop
          val = "Y"
579 dc09c3cf Iustin Pop
        else:
580 dc09c3cf Iustin Pop
          val = "N"
581 dc09c3cf Iustin Pop
      row[idx] = str(val)
582 dc09c3cf Iustin Pop
583 4007f57d Michael Hanselmann
  data = GenerateTable(separator=opts.separator, headers=headers,
584 4007f57d Michael Hanselmann
                       fields=selected_fields, unitfields=unitfields,
585 4007f57d Michael Hanselmann
                       numfields=numfields, data=output, units=opts.units)
586 4007f57d Michael Hanselmann
587 4007f57d Michael Hanselmann
  for line in data:
588 4007f57d Michael Hanselmann
    ToStdout(line)
589 4007f57d Michael Hanselmann
590 4007f57d Michael Hanselmann
  return 0
591 4007f57d Michael Hanselmann
592 4007f57d Michael Hanselmann
593 9b94905f Iustin Pop
def ModifyStorage(opts, args):
594 0e89fc2d Michael Hanselmann
  """Modify storage volume on a node.
595 0e89fc2d Michael Hanselmann

596 0e89fc2d Michael Hanselmann
  @param opts: the command line options selected by the user
597 0e89fc2d Michael Hanselmann
  @type args: list
598 0e89fc2d Michael Hanselmann
  @param args: should contain 3 items: node name, storage type and volume name
599 0e89fc2d Michael Hanselmann
  @rtype: int
600 0e89fc2d Michael Hanselmann
  @return: the desired exit code
601 0e89fc2d Michael Hanselmann

602 0e89fc2d Michael Hanselmann
  """
603 0e89fc2d Michael Hanselmann
  (node_name, user_storage_type, volume_name) = args
604 0e89fc2d Michael Hanselmann
605 86f5eae3 Michael Hanselmann
  storage_type = ConvertStorageType(user_storage_type)
606 0e89fc2d Michael Hanselmann
607 0e89fc2d Michael Hanselmann
  changes = {}
608 0e89fc2d Michael Hanselmann
609 0e89fc2d Michael Hanselmann
  if opts.allocatable is not None:
610 e7b61bb0 Iustin Pop
    changes[constants.SF_ALLOCATABLE] = opts.allocatable
611 0e89fc2d Michael Hanselmann
612 0e89fc2d Michael Hanselmann
  if changes:
613 0e89fc2d Michael Hanselmann
    op = opcodes.OpModifyNodeStorage(node_name=node_name,
614 0e89fc2d Michael Hanselmann
                                     storage_type=storage_type,
615 0e89fc2d Michael Hanselmann
                                     name=volume_name,
616 0e89fc2d Michael Hanselmann
                                     changes=changes)
617 400ca2f7 Iustin Pop
    SubmitOpCode(op, opts=opts)
618 620a85fd Iustin Pop
  else:
619 620a85fd Iustin Pop
    ToStderr("No changes to perform, exiting.")
620 0e89fc2d Michael Hanselmann
621 0e89fc2d Michael Hanselmann
622 9b94905f Iustin Pop
def RepairStorage(opts, args):
623 1e3463f1 Michael Hanselmann
  """Repairs a storage volume on a node.
624 1e3463f1 Michael Hanselmann

625 1e3463f1 Michael Hanselmann
  @param opts: the command line options selected by the user
626 1e3463f1 Michael Hanselmann
  @type args: list
627 1e3463f1 Michael Hanselmann
  @param args: should contain 3 items: node name, storage type and volume name
628 1e3463f1 Michael Hanselmann
  @rtype: int
629 1e3463f1 Michael Hanselmann
  @return: the desired exit code
630 1e3463f1 Michael Hanselmann

631 1e3463f1 Michael Hanselmann
  """
632 1e3463f1 Michael Hanselmann
  (node_name, user_storage_type, volume_name) = args
633 1e3463f1 Michael Hanselmann
634 1e3463f1 Michael Hanselmann
  storage_type = ConvertStorageType(user_storage_type)
635 1e3463f1 Michael Hanselmann
636 1e3463f1 Michael Hanselmann
  op = opcodes.OpRepairNodeStorage(node_name=node_name,
637 1e3463f1 Michael Hanselmann
                                   storage_type=storage_type,
638 7e9c6a78 Iustin Pop
                                   name=volume_name,
639 7e9c6a78 Iustin Pop
                                   ignore_consistency=opts.ignore_consistency)
640 400ca2f7 Iustin Pop
  SubmitOpCode(op, opts=opts)
641 1e3463f1 Michael Hanselmann
642 1e3463f1 Michael Hanselmann
643 b31c8676 Iustin Pop
def SetNodeParams(opts, args):
644 b31c8676 Iustin Pop
  """Modifies a node.
645 b31c8676 Iustin Pop

646 b31c8676 Iustin Pop
  @param opts: the command line options selected by the user
647 b31c8676 Iustin Pop
  @type args: list
648 b31c8676 Iustin Pop
  @param args: should contain only one element, the node name
649 b31c8676 Iustin Pop
  @rtype: int
650 b31c8676 Iustin Pop
  @return: the desired exit code
651 b31c8676 Iustin Pop

652 b31c8676 Iustin Pop
  """
653 53919782 Iustin Pop
  all_changes = [opts.master_candidate, opts.drained, opts.offline,
654 4e37f591 René Nussbaumer
                 opts.master_capable, opts.vm_capable, opts.secondary_ip,
655 4e37f591 René Nussbaumer
                 opts.ndparams]
656 53919782 Iustin Pop
  if all_changes.count(None) == len(all_changes):
657 b31c8676 Iustin Pop
    ToStderr("Please give at least one of the parameters.")
658 b31c8676 Iustin Pop
    return 1
659 b31c8676 Iustin Pop
660 b31c8676 Iustin Pop
  op = opcodes.OpSetNodeParams(node_name=args[0],
661 e7b61bb0 Iustin Pop
                               master_candidate=opts.master_candidate,
662 e7b61bb0 Iustin Pop
                               offline=opts.offline,
663 e7b61bb0 Iustin Pop
                               drained=opts.drained,
664 f91e255a Iustin Pop
                               master_capable=opts.master_capable,
665 53919782 Iustin Pop
                               vm_capable=opts.vm_capable,
666 4d32c211 Guido Trotter
                               secondary_ip=opts.secondary_ip,
667 4c61d894 Iustin Pop
                               force=opts.force,
668 4e37f591 René Nussbaumer
                               ndparams=opts.ndparams,
669 4c61d894 Iustin Pop
                               auto_promote=opts.auto_promote)
670 b31c8676 Iustin Pop
671 b31c8676 Iustin Pop
  # even if here we process the result, we allow submit only
672 b31c8676 Iustin Pop
  result = SubmitOrSend(op, opts)
673 b31c8676 Iustin Pop
674 b31c8676 Iustin Pop
  if result:
675 b31c8676 Iustin Pop
    ToStdout("Modified node %s", args[0])
676 b31c8676 Iustin Pop
    for param, data in result:
677 b31c8676 Iustin Pop
      ToStdout(" - %-5s -> %s", param, data)
678 b31c8676 Iustin Pop
  return 0
679 b31c8676 Iustin Pop
680 b31c8676 Iustin Pop
681 a8083063 Iustin Pop
commands = {
682 6ea815cf Iustin Pop
  'add': (
683 6ea815cf Iustin Pop
    AddNode, [ArgHost(min=1, max=1)],
684 3ef51126 René Nussbaumer
    [SECONDARY_IP_OPT, READD_OPT, NOSSH_KEYCHECK_OPT, NONODE_SETUP_OPT,
685 fd3d37b6 Iustin Pop
     VERBOSE_OPT, NODEGROUP_OPT, PRIORITY_OPT, CAPAB_MASTER_OPT,
686 4e37f591 René Nussbaumer
     CAPAB_VM_OPT, NODE_PARAMS_OPT],
687 3ef51126 René Nussbaumer
    "[-s ip] [--readd] [--no-ssh-key-check] [--no-node-setup]  [--verbose] "
688 2e6469a1 René Nussbaumer
    " <node_name>",
689 6ea815cf Iustin Pop
    "Add a node to the cluster"),
690 6ea815cf Iustin Pop
  'evacuate': (
691 f8c9fa5c Iustin Pop
    EvacuateNode, [ArgNode(min=1)],
692 aa06f8c6 Michael Hanselmann
    [FORCE_OPT, IALLOCATOR_OPT, NEW_SECONDARY_OPT, EARLY_RELEASE_OPT,
693 aa06f8c6 Michael Hanselmann
     PRIORITY_OPT],
694 6ea815cf Iustin Pop
    "[-f] {-I <iallocator> | -n <dst>} <node>",
695 6ea815cf Iustin Pop
    "Relocate the secondary instances from a node"
696 6ea815cf Iustin Pop
    " to other nodes (only for instances with drbd disk template)"),
697 6ea815cf Iustin Pop
  'failover': (
698 aa06f8c6 Michael Hanselmann
    FailoverNode, ARGS_ONE_NODE, [FORCE_OPT, IGNORE_CONSIST_OPT, PRIORITY_OPT],
699 6ea815cf Iustin Pop
    "[-f] <node>",
700 6ea815cf Iustin Pop
    "Stops the primary instances on a node and start them on their"
701 6ea815cf Iustin Pop
    " secondary node (only for instances with drbd disk template)"),
702 6ea815cf Iustin Pop
  'migrate': (
703 aa06f8c6 Michael Hanselmann
    MigrateNode, ARGS_ONE_NODE,
704 aa06f8c6 Michael Hanselmann
    [FORCE_OPT, NONLIVE_OPT, MIGRATION_MODE_OPT, PRIORITY_OPT],
705 6ea815cf Iustin Pop
    "[-f] <node>",
706 6ea815cf Iustin Pop
    "Migrate all the primary instance on a node away from it"
707 6ea815cf Iustin Pop
    " (only for instances of type drbd)"),
708 6ea815cf Iustin Pop
  'info': (
709 064c21f8 Iustin Pop
    ShowNodeConfig, ARGS_MANY_NODES, [],
710 6ea815cf Iustin Pop
    "[<node_name>...]", "Show information about the node(s)"),
711 6ea815cf Iustin Pop
  'list': (
712 6ea815cf Iustin Pop
    ListNodes, ARGS_MANY_NODES,
713 7f5443a0 Michael Hanselmann
    [NOHDR_OPT, SEP_OPT, USEUNITS_OPT, FIELDS_OPT],
714 6ea815cf Iustin Pop
    "[nodes...]",
715 7f5443a0 Michael Hanselmann
    "Lists the nodes in the cluster. The available fields can be shown using"
716 7f5443a0 Michael Hanselmann
    " the \"list-fields\" command (see the man page for details)."
717 7f5443a0 Michael Hanselmann
    " The default field list is (in order): %s." %
718 7f5443a0 Michael Hanselmann
    utils.CommaJoin(_LIST_DEF_FIELDS)),
719 7f5443a0 Michael Hanselmann
  "list-fields": (
720 7f5443a0 Michael Hanselmann
    ListNodeFields, [ArgUnknown()],
721 7f5443a0 Michael Hanselmann
    [NOHDR_OPT, SEP_OPT],
722 7f5443a0 Michael Hanselmann
    "[fields...]",
723 7f5443a0 Michael Hanselmann
    "Lists all available fields for nodes"),
724 6ea815cf Iustin Pop
  'modify': (
725 6ea815cf Iustin Pop
    SetNodeParams, ARGS_ONE_NODE,
726 53919782 Iustin Pop
    [FORCE_OPT, SUBMIT_OPT, MC_OPT, DRAINED_OPT, OFFLINE_OPT,
727 4d32c211 Guido Trotter
     CAPAB_MASTER_OPT, CAPAB_VM_OPT, SECONDARY_IP_OPT,
728 4e37f591 René Nussbaumer
     AUTO_PROMOTE_OPT, DRY_RUN_OPT, PRIORITY_OPT, NODE_PARAMS_OPT],
729 6ea815cf Iustin Pop
    "<node_name>", "Alters the parameters of a node"),
730 6ea815cf Iustin Pop
  'powercycle': (
731 6ea815cf Iustin Pop
    PowercycleNode, ARGS_ONE_NODE,
732 aa06f8c6 Michael Hanselmann
    [FORCE_OPT, CONFIRM_OPT, DRY_RUN_OPT, PRIORITY_OPT],
733 6ea815cf Iustin Pop
    "<node_name>", "Tries to forcefully powercycle a node"),
734 abefdcff René Nussbaumer
  'power': (
735 abefdcff René Nussbaumer
    PowerNode,
736 abefdcff René Nussbaumer
    [ArgChoice(min=1, max=1, choices=_LIST_POWER_COMMANDS),
737 abefdcff René Nussbaumer
     ArgNode(min=1, max=1)],
738 abefdcff René Nussbaumer
    [], "on|off|cycle|status <node>",
739 abefdcff René Nussbaumer
    "Change power state of node by calling out-of-band helper."),
740 6ea815cf Iustin Pop
  'remove': (
741 aa06f8c6 Michael Hanselmann
    RemoveNode, ARGS_ONE_NODE, [DRY_RUN_OPT, PRIORITY_OPT],
742 6ea815cf Iustin Pop
    "<node_name>", "Removes a node from the cluster"),
743 6ea815cf Iustin Pop
  'volumes': (
744 6ea815cf Iustin Pop
    ListVolumes, [ArgNode()],
745 aa06f8c6 Michael Hanselmann
    [NOHDR_OPT, SEP_OPT, USEUNITS_OPT, FIELDS_OPT, PRIORITY_OPT],
746 6ea815cf Iustin Pop
    "[<node_name>...]", "List logical volumes on node(s)"),
747 9b94905f Iustin Pop
  'list-storage': (
748 9b94905f Iustin Pop
    ListStorage, ARGS_MANY_NODES,
749 aa06f8c6 Michael Hanselmann
    [NOHDR_OPT, SEP_OPT, USEUNITS_OPT, FIELDS_OPT, _STORAGE_TYPE_OPT,
750 aa06f8c6 Michael Hanselmann
     PRIORITY_OPT],
751 620a85fd Iustin Pop
    "[<node_name>...]", "List physical volumes on node(s). The available"
752 620a85fd Iustin Pop
    " fields are (see the man page for details): %s." %
753 1f864b60 Iustin Pop
    (utils.CommaJoin(_LIST_STOR_HEADERS))),
754 9b94905f Iustin Pop
  'modify-storage': (
755 9b94905f Iustin Pop
    ModifyStorage,
756 6ea815cf Iustin Pop
    [ArgNode(min=1, max=1),
757 6ea815cf Iustin Pop
     ArgChoice(min=1, max=1, choices=_MODIFIABLE_STORAGE_TYPES),
758 6ea815cf Iustin Pop
     ArgFile(min=1, max=1)],
759 aa06f8c6 Michael Hanselmann
    [ALLOCATABLE_OPT, DRY_RUN_OPT, PRIORITY_OPT],
760 064c21f8 Iustin Pop
    "<node_name> <storage_type> <name>", "Modify storage volume on a node"),
761 9b94905f Iustin Pop
  'repair-storage': (
762 9b94905f Iustin Pop
    RepairStorage,
763 6ea815cf Iustin Pop
    [ArgNode(min=1, max=1),
764 6ea815cf Iustin Pop
     ArgChoice(min=1, max=1, choices=_REPAIRABLE_STORAGE_TYPES),
765 6ea815cf Iustin Pop
     ArgFile(min=1, max=1)],
766 aa06f8c6 Michael Hanselmann
    [IGNORE_CONSIST_OPT, DRY_RUN_OPT, PRIORITY_OPT],
767 6ea815cf Iustin Pop
    "<node_name> <storage_type> <name>",
768 6ea815cf Iustin Pop
    "Repairs a storage volume on a node"),
769 6ea815cf Iustin Pop
  'list-tags': (
770 064c21f8 Iustin Pop
    ListTags, ARGS_ONE_NODE, [],
771 6ea815cf Iustin Pop
    "<node_name>", "List the tags of the given node"),
772 6ea815cf Iustin Pop
  'add-tags': (
773 aa06f8c6 Michael Hanselmann
    AddTags, [ArgNode(min=1, max=1), ArgUnknown()], [TAG_SRC_OPT, PRIORITY_OPT],
774 6ea815cf Iustin Pop
    "<node_name> tag...", "Add tags to the given node"),
775 6ea815cf Iustin Pop
  'remove-tags': (
776 aa06f8c6 Michael Hanselmann
    RemoveTags, [ArgNode(min=1, max=1), ArgUnknown()],
777 aa06f8c6 Michael Hanselmann
    [TAG_SRC_OPT, PRIORITY_OPT],
778 6ea815cf Iustin Pop
    "<node_name> tag...", "Remove tags from the given node"),
779 a8083063 Iustin Pop
  }
780 a8083063 Iustin Pop
781 a8083063 Iustin Pop
782 37494fa4 Michael Hanselmann
def Main():
783 37494fa4 Michael Hanselmann
  return GenericMain(commands, override={"tag_type": constants.TAG_NODE})