Statistics
| Branch: | Tag: | Revision:

root / scripts / gnt-node @ f34901f8

History | View | Annotate | Download (13.3 kB)

1 a8083063 Iustin Pop
#!/usr/bin/python
2 a8083063 Iustin Pop
#
3 a8083063 Iustin Pop
4 e7c6e02b Michael Hanselmann
# Copyright (C) 2006, 2007, 2008 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 a8083063 Iustin Pop
29 a8083063 Iustin Pop
from ganeti.cli import *
30 a8083063 Iustin Pop
from ganeti import opcodes
31 a8083063 Iustin Pop
from ganeti import utils
32 846baef9 Iustin Pop
from ganeti import constants
33 c450e9b0 Iustin Pop
from ganeti import errors
34 827f753e Guido Trotter
from ganeti import bootstrap
35 a8083063 Iustin Pop
36 a8083063 Iustin Pop
37 ebf366ee Iustin Pop
#: default list of field for L{ListNodes}
38 48c4dfa8 Iustin Pop
_LIST_DEF_FIELDS = [
39 48c4dfa8 Iustin Pop
  "name", "dtotal", "dfree",
40 48c4dfa8 Iustin Pop
  "mtotal", "mnode", "mfree",
41 48c4dfa8 Iustin Pop
  "pinst_cnt", "sinst_cnt",
42 48c4dfa8 Iustin Pop
  ]
43 48c4dfa8 Iustin Pop
44 51144e33 Michael Hanselmann
45 4331f6cd Michael Hanselmann
@UsesRPC
46 a8083063 Iustin Pop
def AddNode(opts, args):
47 ebf366ee Iustin Pop
  """Add a node to the cluster.
48 ebf366ee Iustin Pop
49 ebf366ee Iustin Pop
  @param opts: the command line options selected by the user
50 ebf366ee Iustin Pop
  @type args: list
51 ebf366ee Iustin Pop
  @param args: should contain only one element, the new node name
52 ebf366ee Iustin Pop
  @rtype: int
53 ebf366ee Iustin Pop
  @return: the desired exit code
54 05ccd983 Guido Trotter
55 05ccd983 Guido Trotter
  """
56 05ccd983 Guido Trotter
  dns_data = utils.HostInfo(args[0])
57 05ccd983 Guido Trotter
  node = dns_data.name
58 05ccd983 Guido Trotter
59 05ccd983 Guido Trotter
  if not opts.readd:
60 05ccd983 Guido Trotter
    op = opcodes.OpQueryNodes(output_fields=['name'], names=[node])
61 05ccd983 Guido Trotter
    try:
62 05ccd983 Guido Trotter
      output = SubmitOpCode(op)
63 05ccd983 Guido Trotter
    except (errors.OpPrereqError, errors.OpExecError):
64 05ccd983 Guido Trotter
      pass
65 05ccd983 Guido Trotter
    else:
66 3a24c527 Iustin Pop
      ToStderr("Node %s already in the cluster (as %s)"
67 3a24c527 Iustin Pop
               " - please use --readd", args[0], output[0][0])
68 05ccd983 Guido Trotter
      return 1
69 05ccd983 Guido Trotter
70 3a24c527 Iustin Pop
  ToStderr("-- WARNING -- \n"
71 3a24c527 Iustin Pop
           "Performing this operation is going to replace the ssh daemon"
72 3a24c527 Iustin Pop
           " keypair\n"
73 3a24c527 Iustin Pop
           "on the target machine (%s) with the ones of the"
74 3a24c527 Iustin Pop
           " current one\n"
75 3a24c527 Iustin Pop
           "and grant full intra-cluster ssh root access to/from it\n", node)
76 05ccd983 Guido Trotter
77 c4b6c29c Michael Hanselmann
  bootstrap.SetupNodeDaemon(node, opts.ssh_key_check)
78 827f753e Guido Trotter
79 e7c6e02b Michael Hanselmann
  op = opcodes.OpAddNode(node_name=args[0], secondary_ip=opts.secondary_ip,
80 e7c6e02b Michael Hanselmann
                         readd=opts.readd)
81 a8083063 Iustin Pop
  SubmitOpCode(op)
