Statistics
| Branch: | Tag: | Revision:

root / scripts / gnt-node @ c450e9b0

History | View | Annotate | Download (8.2 kB)

1 a8083063 Iustin Pop
#!/usr/bin/python
2 a8083063 Iustin Pop
#
3 a8083063 Iustin Pop
4 a8083063 Iustin Pop
# Copyright (C) 2006, 2007 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 a8083063 Iustin Pop
import sys
23 a8083063 Iustin Pop
from optparse import make_option
24 a8083063 Iustin Pop
25 a8083063 Iustin Pop
from ganeti.cli import *
26 a8083063 Iustin Pop
from ganeti import opcodes
27 a8083063 Iustin Pop
from ganeti import logger
28 a8083063 Iustin Pop
from ganeti import utils
29 846baef9 Iustin Pop
from ganeti import constants
30 c450e9b0 Iustin Pop
from ganeti import errors
31 a8083063 Iustin Pop
32 a8083063 Iustin Pop
33 a8083063 Iustin Pop
def AddNode(opts, args):
34 a8083063 Iustin Pop
  """Add node cli-to-processor bridge."""
35 99e8bbde Guido Trotter
  logger.ToStderr("-- WARNING -- \n"
36 99e8bbde Guido Trotter
    "Performing this operation is going to replace the ssh daemon keypair\n"
37 99e8bbde Guido Trotter
    "on the target machine (%s) with the ones of the current one\n"
38 99e8bbde Guido Trotter
    "and grant full intra-cluster ssh root access to/from it\n" % args[0])
39 a8083063 Iustin Pop
  op = opcodes.OpAddNode(node_name=args[0], secondary_ip=opts.secondary_ip)
40 a8083063 Iustin Pop
  SubmitOpCode(op)
41 a8083063 Iustin Pop
42 a8083063 Iustin Pop
43 a8083063 Iustin Pop
def ListNodes(opts, args):
44 a8083063 Iustin Pop
  """List nodes and their properties.
45 a8083063 Iustin Pop
46 a8083063 Iustin Pop
  """
47 a8083063 Iustin Pop
  if opts.output is None:
48 a8083063 Iustin Pop
    selected_fields = ["name", "dtotal", "dfree",
49 a8083063 Iustin Pop
                       "mtotal", "mnode", "mfree",
50 ec223efb Iustin Pop
                       "pinst_cnt", "sinst_cnt"]
51 a8083063 Iustin Pop
  else:
52 a8083063 Iustin Pop
    selected_fields = opts.output.split(",")
53 a8083063 Iustin Pop
54 246e180a Iustin Pop
  op = opcodes.OpQueryNodes(output_fields=selected_fields, names=[])
55 a8083063 Iustin Pop
  output = SubmitOpCode(op)
56 a8083063 Iustin Pop
57 a8083063 Iustin Pop
  if not opts.no_headers:
58 ec223efb Iustin Pop
    headers = {"name": "Node", "pinst_cnt": "Pinst", "sinst_cnt": "Sinst",
59 ec223efb Iustin Pop
               "pinst_list": "PriInstances", "sinst_list": "SecInstances",
60 137161c9 Michael Hanselmann
               "pip": "PrimaryIP", "sip": "SecondaryIP",
61 137161c9 Michael Hanselmann
               "dtotal": "DTotal", "dfree": "DFree",
62 3ef10550 Michael Hanselmann
               "mtotal": "MTotal", "mnode": "MNode", "mfree": "MFree",
63 3ef10550 Michael Hanselmann
               "bootid": "BootID"}
64 137161c9 Michael Hanselmann
  else:
65 137161c9 Michael Hanselmann
    headers = None
66 137161c9 Michael Hanselmann
67 137161c9 Michael Hanselmann
  if opts.human_readable:
68 137161c9 Michael Hanselmann
    unitfields = ["dtotal", "dfree", "mtotal", "mnode", "mfree"]
69 137161c9 Michael Hanselmann
  else:
70 137161c9 Michael Hanselmann
    unitfields = None
71 137161c9 Michael Hanselmann
72 ec223efb Iustin Pop
  numfields = ["dtotal", "dfree",
73 ec223efb Iustin Pop
               "mtotal", "mnode", "mfree",
74 ec223efb Iustin Pop
               "pinst_cnt", "sinst_cnt"]
75 ec223efb Iustin Pop
76 ec223efb Iustin Pop
  # change raw values to nicer strings
77 ec223efb Iustin Pop
  for row in output:
