Statistics
| Branch: | Tag: | Revision:

root / scripts / gnt-node @ 5661b908

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