82 a8083063 Iustin Pop
83 a8083063 Iustin Pop
84 a8083063 Iustin Pop
def ListNodes(opts, args):
85 a8083063 Iustin Pop
  """List nodes and their properties.
86 a8083063 Iustin Pop
87 ebf366ee Iustin Pop
  @param opts: the command line options selected by the user
88 ebf366ee Iustin Pop
  @type args: list
89 ebf366ee Iustin Pop
  @param args: should be an empty list
90 ebf366ee Iustin Pop
  @rtype: int
91 ebf366ee Iustin Pop
  @return: the desired exit code
92 ebf366ee Iustin Pop
93 a8083063 Iustin Pop
  """
94 a8083063 Iustin Pop
  if opts.output is None:
95 48c4dfa8 Iustin Pop
    selected_fields = _LIST_DEF_FIELDS
96 48c4dfa8 Iustin Pop
  elif opts.output.startswith("+"):
97 48c4dfa8 Iustin Pop
    selected_fields = _LIST_DEF_FIELDS + opts.output[1:].split(",")
98 a8083063 Iustin Pop
  else:
99 a8083063 Iustin Pop
    selected_fields = opts.output.split(",")
100 a8083063 Iustin Pop
101 c54784d9 Michael Hanselmann
  output = GetClient().QueryNodes([], selected_fields)
102 a8083063 Iustin Pop
103 a8083063 Iustin Pop
  if not opts.no_headers:
104 e8a4c138 Iustin Pop
    headers = {
105 e8a4c138 Iustin Pop
      "name": "Node", "pinst_cnt": "Pinst", "sinst_cnt": "Sinst",
106 e8a4c138 Iustin Pop
      "pinst_list": "PriInstances", "sinst_list": "SecInstances",
107 e8a4c138 Iustin Pop
      "pip": "PrimaryIP", "sip": "SecondaryIP",
108 e8a4c138 Iustin Pop
      "dtotal": "DTotal", "dfree": "DFree",
109 e8a4c138 Iustin Pop
      "mtotal": "MTotal", "mnode": "MNode", "mfree": "MFree",
110 e8a4c138 Iustin Pop
      "bootid": "BootID",
111 e8a4c138 Iustin Pop
      "ctotal": "CTotal",
112 130a6a6f Iustin Pop
      "tags": "Tags",
113 38d7239a Iustin Pop
      "serial_no": "SerialNo",
114 e8a4c138 Iustin Pop
      }
115 137161c9 Michael Hanselmann
  else:
116 137161c9 Michael Hanselmann
    headers = None
117 137161c9 Michael Hanselmann
118 9fbfbb7b Iustin Pop
  unitfields = ["dtotal", "dfree", "mtotal", "mnode", "mfree"]
119 137161c9 Michael Hanselmann
120 ec223efb Iustin Pop
  numfields = ["dtotal", "dfree",
121 ec223efb Iustin Pop
               "mtotal", "mnode", "mfree",
122 e8a4c138 Iustin Pop
               "pinst_cnt", "sinst_cnt",
123 38d7239a Iustin Pop
               "ctotal", "serial_no"]
124 ec223efb Iustin Pop
125 130a6a6f Iustin Pop
  list_type_fields = ("pinst_list", "sinst_list", "tags")
126 ec223efb Iustin Pop
  # change raw values to nicer strings
127 ec223efb Iustin Pop
  for row in output:
128 ec223efb Iustin Pop
    for idx, field in enumerate(selected_fields):
129 ec223efb Iustin Pop
      val = row[idx]
130 130a6a6f Iustin Pop
      if field in list_type_fields:
131 ec223efb Iustin Pop
        val = ",".join(val)
132 ec223efb Iustin Pop
      elif val is None:
133 ec223efb Iustin Pop
        val = "?"
134 ec223efb Iustin Pop
      row[idx] = str(val)
135 137161c9 Michael Hanselmann
136 16be8703 Iustin Pop
  data = GenerateTable(separator=opts.separator, headers=headers,
137 16be8703 Iustin Pop
                       fields=selected_fields, unitfields=unitfields,
138 9fbfbb7b Iustin Pop
                       numfields=numfields, data=output, units=opts.units)