78 ec223efb Iustin Pop
    for idx, field in enumerate(selected_fields):
79 ec223efb Iustin Pop
      val = row[idx]
80 ec223efb Iustin Pop
      if field == "pinst_list":
81 ec223efb Iustin Pop
        val = ",".join(val)
82 ec223efb Iustin Pop
      elif field == "sinst_list":
83 ec223efb Iustin Pop
        val = ",".join(val)
84 ec223efb Iustin Pop
      elif val is None:
85 ec223efb Iustin Pop
        val = "?"
86 ec223efb Iustin Pop
      row[idx] = str(val)
87 137161c9 Michael Hanselmann
88 16be8703 Iustin Pop
  data = GenerateTable(separator=opts.separator, headers=headers,
89 16be8703 Iustin Pop
                       fields=selected_fields, unitfields=unitfields,
90 16be8703 Iustin Pop
                       numfields=numfields, data=output)
91 16be8703 Iustin Pop
  for line in data:
92 16be8703 Iustin Pop
    logger.ToStdout(line)
93 a8083063 Iustin Pop
94 a8083063 Iustin Pop
  return 0
95 a8083063 Iustin Pop
96 a8083063 Iustin Pop
97 c450e9b0 Iustin Pop
def FailoverNode(opts, args):
98 c450e9b0 Iustin Pop
  """Failover all primary instance on a node.
99 c450e9b0 Iustin Pop
100 c450e9b0 Iustin Pop
  """
101 c450e9b0 Iustin Pop
  force = opts.force
102 c450e9b0 Iustin Pop
  selected_fields = ["name", "pinst_list"]
103 c450e9b0 Iustin Pop
104 c450e9b0 Iustin Pop
  op = opcodes.OpQueryNodes(output_fields=selected_fields, names=args)
105 c450e9b0 Iustin Pop
  result = SubmitOpCode(op)
106 c450e9b0 Iustin Pop
  node, pinst = result[0]
107 c450e9b0 Iustin Pop
108 c450e9b0 Iustin Pop
  if not pinst:
109 c450e9b0 Iustin Pop
    logger.ToStderr("No primary instances on node %s, exiting." % node)
110 c450e9b0 Iustin Pop
    return 0
111 c450e9b0 Iustin Pop
112 c450e9b0 Iustin Pop
  pinst = utils.NiceSort(pinst)
113 c450e9b0 Iustin Pop
114 c450e9b0 Iustin Pop
  retcode = 0
115 c450e9b0 Iustin Pop
116 c450e9b0 Iustin Pop
  if not force and not AskUser("Fail over instance(s) %s?" %
117 c450e9b0 Iustin Pop
                               (",".join("'%s'" % name for name in pinst))):
118 c450e9b0 Iustin Pop
    return 2
119 c450e9b0 Iustin Pop
120 c450e9b0 Iustin Pop
  good_cnt = bad_cnt = 0
121 c450e9b0 Iustin Pop
  for iname in pinst:
122 c450e9b0 Iustin Pop
    op = opcodes.OpFailoverInstance(instance_name=iname,
123 c450e9b0 Iustin Pop
                                    ignore_consistency=opts.ignore_consistency)
124 c450e9b0 Iustin Pop
    try:
125 c450e9b0 Iustin Pop
      logger.ToStdout("Failing over instance %s" % iname)
126 c450e9b0 Iustin Pop
      SubmitOpCode(op)
127 c450e9b0 Iustin Pop
      logger.ToStdout("Instance %s has been failed over" % iname)
128 c450e9b0 Iustin Pop
      good_cnt += 1
129 c450e9b0 Iustin Pop
    except errors.GenericError, err:
130 c450e9b0 Iustin Pop
      nret, msg = FormatError(err)
131 c450e9b0 Iustin Pop
      retcode |= nret
132 c450e9b0 Iustin Pop
      logger.ToStderr("Error failing over instance %s: %s" % (iname, msg))
133 c450e9b0 Iustin Pop
      bad_cnt += 1
134 c450e9b0 Iustin Pop
135 c450e9b0 Iustin Pop
  if retcode == 0:
136 c450e9b0 Iustin Pop
    logger.ToStdout("All %d instance(s) failed over successfully." % good_cnt)
137 c450e9b0 Iustin Pop
  else:
138 c450e9b0 Iustin Pop
    logger.ToStdout("There were errors during the failover:\n"
139 c450e9b0 Iustin Pop
                    "%d error(s) out of %d instance(s)." %
140 c450e9b0 Iustin Pop
                    (bad_cnt, good_cnt + bad_cnt))
