Statistics
| Branch: | Tag: | Revision:

root / scripts / gnt-instance @ f55ff7ec

History | View | Annotate | Download (26.9 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
import os
24 312ac745 Iustin Pop
import itertools
25 a8083063 Iustin Pop
from optparse import make_option
26 a8083063 Iustin Pop
from cStringIO import StringIO
27 a8083063 Iustin Pop
28 a8083063 Iustin Pop
from ganeti.cli import *
29 a8083063 Iustin Pop
from ganeti import opcodes
30 a8083063 Iustin Pop
from ganeti import logger
31 a8083063 Iustin Pop
from ganeti import constants
32 a8083063 Iustin Pop
from ganeti import utils
33 312ac745 Iustin Pop
from ganeti import errors
34 312ac745 Iustin Pop
35 312ac745 Iustin Pop
36 312ac745 Iustin Pop
_SHUTDOWN_CLUSTER = "cluster"
37 312ac745 Iustin Pop
_SHUTDOWN_NODES_BOTH = "nodes"
38 312ac745 Iustin Pop
_SHUTDOWN_NODES_PRI = "nodes-pri"
39 312ac745 Iustin Pop
_SHUTDOWN_NODES_SEC = "nodes-sec"
40 312ac745 Iustin Pop
_SHUTDOWN_INSTANCES = "instances"
41 312ac745 Iustin Pop
42 312ac745 Iustin Pop
def _ExpandMultiNames(mode, names):
43 312ac745 Iustin Pop
  """Expand the given names using the passed mode.
44 312ac745 Iustin Pop
45 312ac745 Iustin Pop
  Args:
46 312ac745 Iustin Pop
    - mode, which can be one of _SHUTDOWN_CLUSTER, _SHUTDOWN_NODES_BOTH,
47 312ac745 Iustin Pop
      _SHUTDOWN_NODES_PRI, _SHUTDOWN_NODES_SEC or _SHUTDOWN_INSTANCES
48 312ac745 Iustin Pop
    - names, which is a list of names; for cluster, it must be empty,
49 312ac745 Iustin Pop
      and for node and instance it must be a list of valid item
50 312ac745 Iustin Pop
      names (short names are valid as usual, e.g. node1 instead of
51 312ac745 Iustin Pop
      node1.example.com)
52 312ac745 Iustin Pop
53 312ac745 Iustin Pop
  For _SHUTDOWN_CLUSTER, all instances will be returned. For
54 312ac745 Iustin Pop
  _SHUTDOWN_NODES_PRI/SEC, all instances having those nodes as
55 312ac745 Iustin Pop
  primary/secondary will be shutdown. For _SHUTDOWN_NODES_BOTH, all
56 312ac745 Iustin Pop
  instances having those nodes as either primary or secondary will be
57 312ac745 Iustin Pop
  returned. For _SHUTDOWN_INSTANCES, the given instances will be
58 312ac745 Iustin Pop
  returned.
59 312ac745 Iustin Pop
60 312ac745 Iustin Pop
  """
61 312ac745 Iustin Pop
  if mode == _SHUTDOWN_CLUSTER:
62 312ac745 Iustin Pop
    if names:
63 312ac745 Iustin Pop
      raise errors.OpPrereqError("Cluster filter mode takes no arguments")
64 312ac745 Iustin Pop
    op = opcodes.OpQueryInstances(output_fields=["name"], names=[])
65 312ac745 Iustin Pop
    idata = SubmitOpCode(op)
66 312ac745 Iustin Pop
    inames = [row[0] for row in idata]
67 312ac745 Iustin Pop
68 312ac745 Iustin Pop
  elif mode in (_SHUTDOWN_NODES_BOTH,
69 312ac745 Iustin Pop
                _SHUTDOWN_NODES_PRI,
70 312ac745 Iustin Pop
                _SHUTDOWN_NODES_SEC):
71 312ac745 Iustin Pop
    if not names:
72 312ac745 Iustin Pop
      raise errors.OpPrereqError("No node names passed")
73 312ac745 Iustin Pop
    op = opcodes.OpQueryNodes(output_fields=["name", "pinst_list",
74 312ac745 Iustin Pop
                                             "sinst_list"], names=names)
75 312ac745 Iustin Pop
    ndata = SubmitOpCode(op)
76 312ac745 Iustin Pop
    ipri = [row[1] for row in ndata]
77 312ac745 Iustin Pop
    pri_names = list(itertools.chain(*ipri))
78 312ac745 Iustin Pop
    isec = [row[2] for row in ndata]
79 312ac745 Iustin Pop
    sec_names = list(itertools.chain(*isec))
80 312ac745 Iustin Pop
    if mode == _SHUTDOWN_NODES_BOTH:
81 312ac745 Iustin Pop
      inames = pri_names + sec_names
82 312ac745 Iustin Pop
    elif mode == _SHUTDOWN_NODES_PRI:
83 312ac745 Iustin Pop
      inames = pri_names
84 312ac745 Iustin Pop
    elif mode == _SHUTDOWN_NODES_SEC:
85 312ac745 Iustin Pop
      inames = sec_names
86 312ac745 Iustin Pop
    else:
87 312ac745 Iustin Pop
      raise errors.ProgrammerError("Unhandled shutdown type")
88 312ac745 Iustin Pop
89 312ac745 Iustin Pop
  elif mode == _SHUTDOWN_INSTANCES:
90 312ac745 Iustin Pop
    if not names:
91 312ac745 Iustin Pop
      raise errors.OpPrereqError("No instance names passed")
92 312ac745 Iustin Pop
    op = opcodes.OpQueryInstances(output_fields=["name"], names=names)
93 312ac745 Iustin Pop
    idata = SubmitOpCode(op)
94 312ac745 Iustin Pop
    inames = [row[0] for row in idata]
95 312ac745 Iustin Pop
96 312ac745 Iustin Pop
  else:
97 312ac745 Iustin Pop
    raise errors.OpPrereqError("Unknown mode '%s'" % mode)
98 312ac745 Iustin Pop
99 312ac745 Iustin Pop
  return inames
100 a8083063 Iustin Pop
101 a8083063 Iustin Pop
102 804a1e8e Iustin Pop
def _ConfirmOperation(inames, text):
103 804a1e8e Iustin Pop
  """Ask the user to confirm an operation on a list of instances.
104 804a1e8e Iustin Pop
105 804a1e8e Iustin Pop
  This function is used to request confirmation for doing an operation
106 804a1e8e Iustin Pop
  on a given list of instances.
107 804a1e8e Iustin Pop
108 804a1e8e Iustin Pop
  The inames argument is what the selection algorithm computed, and
109 804a1e8e Iustin Pop
  the text argument is the operation we should tell the user to
110 804a1e8e Iustin Pop
  confirm (e.g. 'shutdown' or 'startup').
111 804a1e8e Iustin Pop
112 804a1e8e Iustin Pop
  Returns: boolean depending on user's confirmation.
113 804a1e8e Iustin Pop
114 804a1e8e Iustin Pop
  """
115 804a1e8e Iustin Pop
  count = len(inames)
116 804a1e8e Iustin Pop
  msg = ("The %s will operate on %d instances.\n"
117 804a1e8e Iustin Pop
         "Do you want to continue?" % (text, count))
118 804a1e8e Iustin Pop
  affected = ("\nAffected instances:\n" +
119 804a1e8e Iustin Pop
              "\n".join(["  %s" % name for name in inames]))
120 804a1e8e Iustin Pop
121 804a1e8e Iustin Pop
  choices = [('y', True, 'Yes, execute the %s' % text),
122 804a1e8e Iustin Pop
             ('n', False, 'No, abort the %s' % text)]
123 804a1e8e Iustin Pop
124 804a1e8e Iustin Pop
  if count > 20:
125 804a1e8e Iustin Pop
    choices.insert(1, ('v', 'v', 'View the list of affected instances'))
126 804a1e8e Iustin Pop
    ask = msg
127 804a1e8e Iustin Pop
  else:
128 804a1e8e Iustin Pop
    ask = msg + affected
129 804a1e8e Iustin Pop
130 804a1e8e Iustin Pop
  choice = AskUser(ask, choices)
131 804a1e8e Iustin Pop
  if choice == 'v':
132 804a1e8e Iustin Pop
    choices.pop(1)
133 804a1e8e Iustin Pop
    choice = AskUser(choices, msg + affected)
134 804a1e8e Iustin Pop
  return choice
135 804a1e8e Iustin Pop
136 804a1e8e Iustin Pop
137 a8083063 Iustin Pop
def ListInstances(opts, args):
138 f5abe9bd Oleksiy Mishchenko
  """List instances and their properties.
139 a8083063 Iustin Pop
140 a8083063 Iustin Pop
  """
141 a8083063 Iustin Pop
  if opts.output is None:
142 a8083063 Iustin Pop
    selected_fields = ["name", "os", "pnode", "admin_state",
143 a8083063 Iustin Pop
                       "oper_state", "oper_ram"]
144 a8083063 Iustin Pop
  else:
145 a8083063 Iustin Pop
    selected_fields = opts.output.split(",")
146 a8083063 Iustin Pop
147 069dcc86 Iustin Pop
  op = opcodes.OpQueryInstances(output_fields=selected_fields, names=[])
148 a8083063 Iustin Pop
  output = SubmitOpCode(op)
149 a8083063 Iustin Pop
150 a8083063 Iustin Pop
  if not opts.no_headers:
151 137161c9 Michael Hanselmann
    headers = {"name": "Instance", "os": "OS", "pnode": "Primary_node",
152 137161c9 Michael Hanselmann
               "snodes": "Secondary_Nodes", "admin_state": "Autostart",
153 137161c9 Michael Hanselmann
               "oper_state": "Status", "admin_ram": "Configured_memory",
154 137161c9 Michael Hanselmann
               "oper_ram": "Memory", "disk_template": "Disk_template",
155 137161c9 Michael Hanselmann
               "ip": "IP Address", "mac": "MAC Address",
156 644eeef9 Iustin Pop
               "bridge": "Bridge",
157 644eeef9 Iustin Pop
               "sda_size": "Disk/0", "sdb_size": "Disk/1"}
158 137161c9 Michael Hanselmann
  else:
159 137161c9 Michael Hanselmann
    headers = None
160 137161c9 Michael Hanselmann
161 137161c9 Michael Hanselmann
  if opts.human_readable:
162 644eeef9 Iustin Pop
    unitfields = ["admin_ram", "oper_ram", "sda_size", "sdb_size"]
163 137161c9 Michael Hanselmann
  else:
164 137161c9 Michael Hanselmann
    unitfields = None
165 137161c9 Michael Hanselmann
166 644eeef9 Iustin Pop
  numfields = ["admin_ram", "oper_ram", "sda_size", "sdb_size"]
167 137161c9 Michael Hanselmann
168 8a23d2d3 Iustin Pop
  # change raw values to nicer strings
169 8a23d2d3 Iustin Pop
  for row in output:
170 8a23d2d3 Iustin Pop
    for idx, field in enumerate(selected_fields):
171 8a23d2d3 Iustin Pop
      val = row[idx]
172 8a23d2d3 Iustin Pop
      if field == "snodes":
173 8a23d2d3 Iustin Pop
        val = ",".join(val) or "-"
174 8a23d2d3 Iustin Pop
      elif field == "admin_state":
175 8a23d2d3 Iustin Pop
        if val:
176 8a23d2d3 Iustin Pop
          val = "yes"
177 8a23d2d3 Iustin Pop
        else:
178 8a23d2d3 Iustin Pop
          val = "no"
179 8a23d2d3 Iustin Pop
      elif field == "oper_state":
180 8a23d2d3 Iustin Pop
        if val is None:
181 8a23d2d3 Iustin Pop
          val = "(node down)"
182 8a23d2d3 Iustin Pop
        elif val: # True
183 8a23d2d3 Iustin Pop
          val = "running"
184 8a23d2d3 Iustin Pop
        else:
185 8a23d2d3 Iustin Pop
          val = "stopped"
186 8a23d2d3 Iustin Pop
      elif field == "oper_ram":
187 8a23d2d3 Iustin Pop
        if val is None:
188 8a23d2d3 Iustin Pop
          val = "(node down)"
189 8a23d2d3 Iustin Pop
      elif field == "sda_size" or field == "sdb_size":
190 8a23d2d3 Iustin Pop
        if val is None:
191 8a23d2d3 Iustin Pop
          val = "N/A"
192 8a23d2d3 Iustin Pop
      row[idx] = str(val)
193 8a23d2d3 Iustin Pop
194 16be8703 Iustin Pop
  data = GenerateTable(separator=opts.separator, headers=headers,
195 16be8703 Iustin Pop
                       fields=selected_fields, unitfields=unitfields,
196 16be8703 Iustin Pop
                       numfields=numfields, data=output)
197 16be8703 Iustin Pop
198 16be8703 Iustin Pop
  for line in data:
199 16be8703 Iustin Pop
    logger.ToStdout(line)
200 a8083063 Iustin Pop
201 a8083063 Iustin Pop
  return 0
202 a8083063 Iustin Pop
203 a8083063 Iustin Pop
204 a8083063 Iustin Pop
def AddInstance(opts, args):
205 a8083063 Iustin Pop
  """Add an instance to the cluster.
206 a8083063 Iustin Pop
207 a8083063 Iustin Pop
  Args:
208 a8083063 Iustin Pop
    opts - class with options as members
209 a8083063 Iustin Pop
    args - list with a single element, the instance name
210 a8083063 Iustin Pop
  Opts used:
211 a8083063 Iustin Pop
    mem - amount of memory to allocate to instance (MiB)
212 a8083063 Iustin Pop
    size - amount of disk space to allocate to instance (MiB)
213 a8083063 Iustin Pop
    os - which OS to run on instance
214 a8083063 Iustin Pop
    node - node to run new instance on
215 a8083063 Iustin Pop
216 a8083063 Iustin Pop
  """
217 a8083063 Iustin Pop
  instance = args[0]
218 a8083063 Iustin Pop
219 a8083063 Iustin Pop
  op = opcodes.OpCreateInstance(instance_name=instance, mem_size=opts.mem,
220 a8083063 Iustin Pop
                                disk_size=opts.size, swap_size=opts.swap,
221 a8083063 Iustin Pop
                                disk_template=opts.disk_template,
222 a8083063 Iustin Pop
                                mode=constants.INSTANCE_CREATE,
223 a8083063 Iustin Pop
                                os_type=opts.os, pnode=opts.node,
224 a8083063 Iustin Pop
                                snode=opts.snode, vcpus=opts.vcpus,
225 bdd55f71 Iustin Pop
                                ip=opts.ip, bridge=opts.bridge,
226 bdd55f71 Iustin Pop
                                start=opts.start, ip_check=opts.ip_check,
227 a8083063 Iustin Pop
                                wait_for_sync=opts.wait_for_sync)
228 a8083063 Iustin Pop
  SubmitOpCode(op)
229 a8083063 Iustin Pop
  return 0
230 a8083063 Iustin Pop
231 a8083063 Iustin Pop
232 fe7b0351 Michael Hanselmann
def ReinstallInstance(opts, args):
233 fe7b0351 Michael Hanselmann
  """Reinstall an instance.
234 fe7b0351 Michael Hanselmann
235 fe7b0351 Michael Hanselmann
  Args:
236 fe7b0351 Michael Hanselmann
    opts - class with options as members
237 fe7b0351 Michael Hanselmann
    args - list containing a single element, the instance name
238 fe7b0351 Michael Hanselmann
239 fe7b0351 Michael Hanselmann
  """
240 fe7b0351 Michael Hanselmann
  instance_name = args[0]
241 fe7b0351 Michael Hanselmann
242 fe7b0351 Michael Hanselmann
  if not opts.force:
243 fe7b0351 Michael Hanselmann
    usertext = ("This will reinstall the instance %s and remove "
244 fe7b0351 Michael Hanselmann
                "all data. Continue?") % instance_name
245 47988778 Iustin Pop
    if not AskUser(usertext):
246 fe7b0351 Michael Hanselmann
      return 1
247 fe7b0351 Michael Hanselmann
248 d0834de3 Michael Hanselmann
  op = opcodes.OpReinstallInstance(instance_name=instance_name,
249 d0834de3 Michael Hanselmann
                                   os_type=opts.os)
250 fe7b0351 Michael Hanselmann
  SubmitOpCode(op)
251 fe7b0351 Michael Hanselmann
252 fe7b0351 Michael Hanselmann
  return 0
253 fe7b0351 Michael Hanselmann
254 fe7b0351 Michael Hanselmann
255 a8083063 Iustin Pop
def RemoveInstance(opts, args):
256 a8083063 Iustin Pop
  """Remove an instance.
257 a8083063 Iustin Pop
258 a8083063 Iustin Pop
  Args:
259 a8083063 Iustin Pop
    opts - class with options as members
260 a8083063 Iustin Pop
    args - list containing a single element, the instance name
261 a8083063 Iustin Pop
262 a8083063 Iustin Pop
  """
263 a8083063 Iustin Pop
  instance_name = args[0]
264 a8083063 Iustin Pop
  force = opts.force
265 a8083063 Iustin Pop
266 a8083063 Iustin Pop
  if not force:
267 a8083063 Iustin Pop
    usertext = ("This will remove the volumes of the instance %s"
268 a8083063 Iustin Pop
                " (including mirrors), thus removing all the data"
269 a8083063 Iustin Pop
                " of the instance. Continue?") % instance_name
270 47988778 Iustin Pop
    if not AskUser(usertext):
271 a8083063 Iustin Pop
      return 1
272 a8083063 Iustin Pop
273 1d67656e Iustin Pop
  op = opcodes.OpRemoveInstance(instance_name=instance_name,
274 1d67656e Iustin Pop
                                ignore_failures=opts.ignore_failures)
275 a8083063 Iustin Pop
  SubmitOpCode(op)
276 a8083063 Iustin Pop
  return 0
277 a8083063 Iustin Pop
278 a8083063 Iustin Pop
279 decd5f45 Iustin Pop
def RenameInstance(opts, args):
280 4ab0b9e3 Guido Trotter
  """Rename an instance.
281 decd5f45 Iustin Pop
282 decd5f45 Iustin Pop
  Args:
283 decd5f45 Iustin Pop
    opts - class with options as members
284 decd5f45 Iustin Pop
    args - list containing two elements, the instance name and the new name
285 decd5f45 Iustin Pop
286 decd5f45 Iustin Pop
  """
287 decd5f45 Iustin Pop
  op = opcodes.OpRenameInstance(instance_name=args[0],
288 decd5f45 Iustin Pop
                                new_name=args[1],
289 decd5f45 Iustin Pop
                                ignore_ip=opts.ignore_ip)
290 decd5f45 Iustin Pop
  SubmitOpCode(op)
291 decd5f45 Iustin Pop
292 decd5f45 Iustin Pop
  return 0
293 decd5f45 Iustin Pop
294 decd5f45 Iustin Pop
295 a8083063 Iustin Pop
def ActivateDisks(opts, args):
296 a8083063 Iustin Pop
  """Activate an instance's disks.
297 a8083063 Iustin Pop
298 a8083063 Iustin Pop
  This serves two purposes:
299 a8083063 Iustin Pop
    - it allows one (as long as the instance is not running) to mount
300 a8083063 Iustin Pop
    the disks and modify them from the node
301 a8083063 Iustin Pop
    - it repairs inactive secondary drbds
302 a8083063 Iustin Pop
303 a8083063 Iustin Pop
  """
304 a8083063 Iustin Pop
  instance_name = args[0]
305 a8083063 Iustin Pop
  op = opcodes.OpActivateInstanceDisks(instance_name=instance_name)
306 a8083063 Iustin Pop
  disks_info = SubmitOpCode(op)
307 a8083063 Iustin Pop
  for host, iname, nname in disks_info:
308 a8083063 Iustin Pop
    print "%s:%s:%s" % (host, iname, nname)
309 a8083063 Iustin Pop
  return 0
310 a8083063 Iustin Pop
311 a8083063 Iustin Pop
312 a8083063 Iustin Pop
def DeactivateDisks(opts, args):
313 a8083063 Iustin Pop
  """Command-line interface for _ShutdownInstanceBlockDevices.
314 a8083063 Iustin Pop
315 a8083063 Iustin Pop
  This function takes the instance name, looks for its primary node
316 a8083063 Iustin Pop
  and the tries to shutdown its block devices on that node.
317 a8083063 Iustin Pop
318 a8083063 Iustin Pop
  """
319 a8083063 Iustin Pop
  instance_name = args[0]
320 a8083063 Iustin Pop
  op = opcodes.OpDeactivateInstanceDisks(instance_name=instance_name)
321 a8083063 Iustin Pop
  SubmitOpCode(op)
322 a8083063 Iustin Pop
  return 0
323 a8083063 Iustin Pop
324 a8083063 Iustin Pop
325 a8083063 Iustin Pop
def StartupInstance(opts, args):
326 decd5f45 Iustin Pop
  """Startup an instance.
327 a8083063 Iustin Pop
328 a8083063 Iustin Pop
  Args:
329 a8083063 Iustin Pop
    opts - class with options as members
330 a8083063 Iustin Pop
    args - list containing a single element, the instance name
331 a8083063 Iustin Pop
332 a8083063 Iustin Pop
  """
333 312ac745 Iustin Pop
  if opts.multi_mode is None:
334 312ac745 Iustin Pop
    opts.multi_mode = _SHUTDOWN_INSTANCES
335 312ac745 Iustin Pop
  inames = _ExpandMultiNames(opts.multi_mode, args)
336 804a1e8e Iustin Pop
  multi_on = opts.multi_mode != _SHUTDOWN_INSTANCES or len(inames) > 1
337 804a1e8e Iustin Pop
  if not (opts.force_multi or not multi_on
338 804a1e8e Iustin Pop
          or _ConfirmOperation(inames, "startup")):
339 804a1e8e Iustin Pop
    return 1
340 312ac745 Iustin Pop
  for name in inames:
341 312ac745 Iustin Pop
    op = opcodes.OpStartupInstance(instance_name=name,
342 312ac745 Iustin Pop
                                   force=opts.force,
343 312ac745 Iustin Pop
                                   extra_args=opts.extra_args)
344 312ac745 Iustin Pop
    if multi_on:
345 312ac745 Iustin Pop
      logger.ToStdout("Starting up %s" % name)
346 312ac745 Iustin Pop
    SubmitOpCode(op)
347 a8083063 Iustin Pop
  return 0
348 a8083063 Iustin Pop
349 a8083063 Iustin Pop
350 a8083063 Iustin Pop
def ShutdownInstance(opts, args):
351 a8083063 Iustin Pop
  """Shutdown an instance.
352 a8083063 Iustin Pop
353 a8083063 Iustin Pop
  Args:
354 a8083063 Iustin Pop
    opts - class with options as members
355 a8083063 Iustin Pop
    args - list containing a single element, the instance name
356 a8083063 Iustin Pop
357 a8083063 Iustin Pop
  """
358 312ac745 Iustin Pop
  if opts.multi_mode is None:
359 312ac745 Iustin Pop
    opts.multi_mode = _SHUTDOWN_INSTANCES
360 312ac745 Iustin Pop
  inames = _ExpandMultiNames(opts.multi_mode, args)
361 804a1e8e Iustin Pop
  multi_on = opts.multi_mode != _SHUTDOWN_INSTANCES or len(inames) > 1
362 804a1e8e Iustin Pop
  if not (opts.force_multi or not multi_on
363 804a1e8e Iustin Pop
          or _ConfirmOperation(inames, "shutdown")):
364 804a1e8e Iustin Pop
    return 1
365 312ac745 Iustin Pop
  for name in inames:
366 312ac745 Iustin Pop
    op = opcodes.OpShutdownInstance(instance_name=name)
367 312ac745 Iustin Pop
    if multi_on:
368 312ac745 Iustin Pop
      logger.ToStdout("Shutting down %s" % name)
369 312ac745 Iustin Pop
    SubmitOpCode(op)
370 a8083063 Iustin Pop
  return 0
371 a8083063 Iustin Pop
372 a8083063 Iustin Pop
373 a8083063 Iustin Pop
def AddMDDRBDComponent(opts, args):
374 a8083063 Iustin Pop
  """Add a new component to a remote_raid1 disk.
375 a8083063 Iustin Pop
376 a8083063 Iustin Pop
  Args:
377 a8083063 Iustin Pop
    opts - class with options as members
378 a8083063 Iustin Pop
    args - list with a single element, the instance name
379 a8083063 Iustin Pop
380 a8083063 Iustin Pop
  """
381 a8083063 Iustin Pop
  op = opcodes.OpAddMDDRBDComponent(instance_name=args[0],
382 a8083063 Iustin Pop
                                    disk_name=opts.disk,
383 a8083063 Iustin Pop
                                    remote_node=opts.node)
384 a8083063 Iustin Pop
  SubmitOpCode(op)
385 a8083063 Iustin Pop
  return 0
386 a8083063 Iustin Pop
387 a8083063 Iustin Pop
388 a8083063 Iustin Pop
def RemoveMDDRBDComponent(opts, args):
389 bdb8c997 Guido Trotter
  """Remove a component from a remote_raid1 disk.
390 a8083063 Iustin Pop
391 a8083063 Iustin Pop
  Args:
392 a8083063 Iustin Pop
    opts - class with options as members
393 a8083063 Iustin Pop
    args - list with a single element, the instance name
394 a8083063 Iustin Pop
395 a8083063 Iustin Pop
  """
396 a8083063 Iustin Pop
  op = opcodes.OpRemoveMDDRBDComponent(instance_name=args[0],
397 a8083063 Iustin Pop
                                       disk_name=opts.disk,
398 a8083063 Iustin Pop
                                       disk_id=opts.port)
399 a8083063 Iustin Pop
  SubmitOpCode(op)
400 a8083063 Iustin Pop
  return 0
401 a8083063 Iustin Pop
402 a8083063 Iustin Pop
403 a8083063 Iustin Pop
def ReplaceDisks(opts, args):
404 a8083063 Iustin Pop
  """Replace the disks of an instance
405 a8083063 Iustin Pop
406 a8083063 Iustin Pop
  Args:
407 a8083063 Iustin Pop
    opts - class with options as members
408 a8083063 Iustin Pop
    args - list with a single element, the instance name
409 a8083063 Iustin Pop
410 a8083063 Iustin Pop
  """
411 a8083063 Iustin Pop
  instance_name = args[0]
412 a8083063 Iustin Pop
  new_secondary = opts.new_secondary
413 a8083063 Iustin Pop
  op = opcodes.OpReplaceDisks(instance_name=args[0],
414 a8083063 Iustin Pop
                              remote_node=opts.new_secondary)
415 a8083063 Iustin Pop
  SubmitOpCode(op)
416 a8083063 Iustin Pop
  return 0
417 a8083063 Iustin Pop
418 a8083063 Iustin Pop
419 a8083063 Iustin Pop
def FailoverInstance(opts, args):
420 a8083063 Iustin Pop
  """Failover an instance.
421 a8083063 Iustin Pop
422 a8083063 Iustin Pop
  The failover is done by shutting it down on its present node and
423 a8083063 Iustin Pop
  starting it on the secondary.
424 a8083063 Iustin Pop
425 a8083063 Iustin Pop
  Args:
426 a8083063 Iustin Pop
    opts - class with options as members
427 a8083063 Iustin Pop
    args - list with a single element, the instance name
428 a8083063 Iustin Pop
  Opts used:
429 a8083063 Iustin Pop
    force - whether to failover without asking questions.
430 a8083063 Iustin Pop
431 a8083063 Iustin Pop
  """
432 a8083063 Iustin Pop
  instance_name = args[0]
433 a8083063 Iustin Pop
  force = opts.force
434 a8083063 Iustin Pop
435 a8083063 Iustin Pop
  if not force:
436 a8083063 Iustin Pop
    usertext = ("Failover will happen to image %s."
437 a8083063 Iustin Pop
                " This requires a shutdown of the instance. Continue?" %
438 a8083063 Iustin Pop
                (instance_name,))
439 47988778 Iustin Pop
    if not AskUser(usertext):
440 a8083063 Iustin Pop
      return 1
441 a8083063 Iustin Pop
442 a8083063 Iustin Pop
  op = opcodes.OpFailoverInstance(instance_name=instance_name,
443 a8083063 Iustin Pop
                                  ignore_consistency=opts.ignore_consistency)
444 a8083063 Iustin Pop
  SubmitOpCode(op)
445 a8083063 Iustin Pop
  return 0
446 a8083063 Iustin Pop
447 a8083063 Iustin Pop
448 a8083063 Iustin Pop
def ConnectToInstanceConsole(opts, args):
449 a8083063 Iustin Pop
  """Connect to the console of an instance.
450 a8083063 Iustin Pop
451 a8083063 Iustin Pop
  Args:
452 a8083063 Iustin Pop
    opts - class with options as members
453 a8083063 Iustin Pop
    args - list with a single element, the instance name
454 a8083063 Iustin Pop
455 a8083063 Iustin Pop
  """
456 a8083063 Iustin Pop
  instance_name = args[0]
457 a8083063 Iustin Pop
458 a8083063 Iustin Pop
  op = opcodes.OpConnectConsole(instance_name=instance_name)
459 82122173 Iustin Pop
  cmd, argv = SubmitOpCode(op)
460 a8083063 Iustin Pop
  # drop lock and exec so other commands can run while we have console
461 a8083063 Iustin Pop
  utils.Unlock("cmd")
462 a8083063 Iustin Pop
  try:
463 82122173 Iustin Pop
    os.execvp(cmd, argv)
464 a8083063 Iustin Pop
  finally:
465 82122173 Iustin Pop
    sys.stderr.write("Can't run console command %s with arguments:\n'%s'" %
466 82122173 Iustin Pop
                     (cmd, " ".join(argv)))
467 a8083063 Iustin Pop
    os._exit(1)
468 a8083063 Iustin Pop
469 a8083063 Iustin Pop
470 a8083063 Iustin Pop
def _FormatBlockDevInfo(buf, dev, indent_level):
471 a8083063 Iustin Pop
  """Show block device information.
472 a8083063 Iustin Pop
473 a8083063 Iustin Pop
  This is only used by ShowInstanceConfig(), but it's too big to be
474 a8083063 Iustin Pop
  left for an inline definition.
475 a8083063 Iustin Pop
476 a8083063 Iustin Pop
  """
477 a8083063 Iustin Pop
  def helper(buf, dtype, status):
478 a8083063 Iustin Pop
    """Format one line for phsyical device status."""
479 a8083063 Iustin Pop
    if not status:
480 a8083063 Iustin Pop
      buf.write("not active\n")
481 a8083063 Iustin Pop
    else:
482 a8083063 Iustin Pop
      (path, major, minor, syncp, estt, degr) = status
483 a8083063 Iustin Pop
      buf.write("%s (%d:%d)" % (path, major, minor))
484 a8083063 Iustin Pop
      if dtype in ("md_raid1", "drbd"):
485 a8083063 Iustin Pop
        if syncp is not None:
486 a8083063 Iustin Pop
          sync_text = "*RECOVERING* %5.2f%%," % syncp
487 a8083063 Iustin Pop
          if estt:
488 a8083063 Iustin Pop
            sync_text += " ETA %ds" % estt
489 a8083063 Iustin Pop
          else:
490 a8083063 Iustin Pop
            sync_text += " ETA unknown"
491 a8083063 Iustin Pop
        else:
492 a8083063 Iustin Pop
          sync_text = "in sync"
493 a8083063 Iustin Pop
        if degr:
494 a8083063 Iustin Pop
          degr_text = "*DEGRADED*"
495 a8083063 Iustin Pop
        else:
496 a8083063 Iustin Pop
          degr_text = "ok"
497 a8083063 Iustin Pop
        buf.write(" %s, status %s" % (sync_text, degr_text))
498 a8083063 Iustin Pop
      buf.write("\n")
499 a8083063 Iustin Pop
500 a8083063 Iustin Pop
  if dev["iv_name"] is not None:
501 a8083063 Iustin Pop
    data = "  - %s, " % dev["iv_name"]
502 a8083063 Iustin Pop
  else:
503 a8083063 Iustin Pop
    data = "  - "
504 a8083063 Iustin Pop
  data += "type: %s" % dev["dev_type"]
505 a8083063 Iustin Pop
  if dev["logical_id"] is not None:
506 a8083063 Iustin Pop
    data += ", logical_id: %s" % (dev["logical_id"],)
507 a8083063 Iustin Pop
  elif dev["physical_id"] is not None:
508 a8083063 Iustin Pop
    data += ", physical_id: %s" % (dev["physical_id"],)
509 a8083063 Iustin Pop
  buf.write("%*s%s\n" % (2*indent_level, "", data))
510 a8083063 Iustin Pop
  buf.write("%*s    primary:   " % (2*indent_level, ""))
511 a8083063 Iustin Pop
  helper(buf, dev["dev_type"], dev["pstatus"])
512 a8083063 Iustin Pop
513 a8083063 Iustin Pop
  if dev["sstatus"]:
514 a8083063 Iustin Pop
    buf.write("%*s    secondary: " % (2*indent_level, ""))
515 a8083063 Iustin Pop
    helper(buf, dev["dev_type"], dev["sstatus"])
516 a8083063 Iustin Pop
517 a8083063 Iustin Pop
  if dev["children"]:
518 a8083063 Iustin Pop
    for child in dev["children"]:
519 a8083063 Iustin Pop
      _FormatBlockDevInfo(buf, child, indent_level+1)
520 a8083063 Iustin Pop
521 a8083063 Iustin Pop
522 a8083063 Iustin Pop
def ShowInstanceConfig(opts, args):
523 a8083063 Iustin Pop
  """Compute instance run-time status.
524 a8083063 Iustin Pop
525 a8083063 Iustin Pop
  """
526 a8083063 Iustin Pop
  retcode = 0
527 a8083063 Iustin Pop
  op = opcodes.OpQueryInstanceData(instances=args)
528 a8083063 Iustin Pop
  result = SubmitOpCode(op)
529 a8083063 Iustin Pop
530 a8083063 Iustin Pop
  if not result:
531 a8083063 Iustin Pop
    logger.ToStdout("No instances.")
532 a8083063 Iustin Pop
    return 1
533 a8083063 Iustin Pop
534 a8083063 Iustin Pop
  buf = StringIO()
535 a8083063 Iustin Pop
  retcode = 0
536 a8083063 Iustin Pop
  for instance_name in result:
537 a8083063 Iustin Pop
    instance = result[instance_name]
538 a8083063 Iustin Pop
    buf.write("Instance name: %s\n" % instance["name"])
539 a8083063 Iustin Pop
    buf.write("State: configured to be %s, actual state is %s\n" %
540 a8083063 Iustin Pop
              (instance["config_state"], instance["run_state"]))
541 a8083063 Iustin Pop
    buf.write("  Nodes:\n")
542 a8083063 Iustin Pop
    buf.write("    - primary: %s\n" % instance["pnode"])
543 a8083063 Iustin Pop
    buf.write("    - secondaries: %s\n" % ", ".join(instance["snodes"]))
544 a8083063 Iustin Pop
    buf.write("  Operating system: %s\n" % instance["os"])
545 a8083063 Iustin Pop
    buf.write("  Hardware:\n")
546 f55ff7ec Iustin Pop
    buf.write("    - VCPUs: %d\n" % instance["vcpus"])
547 a8083063 Iustin Pop
    buf.write("    - memory: %dMiB\n" % instance["memory"])
548 a8083063 Iustin Pop
    buf.write("    - NICs: %s\n" %
549 a8083063 Iustin Pop
        ", ".join(["{MAC: %s, IP: %s, bridge: %s}" %
550 a8083063 Iustin Pop
                   (mac, ip, bridge)
551 a8083063 Iustin Pop
                     for mac, ip, bridge in instance["nics"]]))
552 a8083063 Iustin Pop
    buf.write("  Block devices:\n")
553 a8083063 Iustin Pop
554 a8083063 Iustin Pop
    for device in instance["disks"]:
555 a8083063 Iustin Pop
      _FormatBlockDevInfo(buf, device, 1)
556 a8083063 Iustin Pop
557 a8083063 Iustin Pop
  logger.ToStdout(buf.getvalue().rstrip('\n'))
558 a8083063 Iustin Pop
  return retcode
559 a8083063 Iustin Pop
560 a8083063 Iustin Pop
561 a8083063 Iustin Pop
def SetInstanceParms(opts, args):
562 a8083063 Iustin Pop
  """Modifies an instance.
563 a8083063 Iustin Pop
564 a8083063 Iustin Pop
  All parameters take effect only at the next restart of the instance.
565 a8083063 Iustin Pop
566 a8083063 Iustin Pop
  Args:
567 a8083063 Iustin Pop
    opts - class with options as members
568 a8083063 Iustin Pop
    args - list with a single element, the instance name
569 a8083063 Iustin Pop
  Opts used:
570 a8083063 Iustin Pop
    memory - the new memory size
571 a8083063 Iustin Pop
    vcpus - the new number of cpus
572 a8083063 Iustin Pop
573 a8083063 Iustin Pop
  """
574 a8083063 Iustin Pop
  if not opts.mem and not opts.vcpus and not opts.ip and not opts.bridge:
575 a8083063 Iustin Pop
    logger.ToStdout("Please give at least one of the parameters.")
576 a8083063 Iustin Pop
    return 1
577 a8083063 Iustin Pop
578 a8083063 Iustin Pop
  op = opcodes.OpSetInstanceParms(instance_name=args[0], mem=opts.mem,
579 a8083063 Iustin Pop
                                  vcpus=opts.vcpus, ip=opts.ip,
580 a8083063 Iustin Pop
                                  bridge=opts.bridge)
581 a8083063 Iustin Pop
  result = SubmitOpCode(op)
582 a8083063 Iustin Pop
583 a8083063 Iustin Pop
  if result:
584 a8083063 Iustin Pop
    logger.ToStdout("Modified instance %s" % args[0])
585 a8083063 Iustin Pop
    for param, data in result:
586 a8083063 Iustin Pop
      logger.ToStdout(" - %-5s -> %s" % (param, data))
587 a8083063 Iustin Pop
    logger.ToStdout("Please don't forget that these parameters take effect"
588 a8083063 Iustin Pop
                    " only at the next start of the instance.")
589 a8083063 Iustin Pop
  return 0
590 a8083063 Iustin Pop
591 a8083063 Iustin Pop
592 a8083063 Iustin Pop
# options used in more than one cmd
593 a8083063 Iustin Pop
node_opt = make_option("-n", "--node", dest="node", help="Target node",
594 a8083063 Iustin Pop
                       metavar="<node>")
595 a8083063 Iustin Pop
596 d0834de3 Michael Hanselmann
os_opt = cli_option("-o", "--os-type", dest="os", help="What OS to run",
597 739ecd56 Michael Hanselmann
                    metavar="<os>")
598 d0834de3 Michael Hanselmann
599 312ac745 Iustin Pop
# multi-instance selection options
600 804a1e8e Iustin Pop
m_force_multi = make_option("--force-multiple", dest="force_multi",
601 804a1e8e Iustin Pop
                            help="Do not ask for confirmation when more than"
602 804a1e8e Iustin Pop
                            " one instance is affected",
603 804a1e8e Iustin Pop
                            action="store_true", default=False)
604 804a1e8e Iustin Pop
605 312ac745 Iustin Pop
m_pri_node_opt = make_option("--primary", dest="multi_mode",
606 312ac745 Iustin Pop
                             help="Filter by nodes (primary only)",
607 312ac745 Iustin Pop
                             const=_SHUTDOWN_NODES_PRI, action="store_const")
608 312ac745 Iustin Pop
609 312ac745 Iustin Pop
m_sec_node_opt = make_option("--secondary", dest="multi_mode",
610 312ac745 Iustin Pop
                             help="Filter by nodes (secondary only)",
611 312ac745 Iustin Pop
                             const=_SHUTDOWN_NODES_SEC, action="store_const")
612 312ac745 Iustin Pop
613 312ac745 Iustin Pop
m_node_opt = make_option("--node", dest="multi_mode",
614 312ac745 Iustin Pop
                         help="Filter by nodes (primary and secondary)",
615 312ac745 Iustin Pop
                         const=_SHUTDOWN_NODES_BOTH, action="store_const")
616 312ac745 Iustin Pop
617 312ac745 Iustin Pop
m_clust_opt = make_option("--all", dest="multi_mode",
618 312ac745 Iustin Pop
                          help="Select all instances in the cluster",
619 312ac745 Iustin Pop
                          const=_SHUTDOWN_CLUSTER, action="store_const")
620 312ac745 Iustin Pop
621 312ac745 Iustin Pop
m_inst_opt = make_option("--instance", dest="multi_mode",
622 312ac745 Iustin Pop
                         help="Filter by instance name [default]",
623 312ac745 Iustin Pop
                         const=_SHUTDOWN_INSTANCES, action="store_const")
624 312ac745 Iustin Pop
625 312ac745 Iustin Pop
626 a8083063 Iustin Pop
# this is defined separately due to readability only
627 a8083063 Iustin Pop
add_opts = [
628 a8083063 Iustin Pop
  DEBUG_OPT,
629 a8083063 Iustin Pop
  node_opt,
630 b9ac33e9 Iustin Pop
  cli_option("-s", "--os-size", dest="size", help="Disk size, in MiB unless"
631 b9ac33e9 Iustin Pop
             " a suffix is used",
632 a8083063 Iustin Pop
             default=20 * 1024, type="unit", metavar="<size>"),
633 b9ac33e9 Iustin Pop
  cli_option("--swap-size", dest="swap", help="Swap size, in MiB unless a"
634 b9ac33e9 Iustin Pop
             " suffix is used",
635 a8083063 Iustin Pop
             default=4 * 1024, type="unit", metavar="<size>"),
636 d0834de3 Michael Hanselmann
  os_opt,
637 b9ac33e9 Iustin Pop
  cli_option("-m", "--memory", dest="mem", help="Memory size (in MiB)",
638 a8083063 Iustin Pop
              default=128, type="unit", metavar="<mem>"),
639 a8083063 Iustin Pop
  make_option("-p", "--cpu", dest="vcpus", help="Number of virtual CPUs",
640 a8083063 Iustin Pop
              default=1, type="int", metavar="<PROC>"),
641 a8083063 Iustin Pop
  make_option("-t", "--disk-template", dest="disk_template",
642 a8083063 Iustin Pop
              help="Custom disk setup (diskless, plain, local_raid1 or"
643 a8083063 Iustin Pop
              " remote_raid1)", default=None, metavar="TEMPL"),
644 a8083063 Iustin Pop
  make_option("-i", "--ip", dest="ip",
645 a8083063 Iustin Pop
              help="IP address ('none' [default], 'auto', or specify address)",
646 a8083063 Iustin Pop
              default='none', type="string", metavar="<ADDRESS>"),
647 a8083063 Iustin Pop
  make_option("--no-wait-for-sync", dest="wait_for_sync", default=True,
648 a8083063 Iustin Pop
              action="store_false", help="Don't wait for sync (DANGEROUS!)"),
649 a8083063 Iustin Pop
  make_option("--secondary-node", dest="snode",
650 a8083063 Iustin Pop
              help="Secondary node for remote_raid1 disk layout",
651 a8083063 Iustin Pop
              metavar="<node>"),
652 a8083063 Iustin Pop
  make_option("-b", "--bridge", dest="bridge",
653 a8083063 Iustin Pop
              help="Bridge to connect this instance to",
654 bdd55f71 Iustin Pop
              default=None, metavar="<bridge>"),
655 bdd55f71 Iustin Pop
  make_option("--no-start", dest="start", default=True,
656 bdd55f71 Iustin Pop
              action="store_false", help="Don't start the instance after"
657 bdd55f71 Iustin Pop
              " creation"),
658 bdd55f71 Iustin Pop
  make_option("--no-ip-check", dest="ip_check", default=True,
659 bdd55f71 Iustin Pop
              action="store_false", help="Don't check that the instance's IP"
660 bdd55f71 Iustin Pop
              " is alive (only valid with --no-start)"),
661 a8083063 Iustin Pop
  ]
662 a8083063 Iustin Pop
663 a8083063 Iustin Pop
commands = {
664 a8083063 Iustin Pop
  'add': (AddInstance, ARGS_ONE, add_opts,
665 a8083063 Iustin Pop
          "[opts...] <name>",
666 a8083063 Iustin Pop
          "Creates and adds a new instance to the cluster"),
667 a8083063 Iustin Pop
  'add-mirror': (AddMDDRBDComponent, ARGS_ONE,
668 a8083063 Iustin Pop
                [DEBUG_OPT, node_opt,
669 a8083063 Iustin Pop
                 make_option("-b", "--disk", dest="disk", metavar="sdX",
670 a8083063 Iustin Pop
                             help=("The name of the instance disk for which to"
671 a8083063 Iustin Pop
                                   " add the mirror"))],
672 a8083063 Iustin Pop
                "-n node -b disk <instance>",
673 a8083063 Iustin Pop
                "Creates a new mirror for the instance"),
674 a8083063 Iustin Pop
  'console': (ConnectToInstanceConsole, ARGS_ONE, [DEBUG_OPT],
675 a8083063 Iustin Pop
              "<instance>",
676 a8083063 Iustin Pop
              "Opens a console on the specified instance"),
677 a8083063 Iustin Pop
  'failover': (FailoverInstance, ARGS_ONE,
678 fe7b0351 Michael Hanselmann
               [DEBUG_OPT, FORCE_OPT,
679 a8083063 Iustin Pop
                make_option("--ignore-consistency", dest="ignore_consistency",
680 a8083063 Iustin Pop
                            action="store_true", default=False,
681 a8083063 Iustin Pop
                            help="Ignore the consistency of the disks on"
682 a8083063 Iustin Pop
                            " the secondary"),
683 a8083063 Iustin Pop
                ],
684 a8083063 Iustin Pop
               "[-f] <instance>",
685 a8083063 Iustin Pop
               "Stops the instance and starts it on the backup node, using"
686 a8083063 Iustin Pop
               " the remote mirror (only for instances of type remote_raid1)"),
687 a8083063 Iustin Pop
  'info': (ShowInstanceConfig, ARGS_ANY, [DEBUG_OPT], "[<instance>...]",
688 a8083063 Iustin Pop
           "Show information on the specified instance"),
689 a8083063 Iustin Pop
  'list': (ListInstances, ARGS_NONE,
690 dcb93971 Michael Hanselmann
           [DEBUG_OPT, NOHDR_OPT, SEP_OPT, USEUNITS_OPT, FIELDS_OPT],
691 a8083063 Iustin Pop
           "", "Lists the instances and their status"),
692 d0834de3 Michael Hanselmann
  'reinstall': (ReinstallInstance, ARGS_ONE, [DEBUG_OPT, FORCE_OPT, os_opt],
693 fe7b0351 Michael Hanselmann
                "[-f] <instance>", "Reinstall the instance"),
694 1d67656e Iustin Pop
  'remove': (RemoveInstance, ARGS_ONE,
695 1d67656e Iustin Pop
             [DEBUG_OPT, FORCE_OPT,
696 1d67656e Iustin Pop
              make_option("--ignore-failures", dest="ignore_failures",
697 1d67656e Iustin Pop
                          action="store_true", default=False,
698 1d67656e Iustin Pop
                          help=("Remove the instance from the cluster even"
699 1d67656e Iustin Pop
                                " if there are failures during the removal"
700 1d67656e Iustin Pop
                                " process (shutdown, disk removal, etc.)")),
701 1d67656e Iustin Pop
              ],
702 a8083063 Iustin Pop
             "[-f] <instance>", "Shuts down the instance and removes it"),
703 a8083063 Iustin Pop
  'remove-mirror': (RemoveMDDRBDComponent, ARGS_ONE,
704 a8083063 Iustin Pop
                   [DEBUG_OPT, node_opt,
705 a8083063 Iustin Pop
                    make_option("-b", "--disk", dest="disk", metavar="sdX",
706 a8083063 Iustin Pop
                                help=("The name of the instance disk"
707 a8083063 Iustin Pop
                                      " for which to add the mirror")),
708 a8083063 Iustin Pop
                    make_option("-p", "--port", dest="port", metavar="PORT",
709 a8083063 Iustin Pop
                                help=("The port of the drbd device"
710 a8083063 Iustin Pop
                                      " which to remove from the mirror"),
711 a8083063 Iustin Pop
                                type="int"),
712 a8083063 Iustin Pop
                    ],
713 a8083063 Iustin Pop
                   "-b disk -p port <instance>",
714 a8083063 Iustin Pop
                   "Removes a mirror from the instance"),
715 decd5f45 Iustin Pop
  'rename': (RenameInstance, ARGS_FIXED(2),
716 decd5f45 Iustin Pop
             [DEBUG_OPT,
717 decd5f45 Iustin Pop
              make_option("--no-ip-check", dest="ignore_ip",
718 decd5f45 Iustin Pop
                          help="Do not check that the IP of the new name"
719 decd5f45 Iustin Pop
                          " is alive",
720 decd5f45 Iustin Pop
                          default=False, action="store_true"),
721 decd5f45 Iustin Pop
              ],
722 decd5f45 Iustin Pop
             "<instance> <new_name>", "Rename the instance"),
723 a8083063 Iustin Pop
  'replace-disks': (ReplaceDisks, ARGS_ONE,
724 a8083063 Iustin Pop
                    [DEBUG_OPT,
725 a8083063 Iustin Pop
                     make_option("-n", "--new-secondary", dest="new_secondary",
726 a8083063 Iustin Pop
                                 metavar="NODE",
727 a8083063 Iustin Pop
                                 help=("New secondary node (if you want to"
728 a8083063 Iustin Pop
                                       " change the secondary)"))],
729 a8083063 Iustin Pop
                    "[-n NODE] <instance>",
730 a8083063 Iustin Pop
                    "Replaces all disks for the instance"),
731 a8083063 Iustin Pop
  'modify': (SetInstanceParms, ARGS_ONE,
732 fe7b0351 Michael Hanselmann
             [DEBUG_OPT, FORCE_OPT,
733 a8083063 Iustin Pop
              cli_option("-m", "--memory", dest="mem",
734 a8083063 Iustin Pop
                         help="Memory size",
735 a8083063 Iustin Pop
                         default=None, type="unit", metavar="<mem>"),
736 a8083063 Iustin Pop
              make_option("-p", "--cpu", dest="vcpus",
737 a8083063 Iustin Pop
                          help="Number of virtual CPUs",
738 a8083063 Iustin Pop
                          default=None, type="int", metavar="<PROC>"),
739 a8083063 Iustin Pop
              make_option("-i", "--ip", dest="ip",
740 a8083063 Iustin Pop
                          help="IP address ('none' or numeric IP)",
741 a8083063 Iustin Pop
                          default=None, type="string", metavar="<ADDRESS>"),
742 a8083063 Iustin Pop
              make_option("-b", "--bridge", dest="bridge",
743 a8083063 Iustin Pop
                          help="Bridge to connect this instance to",
744 decd5f45 Iustin Pop
                          default=None, type="string", metavar="<bridge>"),
745 a8083063 Iustin Pop
              ],
746 a8083063 Iustin Pop
             "<instance>", "Alters the parameters of an instance"),
747 312ac745 Iustin Pop
  'shutdown': (ShutdownInstance, ARGS_ANY,
748 312ac745 Iustin Pop
               [DEBUG_OPT, m_node_opt, m_pri_node_opt, m_sec_node_opt,
749 804a1e8e Iustin Pop
                m_clust_opt, m_inst_opt, m_force_multi],
750 a8083063 Iustin Pop
               "<instance>", "Stops an instance"),
751 312ac745 Iustin Pop
  'startup': (StartupInstance, ARGS_ANY,
752 804a1e8e Iustin Pop
              [DEBUG_OPT, FORCE_OPT, m_force_multi,
753 a8083063 Iustin Pop
               make_option("-e", "--extra", dest="extra_args",
754 a8083063 Iustin Pop
                           help="Extra arguments for the instance's kernel",
755 a8083063 Iustin Pop
                           default=None, type="string", metavar="<PARAMS>"),
756 312ac745 Iustin Pop
               m_node_opt, m_pri_node_opt, m_sec_node_opt,
757 312ac745 Iustin Pop
               m_clust_opt, m_inst_opt,
758 a8083063 Iustin Pop
               ],
759 a8083063 Iustin Pop
            "<instance>", "Starts an instance"),
760 a8083063 Iustin Pop
  'activate-disks': (ActivateDisks, ARGS_ONE, [DEBUG_OPT],
761 a8083063 Iustin Pop
                     "<instance>",
762 a8083063 Iustin Pop
                     "Activate an instance's disks"),
763 a8083063 Iustin Pop
  'deactivate-disks': (DeactivateDisks, ARGS_ONE, [DEBUG_OPT],
764 a8083063 Iustin Pop
                       "<instance>",
765 a8083063 Iustin Pop
                       "Deactivate an instance's disks"),
766 846baef9 Iustin Pop
  'list-tags': (ListTags, ARGS_ONE, [DEBUG_OPT],
767 846baef9 Iustin Pop
                "<node_name>", "List the tags of the given instance"),
768 810c50b7 Iustin Pop
  'add-tags': (AddTags, ARGS_ATLEAST(1), [DEBUG_OPT, TAG_SRC_OPT],
769 846baef9 Iustin Pop
               "<node_name> tag...", "Add tags to the given instance"),
770 810c50b7 Iustin Pop
  'remove-tags': (RemoveTags, ARGS_ATLEAST(1), [DEBUG_OPT, TAG_SRC_OPT],
771 846baef9 Iustin Pop
                  "<node_name> tag...", "Remove tags from given instance"),
772 a8083063 Iustin Pop
  }
773 a8083063 Iustin Pop
774 a8083063 Iustin Pop
if __name__ == '__main__':
775 846baef9 Iustin Pop
  sys.exit(GenericMain(commands,
776 846baef9 Iustin Pop
                       override={"tag_type": constants.TAG_INSTANCE}))