139 16be8703 Iustin Pop
  for line in data:
140 3a24c527 Iustin Pop
    ToStdout(line)
141 a8083063 Iustin Pop
142 a8083063 Iustin Pop
  return 0
143 a8083063 Iustin Pop
144 a8083063 Iustin Pop
145 a5bc662a Iustin Pop
def EvacuateNode(opts, args):
146 a5bc662a Iustin Pop
  """Relocate all secondary instance from a node.
147 a5bc662a Iustin Pop
148 ebf366ee Iustin Pop
  @param opts: the command line options selected by the user
149 ebf366ee Iustin Pop
  @type args: list
150 ebf366ee Iustin Pop
  @param args: should be an empty list
151 ebf366ee Iustin Pop
  @rtype: int
152 ebf366ee Iustin Pop
  @return: the desired exit code
153 ebf366ee Iustin Pop
154 a5bc662a Iustin Pop
  """
155 a5bc662a Iustin Pop
  force = opts.force
156 a5bc662a Iustin Pop
  selected_fields = ["name", "sinst_list"]
157 a5bc662a Iustin Pop
  src_node, dst_node = args
158 a5bc662a Iustin Pop
159 a5bc662a Iustin Pop
  op = opcodes.OpQueryNodes(output_fields=selected_fields, names=[src_node])
160 a5bc662a Iustin Pop
  result = SubmitOpCode(op)
161 a5bc662a Iustin Pop
  src_node, sinst = result[0]
162 a5bc662a Iustin Pop
  op = opcodes.OpQueryNodes(output_fields=["name"], names=[dst_node])
163 a5bc662a Iustin Pop
  result = SubmitOpCode(op)
164 a5bc662a Iustin Pop
  dst_node = result[0][0]
165 a5bc662a Iustin Pop
166 a5bc662a Iustin Pop
  if src_node == dst_node:
167 a5bc662a Iustin Pop
    raise errors.OpPrereqError("Evacuate node needs different source and"
168 a5bc662a Iustin Pop
                               " target nodes (node %s given twice)" %
169 a5bc662a Iustin Pop
                               src_node)
170 a5bc662a Iustin Pop
171 a5bc662a Iustin Pop
  if not sinst:
172 3a24c527 Iustin Pop
    ToStderr("No secondary instances on node %s, exiting.", src_node)
173 a5bc662a Iustin Pop
    return constants.EXIT_SUCCESS
174 a5bc662a Iustin Pop
175 a5bc662a Iustin Pop
  sinst = utils.NiceSort(sinst)
176 a5bc662a Iustin Pop
177 a5bc662a Iustin Pop
  retcode = constants.EXIT_SUCCESS
178 a5bc662a Iustin Pop
179 a5bc662a Iustin Pop
  if not force and not AskUser("Relocate instance(s) %s from node\n"
180 a5bc662a Iustin Pop
                               " %s to node\n %s?" %
181 a5bc662a Iustin Pop
                               (",".join("'%s'" % name for name in sinst),
182 a5bc662a Iustin Pop
                               src_node, dst_node)):
183 a5bc662a Iustin Pop
    return constants.EXIT_CONFIRMATION
184 a5bc662a Iustin Pop
185 a5bc662a Iustin Pop
  good_cnt = bad_cnt = 0
186 a5bc662a Iustin Pop
  for iname in sinst:
187 a5bc662a Iustin Pop
    op = opcodes.OpReplaceDisks(instance_name=iname,
188 22d31e49 Michael Hanselmann
                                remote_node=dst_node,
189 22d31e49 Michael Hanselmann
                                mode=constants.REPLACE_DISK_ALL,
190 22d31e49 Michael Hanselmann
                                disks=["sda", "sdb"])
191 a5bc662a Iustin Pop
    try:
192 3a24c527 Iustin Pop
      ToStdout("Replacing disks for instance %s", iname)
193 a5bc662a Iustin Pop
      SubmitOpCode(op)
194 3a24c527 Iustin Pop
      ToStdout("Instance %s has been relocated", iname)
195 a5bc662a Iustin Pop
      good_cnt += 1
196 a5bc662a Iustin Pop
    except errors.GenericError, err:
197 a5bc662a Iustin Pop
      nret, msg = FormatError(err)
198 a5bc662a Iustin Pop
      retcode |= nret
199 3a24c527 Iustin Pop
      ToStderr("Error replacing disks for instance %s: %s", iname, msg)
200 a5bc662a Iustin Pop
      bad_cnt += 1
201 a5bc662a Iustin Pop
202 a5bc662a Iustin Pop
  if retcode == constants.EXIT_SUCCESS:
203 3a24c527 Iustin Pop
    ToStdout("All %d instance(s) relocated successfully.", good_cnt)
204 a5bc662a Iustin Pop
  else:
205 3a24c527 Iustin Pop
    ToStdout("There were errors during the relocation:\n"
206 3a24c527 Iustin Pop
             "%d error(s) out of %d instance(s).", bad_cnt, good_cnt + bad_cnt)
207 a5bc662a Iustin Pop
  return retcode
208 a5bc662a Iustin Pop
209 a5bc662a Iustin Pop
210 c450e9b0 Iustin Pop
def FailoverNode(opts, args):
211 c450e9b0 Iustin Pop
  """Failover all primary instance on a node.
212 c450e9b0 Iustin Pop
213 ebf366ee Iustin Pop
  @param opts: the command line options selected by the user
214 ebf366ee Iustin Pop
  @type args: list
215 ebf366ee Iustin Pop
  @param args: should be an empty list
216 ebf366ee Iustin Pop
  @rtype: int
217 ebf366ee Iustin Pop
  @return: the desired exit code
218 ebf366ee Iustin Pop
219 c450e9b0 Iustin Pop
  """
220 c450e9b0 Iustin Pop
  force = opts.force
221 c450e9b0 Iustin Pop
  selected_fields = ["name", "pinst_list"]
222 c450e9b0 Iustin Pop
223 c450e9b0 Iustin Pop
  op = opcodes.OpQueryNodes(output_fields=selected_fields, names=args)
224 c450e9b0 Iustin Pop
  result = SubmitOpCode(op)
225 c450e9b0 Iustin Pop
  node, pinst = result[0]
226 c450e9b0 Iustin Pop
227 c450e9b0 Iustin Pop
  if not pinst:
228 3a24c527 Iustin Pop
    ToStderr("No primary instances on node %s, exiting.", node)
229 c450e9b0 Iustin Pop
    return 0
230 c450e9b0 Iustin Pop
231 c450e9b0 Iustin Pop
  pinst = utils.NiceSort(pinst)
232 c450e9b0 Iustin Pop
233 c450e9b0 Iustin Pop
  retcode = 0
234 c450e9b0 Iustin Pop
235 c450e9b0 Iustin Pop
  if not force and not AskUser("Fail over instance(s) %s?" %
236 c450e9b0 Iustin Pop
                               (",".join("'%s'" % name for name in pinst))):
237 c450e9b0 Iustin Pop
    return 2
238 c450e9b0 Iustin Pop
239 c450e9b0 Iustin Pop
  good_cnt = bad_cnt = 0
240 c450e9b0 Iustin Pop
  for iname in pinst:
241 c450e9b0 Iustin Pop
    op = opcodes.OpFailoverInstance(instance_name=iname,
242 c450e9b0 Iustin Pop
                                    ignore_consistency=opts.ignore_consistency)
243 c450e9b0 Iustin Pop
    try:
244 3a24c527 Iustin Pop
      ToStdout("Failing over instance %s", iname)
245 c450e9b0 Iustin Pop
      SubmitOpCode(op)
246 3a24c527 Iustin Pop
      ToStdout("Instance %s has been failed over", iname)
247 c450e9b0 Iustin Pop
      good_cnt += 1
248 c450e9b0 Iustin Pop
    except errors.GenericError, err:
249 c450e9b0 Iustin Pop
      nret, msg = FormatError(err)
250 c450e9b0 Iustin Pop
      retcode |= nret
251 3a24c527 Iustin Pop
      ToStderr("Error failing over instance %s: %s", iname, msg)
252 c450e9b0 Iustin Pop
      bad_cnt += 1
253 c450e9b0 Iustin Pop
254 c450e9b0 Iustin Pop
  if retcode == 0:
