Statistics
| Branch: | Tag: | Revision:

root / scripts / gnt-node @ cc3bcec8

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