141 c450e9b0 Iustin Pop
  return retcode
142 c450e9b0 Iustin Pop
143 c450e9b0 Iustin Pop
144 a8083063 Iustin Pop
def ShowNodeConfig(opts, args):
145 a8083063 Iustin Pop
  """Show node information.
146 a8083063 Iustin Pop
147 a8083063 Iustin Pop
  """
148 4a72cc75 Iustin Pop
  op = opcodes.OpQueryNodes(output_fields=["name", "pip", "sip",
149 4a72cc75 Iustin Pop
                                           "pinst_list", "sinst_list"],
150 246e180a Iustin Pop
                            names=args)
151 a8083063 Iustin Pop
  result = SubmitOpCode(op)
152 a8083063 Iustin Pop
153 a8083063 Iustin Pop
  for name, primary_ip, secondary_ip, pinst, sinst in result:
154 a8083063 Iustin Pop
    logger.ToStdout("Node name: %s" % name)
155 a8083063 Iustin Pop
    logger.ToStdout("  primary ip: %s" % primary_ip)
156 a8083063 Iustin Pop
    logger.ToStdout("  secondary ip: %s" % secondary_ip)
157 a8083063 Iustin Pop
    if pinst:
158 a8083063 Iustin Pop
      logger.ToStdout("  primary for instances:")
159 a8083063 Iustin Pop
      for iname in pinst:
160 a8083063 Iustin Pop
        logger.ToStdout("    - %s" % iname)
161 a8083063 Iustin Pop
    else:
162 a8083063 Iustin Pop
      logger.ToStdout("  primary for no instances")
163 a8083063 Iustin Pop
    if sinst:
164 a8083063 Iustin Pop
      logger.ToStdout("  secondary for instances:")
165 a8083063 Iustin Pop
      for iname in sinst:
166 a8083063 Iustin Pop
        logger.ToStdout("    - %s" % iname)
167 a8083063 Iustin Pop
    else:
168 a8083063 Iustin Pop
      logger.ToStdout("  secondary for no instances")
169 a8083063 Iustin Pop
170 a8083063 Iustin Pop
  return 0
171 a8083063 Iustin Pop
172 a8083063 Iustin Pop
173 a8083063 Iustin Pop
def RemoveNode(opts, args):
174 a8083063 Iustin Pop
  """Remove node cli-to-processor bridge."""
175 a8083063 Iustin Pop
  op = opcodes.OpRemoveNode(node_name=args[0])
176 a8083063 Iustin Pop
  SubmitOpCode(op)
177 a8083063 Iustin Pop
178 a8083063 Iustin Pop
179 dcb93971 Michael Hanselmann
def ListVolumes(opts, args):
180 dcb93971 Michael Hanselmann
  """List logical volumes on node(s).
181 dcb93971 Michael Hanselmann
182 dcb93971 Michael Hanselmann
  """
183 dcb93971 Michael Hanselmann
  if opts.output is None:
184 dcb93971 Michael Hanselmann
    selected_fields = ["node", "phys", "vg",
185 dcb93971 Michael Hanselmann
                       "name", "size", "instance"]
186 dcb93971 Michael Hanselmann
  else:
187 dcb93971 Michael Hanselmann
    selected_fields = opts.output.split(",")
188 dcb93971 Michael Hanselmann
189 dcb93971 Michael Hanselmann
  op = opcodes.OpQueryNodeVolumes(nodes=args, output_fields=selected_fields)
190 dcb93971 Michael Hanselmann
  output = SubmitOpCode(op)
191 dcb93971 Michael Hanselmann
192 dcb93971 Michael Hanselmann
  if not opts.no_headers:
193 137161c9 Michael Hanselmann
    headers = {"node": "Node", "phys": "PhysDev",
194 137161c9 Michael Hanselmann
               "vg": "VG", "name": "Name",
195 137161c9 Michael Hanselmann
               "size": "Size", "instance": "Instance"}
196 137161c9 Michael Hanselmann
  else:
197 137161c9 Michael Hanselmann
    headers = None
198 137161c9 Michael Hanselmann
199 137161c9 Michael Hanselmann
  if opts.human_readable:
200 137161c9 Michael Hanselmann
    unitfields = ["size"]
201 137161c9 Michael Hanselmann
  else:
202 137161c9 Michael Hanselmann
    unitfields = None