255 3a24c527 Iustin Pop
    ToStdout("All %d instance(s) failed over successfully.", good_cnt)
256 c450e9b0 Iustin Pop
  else:
257 3a24c527 Iustin Pop
    ToStdout("There were errors during the failover:\n"
258 3a24c527 Iustin Pop
             "%d error(s) out of %d instance(s).", bad_cnt, good_cnt + bad_cnt)
259 c450e9b0 Iustin Pop
  return retcode
260 c450e9b0 Iustin Pop
261 c450e9b0 Iustin Pop
262 a8083063 Iustin Pop
def ShowNodeConfig(opts, args):
263 a8083063 Iustin Pop
  """Show node information.
264 a8083063 Iustin Pop
265 ebf366ee Iustin Pop
  @param opts: the command line options selected by the user
266 ebf366ee Iustin Pop
  @type args: list
267 ebf366ee Iustin Pop
  @param args: should either be an empty list, in which case
268 ebf366ee Iustin Pop
      we show information about all nodes, or should contain
269 ebf366ee Iustin Pop
      a list of nodes to be queried for information
270 ebf366ee Iustin Pop
  @rtype: int
271 ebf366ee Iustin Pop
  @return: the desired exit code
272 ebf366ee Iustin Pop
273 a8083063 Iustin Pop
  """
274 4a72cc75 Iustin Pop
  op = opcodes.OpQueryNodes(output_fields=["name", "pip", "sip",
275 4a72cc75 Iustin Pop
                                           "pinst_list", "sinst_list"],
276 246e180a Iustin Pop
                            names=args)
277 a8083063 Iustin Pop
  result = SubmitOpCode(op)
278 a8083063 Iustin Pop
279 a8083063 Iustin Pop
  for name, primary_ip, secondary_ip, pinst, sinst in result:
280 3a24c527 Iustin Pop
    ToStdout("Node name: %s", name)
281 3a24c527 Iustin Pop
    ToStdout("  primary ip: %s", primary_ip)
282 3a24c527 Iustin Pop
    ToStdout("  secondary ip: %s", secondary_ip)
283 a8083063 Iustin Pop
    if pinst:
284 3a24c527 Iustin Pop
      ToStdout("  primary for instances:")
285 a8083063 Iustin Pop
      for iname in pinst:
286 3a24c527 Iustin Pop
        ToStdout("    - %s", iname)
287 a8083063 Iustin Pop
    else:
288 3a24c527 Iustin Pop
      ToStdout("  primary for no instances")
289 a8083063 Iustin Pop
    if sinst:
290 3a24c527 Iustin Pop
      ToStdout("  secondary for instances:")
291 a8083063 Iustin Pop
      for iname in sinst:
292 3a24c527 Iustin Pop
        ToStdout("    - %s", iname)
293 a8083063 Iustin Pop
    else:
294 3a24c527 Iustin Pop
      ToStdout("  secondary for no instances")
295 a8083063 Iustin Pop
296 a8083063 Iustin Pop
  return 0
297 a8083063 Iustin Pop
298 a8083063 Iustin Pop
299 a8083063 Iustin Pop
def RemoveNode(opts, args):
300 ebf366ee Iustin Pop
  """Remove a node from the cluster.
301 ebf366ee Iustin Pop
302 ebf366ee Iustin Pop
  @param opts: the command line options selected by the user
303 ebf366ee Iustin Pop
  @type args: list
304 ebf366ee Iustin Pop
  @param args: should contain only one element, the name of
305 ebf366ee Iustin Pop
      the node to be removed
306 ebf366ee Iustin Pop
  @rtype: int
307 ebf366ee Iustin Pop
  @return: the desired exit code
308 ebf366ee Iustin Pop
309 ebf366ee Iustin Pop
  """
310 a8083063 Iustin Pop
  op = opcodes.OpRemoveNode(node_name=args[0])
311 a8083063 Iustin Pop
  SubmitOpCode(op)
312 ebf366ee Iustin Pop
  return 0
