Statistics
| Branch: | Tag: | Revision:

root / scripts / gnt-node @ 0e67cdbe

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