Statistics
| Branch: | Tag: | Revision:

root / scripts / gnt-node @ 87622829

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