313 a8083063 Iustin Pop
314 a8083063 Iustin Pop
315 dcb93971 Michael Hanselmann
def ListVolumes(opts, args):
316 dcb93971 Michael Hanselmann
  """List logical volumes on node(s).
317 dcb93971 Michael Hanselmann
318 ebf366ee Iustin Pop
  @param opts: the command line options selected by the user
319 ebf366ee Iustin Pop
  @type args: list
320 ebf366ee Iustin Pop
  @param args: should either be an empty list, in which case
321 ebf366ee Iustin Pop
      we list data for all nodes, or contain a list of nodes
322 ebf366ee Iustin Pop
      to display data only for those
323 ebf366ee Iustin Pop
  @rtype: int
324 ebf366ee Iustin Pop
  @return: the desired exit code
325 ebf366ee Iustin Pop
326 dcb93971 Michael Hanselmann
  """
327 dcb93971 Michael Hanselmann
  if opts.output is None:
328 dcb93971 Michael Hanselmann
    selected_fields = ["node", "phys", "vg",
329 dcb93971 Michael Hanselmann
                       "name", "size", "instance"]
330 dcb93971 Michael Hanselmann
  else:
331 dcb93971 Michael Hanselmann
    selected_fields = opts.output.split(",")
332 dcb93971 Michael Hanselmann
333 dcb93971 Michael Hanselmann
  op = opcodes.OpQueryNodeVolumes(nodes=args, output_fields=selected_fields)
334 dcb93971 Michael Hanselmann
  output = SubmitOpCode(op)
335 dcb93971 Michael Hanselmann
336 dcb93971 Michael Hanselmann
  if not opts.no_headers:
337 137161c9 Michael Hanselmann
    headers = {"node": "Node", "phys": "PhysDev",
338 137161c9 Michael Hanselmann
               "vg": "VG", "name": "Name",
339 137161c9 Michael Hanselmann
               "size": "Size", "instance": "Instance"}
340 137161c9 Michael Hanselmann
  else:
341 137161c9 Michael Hanselmann
    headers = None
342 137161c9 Michael Hanselmann
343 9fbfbb7b Iustin Pop
  unitfields = ["size"]
344 137161c9 Michael Hanselmann
345 137161c9 Michael Hanselmann
  numfields = ["size"]
346 137161c9 Michael Hanselmann
347 16be8703 Iustin Pop
  data = GenerateTable(separator=opts.separator, headers=headers,
348 16be8703 Iustin Pop
                       fields=selected_fields, unitfields=unitfields,
349 9fbfbb7b Iustin Pop
                       numfields=numfields, data=output, units=opts.units)
350 16be8703 Iustin Pop
351 16be8703 Iustin Pop
  for line in data:
352 3a24c527 Iustin Pop
    ToStdout(line)
353 dcb93971 Michael Hanselmann
354 dcb93971 Michael Hanselmann
  return 0
