Statistics
| Branch: | Tag: | Revision:

root / scripts / gnt-node @ 4331f6cd

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