203 137161c9 Michael Hanselmann
204 137161c9 Michael Hanselmann
  numfields = ["size"]
205 137161c9 Michael Hanselmann
206 16be8703 Iustin Pop
  data = GenerateTable(separator=opts.separator, headers=headers,
207 16be8703 Iustin Pop
                       fields=selected_fields, unitfields=unitfields,
208 16be8703 Iustin Pop
                       numfields=numfields, data=output)
209 16be8703 Iustin Pop
210 16be8703 Iustin Pop
  for line in data:
211 16be8703 Iustin Pop
    logger.ToStdout(line)
212 dcb93971 Michael Hanselmann
213 dcb93971 Michael Hanselmann
  return 0
214 dcb93971 Michael Hanselmann
215 dcb93971 Michael Hanselmann
216 a8083063 Iustin Pop
commands = {
217 a8083063 Iustin Pop
  'add': (AddNode, ARGS_ONE,
218 a8083063 Iustin Pop
          [DEBUG_OPT,
219 a8083063 Iustin Pop
           make_option("-s", "--secondary-ip", dest="secondary_ip",
220 a8083063 Iustin Pop
                       help="Specify the secondary ip for the node",
221 a8083063 Iustin Pop
                       metavar="ADDRESS", default=None),],
222 a8083063 Iustin Pop
          "<node_name>", "Add a node to the cluster"),
223 c450e9b0 Iustin Pop
  'failover': (FailoverNode, ARGS_ONE,
224 c450e9b0 Iustin Pop
               [DEBUG_OPT, FORCE_OPT,
225 c450e9b0 Iustin Pop
                make_option("--ignore-consistency", dest="ignore_consistency",
226 c450e9b0 Iustin Pop
                            action="store_true", default=False,
227 c450e9b0 Iustin Pop
                            help="Ignore the consistency of the disks on"
228 c450e9b0 Iustin Pop
                            " the secondary"),
229 c450e9b0 Iustin Pop
                ],
230 c450e9b0 Iustin Pop
               "[-f] <node>",
231 c450e9b0 Iustin Pop
               "Stops the primary instances on a node and start them on their"
232 c450e9b0 Iustin Pop
               " secondary node (only for instances of type remote_raid1)"),
233 a8083063 Iustin Pop
  'info': (ShowNodeConfig, ARGS_ANY, [DEBUG_OPT],
234 a8083063 Iustin Pop
           "[<node_name>...]", "Show information about the node(s)"),
235 a8083063 Iustin Pop
  'list': (ListNodes, ARGS_NONE,
236 dcb93971 Michael Hanselmann
           [DEBUG_OPT, NOHDR_OPT, SEP_OPT, USEUNITS_OPT, FIELDS_OPT],
237 a8083063 Iustin Pop
           "", "Lists the nodes in the cluster"),
238 a8083063 Iustin Pop
  'remove': (RemoveNode, ARGS_ONE, [DEBUG_OPT],
239 a8083063 Iustin Pop
             "<node_name>", "Removes a node from the cluster"),
240 dcb93971 Michael Hanselmann
  'volumes': (ListVolumes, ARGS_ANY,
241 dcb93971 Michael Hanselmann
              [DEBUG_OPT, NOHDR_OPT, SEP_OPT, USEUNITS_OPT, FIELDS_OPT],
242 dcb93971 Michael Hanselmann
              "[<node_name>...]", "List logical volumes on node(s)"),
243 846baef9 Iustin Pop
  'list-tags': (ListTags, ARGS_ONE, [DEBUG_OPT],
244 846baef9 Iustin Pop
                "<node_name>", "List the tags of the given node"),
245 810c50b7 Iustin Pop
  'add-tags': (AddTags, ARGS_ATLEAST(1), [DEBUG_OPT, TAG_SRC_OPT],
246 846baef9 Iustin Pop
               "<node_name> tag...", "Add tags to the given node"),
247 810c50b7 Iustin Pop
  'remove-tags': (RemoveTags, ARGS_ATLEAST(1), [DEBUG_OPT, TAG_SRC_OPT],
248 846baef9 Iustin Pop
                  "<node_name> tag...", "Remove tags from the given node"),
249 a8083063 Iustin Pop
  }
250 a8083063 Iustin Pop
251 a8083063 Iustin Pop
252 a8083063 Iustin Pop
if __name__ == '__main__':
253 846baef9 Iustin Pop
  sys.exit(GenericMain(commands, override={"tag_type": constants.TAG_NODE}))