355 dcb93971 Michael Hanselmann
356 dcb93971 Michael Hanselmann
357 a8083063 Iustin Pop
commands = {
358 a8083063 Iustin Pop
  'add': (AddNode, ARGS_ONE,
359 a8083063 Iustin Pop
          [DEBUG_OPT,
360 a8083063 Iustin Pop
           make_option("-s", "--secondary-ip", dest="secondary_ip",
361 a8083063 Iustin Pop
                       help="Specify the secondary ip for the node",
362 e7c6e02b Michael Hanselmann
                       metavar="ADDRESS", default=None),
363 e7c6e02b Michael Hanselmann
           make_option("--readd", dest="readd",
364 e7c6e02b Michael Hanselmann
                       default=False, action="store_true",
365 e7c6e02b Michael Hanselmann
                       help="Readd old node after replacing it"),
366 c4b6c29c Michael Hanselmann
           make_option("--no-ssh-key-check", dest="ssh_key_check",
367 c4b6c29c Michael Hanselmann
                       default=True, action="store_false",
368 c4b6c29c Michael Hanselmann
                       help="Disable SSH key fingerprint checking"),
369 e7c6e02b Michael Hanselmann
           ],
370 c4b6c29c Michael Hanselmann
          "[-s ip] [--readd] [--no-ssh-key-check] <node_name>",
371 c4b6c29c Michael Hanselmann
          "Add a node to the cluster"),
372 a5bc662a Iustin Pop
  'evacuate': (EvacuateNode, ARGS_FIXED(2),
373 a5bc662a Iustin Pop
               [DEBUG_OPT, FORCE_OPT],
374 9a033156 Iustin Pop
               "[-f] <src> <dst>",
375 a5bc662a Iustin Pop
               "Relocate the secondary instances from the first node"
376 abdf0113 Iustin Pop
               " to the second one (only for instances with drbd disk template"
377 abdf0113 Iustin Pop
               ),
378 c450e9b0 Iustin Pop
  'failover': (FailoverNode, ARGS_ONE,
379 c450e9b0 Iustin Pop
               [DEBUG_OPT, FORCE_OPT,
380 c450e9b0 Iustin Pop
                make_option("--ignore-consistency", dest="ignore_consistency",
381 c450e9b0 Iustin Pop
                            action="store_true", default=False,
382 c450e9b0 Iustin Pop
                            help="Ignore the consistency of the disks on"
383 c450e9b0 Iustin Pop
                            " the secondary"),
384 c450e9b0 Iustin Pop
                ],
385 9a033156 Iustin Pop
               "[-f] <node>",
386 c450e9b0 Iustin Pop
               "Stops the primary instances on a node and start them on their"
387 abdf0113 Iustin Pop
               " secondary node (only for instances with drbd disk template)"),
388 a8083063 Iustin Pop
  'info': (ShowNodeConfig, ARGS_ANY, [DEBUG_OPT],
389 9a033156 Iustin Pop
           "[<node_name>...]", "Show information about the node(s)"),
390 a8083063 Iustin Pop
  'list': (ListNodes, ARGS_NONE,
391 94428652 Iustin Pop
           [DEBUG_OPT, NOHDR_OPT, SEP_OPT, USEUNITS_OPT, FIELDS_OPT,
392 94428652 Iustin Pop
            SUBMIT_OPT],
393 9a033156 Iustin Pop
           "", "Lists the nodes in the cluster. The available fields"
394 d8a4b51d Iustin Pop
           " are (see the man page for details): name, pinst_cnt, pinst_list,"
395 d8a4b51d Iustin Pop
           " sinst_cnt, sinst_list, pip, sip, dtotal, dfree, mtotal, mnode,"
396 38d7239a Iustin Pop
           " mfree, bootid, cpu_count, serial_no."
397 38d7239a Iustin Pop
           " The default field list is"
398 48c4dfa8 Iustin Pop
           " (in order): %s." % ", ".join(_LIST_DEF_FIELDS),
399 48c4dfa8 Iustin Pop
           ),
400 a8083063 Iustin Pop
  'remove': (RemoveNode, ARGS_ONE, [DEBUG_OPT],
401 9a033156 Iustin Pop
             "<node_name>", "Removes a node from the cluster"),
402 dcb93971 Michael Hanselmann
  'volumes': (ListVolumes, ARGS_ANY,
403 dcb93971 Michael Hanselmann
              [DEBUG_OPT, NOHDR_OPT, SEP_OPT, USEUNITS_OPT, FIELDS_OPT],
404 9a033156 Iustin Pop
              "[<node_name>...]", "List logical volumes on node(s)"),
405 846baef9 Iustin Pop
  'list-tags': (ListTags, ARGS_ONE, [DEBUG_OPT],
406 9a033156 Iustin Pop
                "<node_name>", "List the tags of the given node"),
407 810c50b7 Iustin Pop
  'add-tags': (AddTags, ARGS_ATLEAST(1), [DEBUG_OPT, TAG_SRC_OPT],
408 9a033156 Iustin Pop
               "<node_name> tag...", "Add tags to the given node"),
409 810c50b7 Iustin Pop
  'remove-tags': (RemoveTags, ARGS_ATLEAST(1), [DEBUG_OPT, TAG_SRC_OPT],
410 9a033156 Iustin Pop
                  "<node_name> tag...", "Remove tags from the given node"),
411 a8083063 Iustin Pop
  }
412 a8083063 Iustin Pop
413 a8083063 Iustin Pop
414 a8083063 Iustin Pop
if __name__ == '__main__':
415 846baef9 Iustin Pop
  sys.exit(GenericMain(commands, override={"tag_type": constants.TAG_NODE}))