Statistics
| Branch: | Tag: | Revision:

root / scripts / gnt-instance @ dbfd89dd

History | View | Annotate | Download (34.5 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 973d7867 Iustin Pop
def _TransformPath(user_input):
138 973d7867 Iustin Pop
  """Transform a user path into a canonical value.
139 973d7867 Iustin Pop
140 973d7867 Iustin Pop
  This function transforms the a path passed as textual information
141 973d7867 Iustin Pop
  into the constants that the LU code expects.
142 973d7867 Iustin Pop
143 973d7867 Iustin Pop
  """
144 973d7867 Iustin Pop
  if user_input:
145 973d7867 Iustin Pop
    if user_input.lower() == "default":
146 973d7867 Iustin Pop
      result_path = constants.VALUE_DEFAULT
147 973d7867 Iustin Pop
    elif user_input.lower() == "none":
148 973d7867 Iustin Pop
      result_path = constants.VALUE_NONE
149 973d7867 Iustin Pop
    else:
150 973d7867 Iustin Pop
      if not os.path.isabs(user_input):
151 973d7867 Iustin Pop
        raise errors.OpPrereqError("Path '%s' is not an absolute filename" %
152 973d7867 Iustin Pop
                                   user_input)
153 973d7867 Iustin Pop
      result_path = user_input
154 973d7867 Iustin Pop
  else:
155 973d7867 Iustin Pop
    result_path = constants.VALUE_DEFAULT
156 973d7867 Iustin Pop
157 973d7867 Iustin Pop
  return result_path
158 973d7867 Iustin Pop
159 973d7867 Iustin Pop
160 a8083063 Iustin Pop
def ListInstances(opts, args):
161 f5abe9bd Oleksiy Mishchenko
  """List instances and their properties.
162 a8083063 Iustin Pop
163 a8083063 Iustin Pop
  """
164 a8083063 Iustin Pop
  if opts.output is None:
165 a8083063 Iustin Pop
    selected_fields = ["name", "os", "pnode", "admin_state",
166 a8083063 Iustin Pop
                       "oper_state", "oper_ram"]
167 a8083063 Iustin Pop
  else:
168 a8083063 Iustin Pop
    selected_fields = opts.output.split(",")
169 a8083063 Iustin Pop
170 069dcc86 Iustin Pop
  op = opcodes.OpQueryInstances(output_fields=selected_fields, names=[])
171 a8083063 Iustin Pop
  output = SubmitOpCode(op)
172 a8083063 Iustin Pop
173 a8083063 Iustin Pop
  if not opts.no_headers:
174 137161c9 Michael Hanselmann
    headers = {"name": "Instance", "os": "OS", "pnode": "Primary_node",
175 137161c9 Michael Hanselmann
               "snodes": "Secondary_Nodes", "admin_state": "Autostart",
176 137161c9 Michael Hanselmann
               "oper_state": "Status", "admin_ram": "Configured_memory",
177 137161c9 Michael Hanselmann
               "oper_ram": "Memory", "disk_template": "Disk_template",
178 137161c9 Michael Hanselmann
               "ip": "IP Address", "mac": "MAC Address",
179 644eeef9 Iustin Pop
               "bridge": "Bridge",
180 644eeef9 Iustin Pop
               "sda_size": "Disk/0", "sdb_size": "Disk/1"}
181 137161c9 Michael Hanselmann
  else:
182 137161c9 Michael Hanselmann
    headers = None
183 137161c9 Michael Hanselmann
184 137161c9 Michael Hanselmann
  if opts.human_readable:
185 644eeef9 Iustin Pop
    unitfields = ["admin_ram", "oper_ram", "sda_size", "sdb_size"]
186 137161c9 Michael Hanselmann
  else:
187 137161c9 Michael Hanselmann
    unitfields = None
188 137161c9 Michael Hanselmann
189 644eeef9 Iustin Pop
  numfields = ["admin_ram", "oper_ram", "sda_size", "sdb_size"]
190 137161c9 Michael Hanselmann
191 8a23d2d3 Iustin Pop
  # change raw values to nicer strings
192 8a23d2d3 Iustin Pop
  for row in output:
193 8a23d2d3 Iustin Pop
    for idx, field in enumerate(selected_fields):
194 8a23d2d3 Iustin Pop
      val = row[idx]
195 8a23d2d3 Iustin Pop
      if field == "snodes":
196 8a23d2d3 Iustin Pop
        val = ",".join(val) or "-"
197 8a23d2d3 Iustin Pop
      elif field == "admin_state":
198 8a23d2d3 Iustin Pop
        if val:
199 8a23d2d3 Iustin Pop
          val = "yes"
200 8a23d2d3 Iustin Pop
        else:
201 8a23d2d3 Iustin Pop
          val = "no"
202 8a23d2d3 Iustin Pop
      elif field == "oper_state":
203 8a23d2d3 Iustin Pop
        if val is None:
204 8a23d2d3 Iustin Pop
          val = "(node down)"
205 8a23d2d3 Iustin Pop
        elif val: # True
206 8a23d2d3 Iustin Pop
          val = "running"
207 8a23d2d3 Iustin Pop
        else:
208 8a23d2d3 Iustin Pop
          val = "stopped"
209 8a23d2d3 Iustin Pop
      elif field == "oper_ram":
210 8a23d2d3 Iustin Pop
        if val is None:
211 8a23d2d3 Iustin Pop
          val = "(node down)"
212 8a23d2d3 Iustin Pop
      elif field == "sda_size" or field == "sdb_size":
213 8a23d2d3 Iustin Pop
        if val is None:
214 8a23d2d3 Iustin Pop
          val = "N/A"
215 8a23d2d3 Iustin Pop
      row[idx] = str(val)
216 8a23d2d3 Iustin Pop
217 16be8703 Iustin Pop
  data = GenerateTable(separator=opts.separator, headers=headers,
218 16be8703 Iustin Pop
                       fields=selected_fields, unitfields=unitfields,
219 16be8703 Iustin Pop
                       numfields=numfields, data=output)
220 16be8703 Iustin Pop
221 16be8703 Iustin Pop
  for line in data:
222 16be8703 Iustin Pop
    logger.ToStdout(line)
223 a8083063 Iustin Pop
224 a8083063 Iustin Pop
  return 0
225 a8083063 Iustin Pop
226 a8083063 Iustin Pop
227 a8083063 Iustin Pop
def AddInstance(opts, args):
228 a8083063 Iustin Pop
  """Add an instance to the cluster.
229 a8083063 Iustin Pop
230 a8083063 Iustin Pop
  Args:
231 a8083063 Iustin Pop
    opts - class with options as members
232 a8083063 Iustin Pop
    args - list with a single element, the instance name
233 a8083063 Iustin Pop
  Opts used:
234 a8083063 Iustin Pop
    mem - amount of memory to allocate to instance (MiB)
235 a8083063 Iustin Pop
    size - amount of disk space to allocate to instance (MiB)
236 a8083063 Iustin Pop
    os - which OS to run on instance
237 a8083063 Iustin Pop
    node - node to run new instance on
238 a8083063 Iustin Pop
239 a8083063 Iustin Pop
  """
240 a8083063 Iustin Pop
  instance = args[0]
241 a8083063 Iustin Pop
242 60d49723 Michael Hanselmann
  (pnode, snode) = SplitNodeOption(opts.node)
243 60d49723 Michael Hanselmann
244 3b6d8c9b Iustin Pop
  kernel_path = _TransformPath(opts.kernel_path)
245 3b6d8c9b Iustin Pop
  initrd_path = _TransformPath(opts.initrd_path)
246 3b6d8c9b Iustin Pop
247 a8083063 Iustin Pop
  op = opcodes.OpCreateInstance(instance_name=instance, mem_size=opts.mem,
248 a8083063 Iustin Pop
                                disk_size=opts.size, swap_size=opts.swap,
249 a8083063 Iustin Pop
                                disk_template=opts.disk_template,
250 a8083063 Iustin Pop
                                mode=constants.INSTANCE_CREATE,
251 60d49723 Michael Hanselmann
                                os_type=opts.os, pnode=pnode,
252 60d49723 Michael Hanselmann
                                snode=snode, vcpus=opts.vcpus,
253 bdd55f71 Iustin Pop
                                ip=opts.ip, bridge=opts.bridge,
254 bdd55f71 Iustin Pop
                                start=opts.start, ip_check=opts.ip_check,
255 3b6d8c9b Iustin Pop
                                wait_for_sync=opts.wait_for_sync,
256 3b6d8c9b Iustin Pop
                                mac=opts.mac,
257 3b6d8c9b Iustin Pop
                                kernel_path=kernel_path,
258 25c5878d Alexander Schreiber
                                initrd_path=initrd_path,
259 25c5878d Alexander Schreiber
                                hvm_boot_order=opts.hvm_boot_order)
260 a8083063 Iustin Pop
  SubmitOpCode(op)
261 a8083063 Iustin Pop
  return 0
262 a8083063 Iustin Pop
263 a8083063 Iustin Pop
264 fe7b0351 Michael Hanselmann
def ReinstallInstance(opts, args):
265 fe7b0351 Michael Hanselmann
  """Reinstall an instance.
266 fe7b0351 Michael Hanselmann
267 fe7b0351 Michael Hanselmann
  Args:
268 fe7b0351 Michael Hanselmann
    opts - class with options as members
269 fe7b0351 Michael Hanselmann
    args - list containing a single element, the instance name
270 fe7b0351 Michael Hanselmann
271 fe7b0351 Michael Hanselmann
  """
272 fe7b0351 Michael Hanselmann
  instance_name = args[0]
273 fe7b0351 Michael Hanselmann
274 fe7b0351 Michael Hanselmann
  if not opts.force:
275 f4bc1f2c Michael Hanselmann
    usertext = ("This will reinstall the instance %s and remove"
276 f4bc1f2c Michael Hanselmann
                " all data. Continue?") % instance_name
277 47988778 Iustin Pop
    if not AskUser(usertext):
278 fe7b0351 Michael Hanselmann
      return 1
279 fe7b0351 Michael Hanselmann
280 d0834de3 Michael Hanselmann
  op = opcodes.OpReinstallInstance(instance_name=instance_name,
281 d0834de3 Michael Hanselmann
                                   os_type=opts.os)
282 fe7b0351 Michael Hanselmann
  SubmitOpCode(op)
283 fe7b0351 Michael Hanselmann
284 fe7b0351 Michael Hanselmann
  return 0
285 fe7b0351 Michael Hanselmann
286 fe7b0351 Michael Hanselmann
287 a8083063 Iustin Pop
def RemoveInstance(opts, args):
288 a8083063 Iustin Pop
  """Remove an instance.
289 a8083063 Iustin Pop
290 a8083063 Iustin Pop
  Args:
291 a8083063 Iustin Pop
    opts - class with options as members
292 a8083063 Iustin Pop
    args - list containing a single element, the instance name
293 a8083063 Iustin Pop
294 a8083063 Iustin Pop
  """
295 a8083063 Iustin Pop
  instance_name = args[0]
296 a8083063 Iustin Pop
  force = opts.force
297 a8083063 Iustin Pop
298 a8083063 Iustin Pop
  if not force:
299 a8083063 Iustin Pop
    usertext = ("This will remove the volumes of the instance %s"
300 a8083063 Iustin Pop
                " (including mirrors), thus removing all the data"
301 a8083063 Iustin Pop
                " of the instance. Continue?") % instance_name
302 47988778 Iustin Pop
    if not AskUser(usertext):
303 a8083063 Iustin Pop
      return 1
304 a8083063 Iustin Pop
305 1d67656e Iustin Pop
  op = opcodes.OpRemoveInstance(instance_name=instance_name,
306 1d67656e Iustin Pop
                                ignore_failures=opts.ignore_failures)
307 a8083063 Iustin Pop
  SubmitOpCode(op)
308 a8083063 Iustin Pop
  return 0
309 a8083063 Iustin Pop
310 a8083063 Iustin Pop
311 decd5f45 Iustin Pop
def RenameInstance(opts, args):
312 4ab0b9e3 Guido Trotter
  """Rename an instance.
313 decd5f45 Iustin Pop
314 decd5f45 Iustin Pop
  Args:
315 decd5f45 Iustin Pop
    opts - class with options as members
316 decd5f45 Iustin Pop
    args - list containing two elements, the instance name and the new name
317 decd5f45 Iustin Pop
318 decd5f45 Iustin Pop
  """
319 decd5f45 Iustin Pop
  op = opcodes.OpRenameInstance(instance_name=args[0],
320 decd5f45 Iustin Pop
                                new_name=args[1],
321 decd5f45 Iustin Pop
                                ignore_ip=opts.ignore_ip)
322 decd5f45 Iustin Pop
  SubmitOpCode(op)
323 decd5f45 Iustin Pop
324 decd5f45 Iustin Pop
  return 0
325 decd5f45 Iustin Pop
326 decd5f45 Iustin Pop
327 a8083063 Iustin Pop
def ActivateDisks(opts, args):
328 a8083063 Iustin Pop
  """Activate an instance's disks.
329 a8083063 Iustin Pop
330 a8083063 Iustin Pop
  This serves two purposes:
331 a8083063 Iustin Pop
    - it allows one (as long as the instance is not running) to mount
332 a8083063 Iustin Pop
    the disks and modify them from the node
333 a8083063 Iustin Pop
    - it repairs inactive secondary drbds
334 a8083063 Iustin Pop
335 a8083063 Iustin Pop
  """
336 a8083063 Iustin Pop
  instance_name = args[0]
337 a8083063 Iustin Pop
  op = opcodes.OpActivateInstanceDisks(instance_name=instance_name)
338 a8083063 Iustin Pop
  disks_info = SubmitOpCode(op)
339 a8083063 Iustin Pop
  for host, iname, nname in disks_info:
340 a8083063 Iustin Pop
    print "%s:%s:%s" % (host, iname, nname)
341 a8083063 Iustin Pop
  return 0
342 a8083063 Iustin Pop
343 a8083063 Iustin Pop
344 a8083063 Iustin Pop
def DeactivateDisks(opts, args):
345 a8083063 Iustin Pop
  """Command-line interface for _ShutdownInstanceBlockDevices.
346 a8083063 Iustin Pop
347 a8083063 Iustin Pop
  This function takes the instance name, looks for its primary node
348 a8083063 Iustin Pop
  and the tries to shutdown its block devices on that node.
349 a8083063 Iustin Pop
350 a8083063 Iustin Pop
  """
351 a8083063 Iustin Pop
  instance_name = args[0]
352 a8083063 Iustin Pop
  op = opcodes.OpDeactivateInstanceDisks(instance_name=instance_name)
353 a8083063 Iustin Pop
  SubmitOpCode(op)
354 a8083063 Iustin Pop
  return 0
355 a8083063 Iustin Pop
356 a8083063 Iustin Pop
357 a8083063 Iustin Pop
def StartupInstance(opts, args):
358 decd5f45 Iustin Pop
  """Startup an instance.
359 a8083063 Iustin Pop
360 a8083063 Iustin Pop
  Args:
361 a8083063 Iustin Pop
    opts - class with options as members
362 a8083063 Iustin Pop
    args - list containing a single element, the instance name
363 a8083063 Iustin Pop
364 a8083063 Iustin Pop
  """
365 312ac745 Iustin Pop
  if opts.multi_mode is None:
366 312ac745 Iustin Pop
    opts.multi_mode = _SHUTDOWN_INSTANCES
367 312ac745 Iustin Pop
  inames = _ExpandMultiNames(opts.multi_mode, args)
368 bcee9cb4 Iustin Pop
  if not inames:
369 bcee9cb4 Iustin Pop
    raise errors.OpPrereqError("Selection filter does not match any instances")
370 804a1e8e Iustin Pop
  multi_on = opts.multi_mode != _SHUTDOWN_INSTANCES or len(inames) > 1
371 804a1e8e Iustin Pop
  if not (opts.force_multi or not multi_on
372 804a1e8e Iustin Pop
          or _ConfirmOperation(inames, "startup")):
373 804a1e8e Iustin Pop
    return 1
374 312ac745 Iustin Pop
  for name in inames:
375 312ac745 Iustin Pop
    op = opcodes.OpStartupInstance(instance_name=name,
376 312ac745 Iustin Pop
                                   force=opts.force,
377 312ac745 Iustin Pop
                                   extra_args=opts.extra_args)
378 312ac745 Iustin Pop
    if multi_on:
379 312ac745 Iustin Pop
      logger.ToStdout("Starting up %s" % name)
380 312ac745 Iustin Pop
    SubmitOpCode(op)
381 a8083063 Iustin Pop
  return 0
382 a8083063 Iustin Pop
383 579d4337 Alexander Schreiber
def RebootInstance(opts, args):
384 579d4337 Alexander Schreiber
  """Reboot an instance
385 579d4337 Alexander Schreiber
386 579d4337 Alexander Schreiber
  Args:
387 579d4337 Alexander Schreiber
    opts - class with options as members
388 579d4337 Alexander Schreiber
    args - list containing a single element, the instance name
389 579d4337 Alexander Schreiber
390 579d4337 Alexander Schreiber
  """
391 579d4337 Alexander Schreiber
  if opts.multi_mode is None:
392 579d4337 Alexander Schreiber
    opts.multi_mode = _SHUTDOWN_INSTANCES
393 579d4337 Alexander Schreiber
  inames = _ExpandMultiNames(opts.multi_mode, args)
394 bcee9cb4 Iustin Pop
  if not inames:
395 bcee9cb4 Iustin Pop
    raise errors.OpPrereqError("Selection filter does not match any instances")
396 579d4337 Alexander Schreiber
  multi_on = opts.multi_mode != _SHUTDOWN_INSTANCES or len(inames) > 1
397 579d4337 Alexander Schreiber
  if not (opts.force_multi or not multi_on
398 579d4337 Alexander Schreiber
          or _ConfirmOperation(inames, "reboot")):
399 579d4337 Alexander Schreiber
    return 1
400 579d4337 Alexander Schreiber
  for name in inames:
401 579d4337 Alexander Schreiber
    op = opcodes.OpRebootInstance(instance_name=name,
402 579d4337 Alexander Schreiber
                                  reboot_type=opts.reboot_type,
403 579d4337 Alexander Schreiber
                                  ignore_secondaries=opts.ignore_secondaries)
404 579d4337 Alexander Schreiber
405 579d4337 Alexander Schreiber
    SubmitOpCode(op)
406 579d4337 Alexander Schreiber
  return 0
407 a8083063 Iustin Pop
408 a8083063 Iustin Pop
def ShutdownInstance(opts, args):
409 a8083063 Iustin Pop
  """Shutdown an instance.
410 a8083063 Iustin Pop
411 a8083063 Iustin Pop
  Args:
412 a8083063 Iustin Pop
    opts - class with options as members
413 a8083063 Iustin Pop
    args - list containing a single element, the instance name
414 a8083063 Iustin Pop
415 a8083063 Iustin Pop
  """
416 312ac745 Iustin Pop
  if opts.multi_mode is None:
417 312ac745 Iustin Pop
    opts.multi_mode = _SHUTDOWN_INSTANCES
418 312ac745 Iustin Pop
  inames = _ExpandMultiNames(opts.multi_mode, args)
419 bcee9cb4 Iustin Pop
  if not inames:
420 bcee9cb4 Iustin Pop
    raise errors.OpPrereqError("Selection filter does not match any instances")
421 804a1e8e Iustin Pop
  multi_on = opts.multi_mode != _SHUTDOWN_INSTANCES or len(inames) > 1
422 804a1e8e Iustin Pop
  if not (opts.force_multi or not multi_on
423 804a1e8e Iustin Pop
          or _ConfirmOperation(inames, "shutdown")):
424 804a1e8e Iustin Pop
    return 1
425 312ac745 Iustin Pop
  for name in inames:
426 312ac745 Iustin Pop
    op = opcodes.OpShutdownInstance(instance_name=name)
427 312ac745 Iustin Pop
    if multi_on:
428 312ac745 Iustin Pop
      logger.ToStdout("Shutting down %s" % name)
429 312ac745 Iustin Pop
    SubmitOpCode(op)
430 a8083063 Iustin Pop
  return 0
431 a8083063 Iustin Pop
432 a8083063 Iustin Pop
433 a8083063 Iustin Pop
def AddMDDRBDComponent(opts, args):
434 a8083063 Iustin Pop
  """Add a new component to a remote_raid1 disk.
435 a8083063 Iustin Pop
436 a8083063 Iustin Pop
  Args:
437 a8083063 Iustin Pop
    opts - class with options as members
438 a8083063 Iustin Pop
    args - list with a single element, the instance name
439 a8083063 Iustin Pop
440 a8083063 Iustin Pop
  """
441 a8083063 Iustin Pop
  op = opcodes.OpAddMDDRBDComponent(instance_name=args[0],
442 a8083063 Iustin Pop
                                    disk_name=opts.disk,
443 a8083063 Iustin Pop
                                    remote_node=opts.node)
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 RemoveMDDRBDComponent(opts, args):
449 bdb8c997 Guido Trotter
  """Remove a component from a remote_raid1 disk.
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
  op = opcodes.OpRemoveMDDRBDComponent(instance_name=args[0],
457 a8083063 Iustin Pop
                                       disk_name=opts.disk,
458 a8083063 Iustin Pop
                                       disk_id=opts.port)
459 a8083063 Iustin Pop
  SubmitOpCode(op)
460 a8083063 Iustin Pop
  return 0
461 a8083063 Iustin Pop
462 a8083063 Iustin Pop
463 a8083063 Iustin Pop
def ReplaceDisks(opts, args):
464 a8083063 Iustin Pop
  """Replace the disks of an instance
465 a8083063 Iustin Pop
466 a8083063 Iustin Pop
  Args:
467 a8083063 Iustin Pop
    opts - class with options as members
468 a8083063 Iustin Pop
    args - list with a single element, the instance name
469 a8083063 Iustin Pop
470 a8083063 Iustin Pop
  """
471 a8083063 Iustin Pop
  instance_name = args[0]
472 a9e0c397 Iustin Pop
  new_2ndary = opts.new_secondary
473 a9e0c397 Iustin Pop
  if opts.disks is None:
474 a9e0c397 Iustin Pop
    disks = ["sda", "sdb"]
475 a9e0c397 Iustin Pop
  else:
476 a9e0c397 Iustin Pop
    disks = opts.disks.split(",")
477 a9e0c397 Iustin Pop
  if opts.on_primary == opts.on_secondary: # no -p or -s passed, or both passed
478 a9e0c397 Iustin Pop
    mode = constants.REPLACE_DISK_ALL
479 a9e0c397 Iustin Pop
  elif opts.on_primary: # only on primary:
480 a9e0c397 Iustin Pop
    mode = constants.REPLACE_DISK_PRI
481 a9e0c397 Iustin Pop
    if new_2ndary is not None:
482 a9e0c397 Iustin Pop
      raise errors.OpPrereqError("Can't change secondary node on primary disk"
483 a9e0c397 Iustin Pop
                                 " replacement")
484 a9e0c397 Iustin Pop
  elif opts.on_secondary is not None: # only on secondary
485 a9e0c397 Iustin Pop
    mode = constants.REPLACE_DISK_SEC
486 a9e0c397 Iustin Pop
487 a9e0c397 Iustin Pop
  op = opcodes.OpReplaceDisks(instance_name=args[0], disks=disks,
488 a9e0c397 Iustin Pop
                              remote_node=new_2ndary, mode=mode)
489 a8083063 Iustin Pop
  SubmitOpCode(op)
490 a8083063 Iustin Pop
  return 0
491 a8083063 Iustin Pop
492 a8083063 Iustin Pop
493 a8083063 Iustin Pop
def FailoverInstance(opts, args):
494 a8083063 Iustin Pop
  """Failover an instance.
495 a8083063 Iustin Pop
496 a8083063 Iustin Pop
  The failover is done by shutting it down on its present node and
497 a8083063 Iustin Pop
  starting it on the secondary.
498 a8083063 Iustin Pop
499 a8083063 Iustin Pop
  Args:
500 a8083063 Iustin Pop
    opts - class with options as members
501 a8083063 Iustin Pop
    args - list with a single element, the instance name
502 a8083063 Iustin Pop
  Opts used:
503 a8083063 Iustin Pop
    force - whether to failover without asking questions.
504 a8083063 Iustin Pop
505 a8083063 Iustin Pop
  """
506 80de0e3f Iustin Pop
  instance_name = args[0]
507 80de0e3f Iustin Pop
  force = opts.force
508 a8083063 Iustin Pop
509 80de0e3f Iustin Pop
  if not force:
510 80de0e3f Iustin Pop
    usertext = ("Failover will happen to image %s."
511 80de0e3f Iustin Pop
                " This requires a shutdown of the instance. Continue?" %
512 80de0e3f Iustin Pop
                (instance_name,))
513 80de0e3f Iustin Pop
    if not AskUser(usertext):
514 80de0e3f Iustin Pop
      return 1
515 a8083063 Iustin Pop
516 80de0e3f Iustin Pop
  op = opcodes.OpFailoverInstance(instance_name=instance_name,
517 80de0e3f Iustin Pop
                                  ignore_consistency=opts.ignore_consistency)
518 80de0e3f Iustin Pop
  SubmitOpCode(op)
519 80de0e3f Iustin Pop
  return 0
520 a8083063 Iustin Pop
521 a8083063 Iustin Pop
522 a8083063 Iustin Pop
def ConnectToInstanceConsole(opts, args):
523 a8083063 Iustin Pop
  """Connect to the console of an instance.
524 a8083063 Iustin Pop
525 a8083063 Iustin Pop
  Args:
526 a8083063 Iustin Pop
    opts - class with options as members
527 a8083063 Iustin Pop
    args - list with a single element, the instance name
528 a8083063 Iustin Pop
529 a8083063 Iustin Pop
  """
530 a8083063 Iustin Pop
  instance_name = args[0]
531 a8083063 Iustin Pop
532 a8083063 Iustin Pop
  op = opcodes.OpConnectConsole(instance_name=instance_name)
533 82122173 Iustin Pop
  cmd, argv = SubmitOpCode(op)
534 a8083063 Iustin Pop
  # drop lock and exec so other commands can run while we have console
535 a8083063 Iustin Pop
  utils.Unlock("cmd")
536 a8083063 Iustin Pop
  try:
537 82122173 Iustin Pop
    os.execvp(cmd, argv)
538 a8083063 Iustin Pop
  finally:
539 82122173 Iustin Pop
    sys.stderr.write("Can't run console command %s with arguments:\n'%s'" %
540 82122173 Iustin Pop
                     (cmd, " ".join(argv)))
541 a8083063 Iustin Pop
    os._exit(1)
542 a8083063 Iustin Pop
543 a8083063 Iustin Pop
544 a8083063 Iustin Pop
def _FormatBlockDevInfo(buf, dev, indent_level):
545 a8083063 Iustin Pop
  """Show block device information.
546 a8083063 Iustin Pop
547 a8083063 Iustin Pop
  This is only used by ShowInstanceConfig(), but it's too big to be
548 a8083063 Iustin Pop
  left for an inline definition.
549 a8083063 Iustin Pop
550 a8083063 Iustin Pop
  """
551 a8083063 Iustin Pop
  def helper(buf, dtype, status):
552 a8083063 Iustin Pop
    """Format one line for phsyical device status."""
553 a8083063 Iustin Pop
    if not status:
554 a8083063 Iustin Pop
      buf.write("not active\n")
555 a8083063 Iustin Pop
    else:
556 0834c866 Iustin Pop
      (path, major, minor, syncp, estt, degr, ldisk) = status
557 a8083063 Iustin Pop
      buf.write("%s (%d:%d)" % (path, major, minor))
558 a1f445d3 Iustin Pop
      if dtype in (constants.LD_MD_R1, constants.LD_DRBD7, constants.LD_DRBD8):
559 a8083063 Iustin Pop
        if syncp is not None:
560 a8083063 Iustin Pop
          sync_text = "*RECOVERING* %5.2f%%," % syncp
561 a8083063 Iustin Pop
          if estt:
562 a8083063 Iustin Pop
            sync_text += " ETA %ds" % estt
563 a8083063 Iustin Pop
          else:
564 a8083063 Iustin Pop
            sync_text += " ETA unknown"
565 a8083063 Iustin Pop
        else:
566 a8083063 Iustin Pop
          sync_text = "in sync"
567 a8083063 Iustin Pop
        if degr:
568 a8083063 Iustin Pop
          degr_text = "*DEGRADED*"
569 a8083063 Iustin Pop
        else:
570 a8083063 Iustin Pop
          degr_text = "ok"
571 0834c866 Iustin Pop
        if ldisk:
572 0834c866 Iustin Pop
          ldisk_text = " *MISSING DISK*"
573 0834c866 Iustin Pop
        else:
574 0834c866 Iustin Pop
          ldisk_text = ""
575 0834c866 Iustin Pop
        buf.write(" %s, status %s%s" % (sync_text, degr_text, ldisk_text))
576 9db6dbce Iustin Pop
      elif dtype == constants.LD_LV:
577 0834c866 Iustin Pop
        if ldisk:
578 0834c866 Iustin Pop
          ldisk_text = " *FAILED* (failed drive?)"
579 9db6dbce Iustin Pop
        else:
580 0834c866 Iustin Pop
          ldisk_text = ""
581 0834c866 Iustin Pop
        buf.write(ldisk_text)
582 a8083063 Iustin Pop
      buf.write("\n")
583 a8083063 Iustin Pop
584 a8083063 Iustin Pop
  if dev["iv_name"] is not None:
585 a8083063 Iustin Pop
    data = "  - %s, " % dev["iv_name"]
586 a8083063 Iustin Pop
  else:
587 a8083063 Iustin Pop
    data = "  - "
588 a8083063 Iustin Pop
  data += "type: %s" % dev["dev_type"]
589 a8083063 Iustin Pop
  if dev["logical_id"] is not None:
590 a8083063 Iustin Pop
    data += ", logical_id: %s" % (dev["logical_id"],)
591 a8083063 Iustin Pop
  elif dev["physical_id"] is not None:
592 a8083063 Iustin Pop
    data += ", physical_id: %s" % (dev["physical_id"],)
593 a8083063 Iustin Pop
  buf.write("%*s%s\n" % (2*indent_level, "", data))
594 a8083063 Iustin Pop
  buf.write("%*s    primary:   " % (2*indent_level, ""))
595 a8083063 Iustin Pop
  helper(buf, dev["dev_type"], dev["pstatus"])
596 a8083063 Iustin Pop
597 a8083063 Iustin Pop
  if dev["sstatus"]:
598 a8083063 Iustin Pop
    buf.write("%*s    secondary: " % (2*indent_level, ""))
599 a8083063 Iustin Pop
    helper(buf, dev["dev_type"], dev["sstatus"])
600 a8083063 Iustin Pop
601 a8083063 Iustin Pop
  if dev["children"]:
602 a8083063 Iustin Pop
    for child in dev["children"]:
603 a8083063 Iustin Pop
      _FormatBlockDevInfo(buf, child, indent_level+1)
604 a8083063 Iustin Pop
605 a8083063 Iustin Pop
606 a8083063 Iustin Pop
def ShowInstanceConfig(opts, args):
607 a8083063 Iustin Pop
  """Compute instance run-time status.
608 a8083063 Iustin Pop
609 a8083063 Iustin Pop
  """
610 a8083063 Iustin Pop
  retcode = 0
611 a8083063 Iustin Pop
  op = opcodes.OpQueryInstanceData(instances=args)
612 a8083063 Iustin Pop
  result = SubmitOpCode(op)
613 a8083063 Iustin Pop
614 a8083063 Iustin Pop
  if not result:
615 a8083063 Iustin Pop
    logger.ToStdout("No instances.")
616 a8083063 Iustin Pop
    return 1
617 a8083063 Iustin Pop
618 a8083063 Iustin Pop
  buf = StringIO()
619 a8083063 Iustin Pop
  retcode = 0
620 a8083063 Iustin Pop
  for instance_name in result:
621 a8083063 Iustin Pop
    instance = result[instance_name]
622 a8083063 Iustin Pop
    buf.write("Instance name: %s\n" % instance["name"])
623 a8083063 Iustin Pop
    buf.write("State: configured to be %s, actual state is %s\n" %
624 a8083063 Iustin Pop
              (instance["config_state"], instance["run_state"]))
625 a8083063 Iustin Pop
    buf.write("  Nodes:\n")
626 a8083063 Iustin Pop
    buf.write("    - primary: %s\n" % instance["pnode"])
627 a8083063 Iustin Pop
    buf.write("    - secondaries: %s\n" % ", ".join(instance["snodes"]))
628 a8083063 Iustin Pop
    buf.write("  Operating system: %s\n" % instance["os"])
629 58acb49d Alexander Schreiber
    buf.write("  Allocated network port: %s\n" % instance["network_port"])
630 71aa8f73 Iustin Pop
    if instance["kernel_path"] in (None, constants.VALUE_DEFAULT):
631 71aa8f73 Iustin Pop
      kpath = "(default: %s)" % constants.XEN_KERNEL
632 71aa8f73 Iustin Pop
    else:
633 71aa8f73 Iustin Pop
      kpath = instance["kernel_path"]
634 71aa8f73 Iustin Pop
    buf.write("  Kernel path: %s\n" % kpath)
635 71aa8f73 Iustin Pop
    if instance["initrd_path"] in (None, constants.VALUE_DEFAULT):
636 71aa8f73 Iustin Pop
      initrd = "(default: %s)" % constants.XEN_INITRD
637 71aa8f73 Iustin Pop
    elif instance["initrd_path"] == constants.VALUE_NONE:
638 71aa8f73 Iustin Pop
      initrd = "(none)"
639 71aa8f73 Iustin Pop
    else:
640 71aa8f73 Iustin Pop
      initrd = instance["initrd_path"]
641 71aa8f73 Iustin Pop
    buf.write("       initrd: %s\n" % initrd)
642 8ae6bb54 Iustin Pop
    buf.write("  HVM boot order: %s\n" % instance["hvm_boot_order"])
643 a8083063 Iustin Pop
    buf.write("  Hardware:\n")
644 f55ff7ec Iustin Pop
    buf.write("    - VCPUs: %d\n" % instance["vcpus"])
645 a8083063 Iustin Pop
    buf.write("    - memory: %dMiB\n" % instance["memory"])
646 a8083063 Iustin Pop
    buf.write("    - NICs: %s\n" %
647 a8083063 Iustin Pop
        ", ".join(["{MAC: %s, IP: %s, bridge: %s}" %
648 a8083063 Iustin Pop
                   (mac, ip, bridge)
649 a8083063 Iustin Pop
                     for mac, ip, bridge in instance["nics"]]))
650 a8083063 Iustin Pop
    buf.write("  Block devices:\n")
651 a8083063 Iustin Pop
652 a8083063 Iustin Pop
    for device in instance["disks"]:
653 a8083063 Iustin Pop
      _FormatBlockDevInfo(buf, device, 1)
654 a8083063 Iustin Pop
655 a8083063 Iustin Pop
  logger.ToStdout(buf.getvalue().rstrip('\n'))
656 a8083063 Iustin Pop
  return retcode
657 a8083063 Iustin Pop
658 a8083063 Iustin Pop
659 a8083063 Iustin Pop
def SetInstanceParms(opts, args):
660 a8083063 Iustin Pop
  """Modifies an instance.
661 a8083063 Iustin Pop
662 a8083063 Iustin Pop
  All parameters take effect only at the next restart of the instance.
663 a8083063 Iustin Pop
664 a8083063 Iustin Pop
  Args:
665 a8083063 Iustin Pop
    opts - class with options as members
666 a8083063 Iustin Pop
    args - list with a single element, the instance name
667 a8083063 Iustin Pop
  Opts used:
668 a8083063 Iustin Pop
    memory - the new memory size
669 a8083063 Iustin Pop
    vcpus - the new number of cpus
670 1862d460 Alexander Schreiber
    mac - the new MAC address of the instance
671 a8083063 Iustin Pop
672 a8083063 Iustin Pop
  """
673 973d7867 Iustin Pop
  if not (opts.mem or opts.vcpus or opts.ip or opts.bridge or opts.mac or
674 25c5878d Alexander Schreiber
          opts.kernel_path or opts.initrd_path or opts.hvm_boot_order):
675 a8083063 Iustin Pop
    logger.ToStdout("Please give at least one of the parameters.")
676 a8083063 Iustin Pop
    return 1
677 a8083063 Iustin Pop
678 973d7867 Iustin Pop
  kernel_path = _TransformPath(opts.kernel_path)
679 973d7867 Iustin Pop
  initrd_path = _TransformPath(opts.initrd_path)
680 25c5878d Alexander Schreiber
  if opts.hvm_boot_order.lower() == 'default':
681 25c5878d Alexander Schreiber
    hvm_boot_order = constants.VALUE_DEFAULT
682 25c5878d Alexander Schreiber
  else:
683 25c5878d Alexander Schreiber
    hvm_boot_order = opts.hvm_boot_order
684 973d7867 Iustin Pop
685 a8083063 Iustin Pop
  op = opcodes.OpSetInstanceParms(instance_name=args[0], mem=opts.mem,
686 a8083063 Iustin Pop
                                  vcpus=opts.vcpus, ip=opts.ip,
687 973d7867 Iustin Pop
                                  bridge=opts.bridge, mac=opts.mac,
688 973d7867 Iustin Pop
                                  kernel_path=opts.kernel_path,
689 25c5878d Alexander Schreiber
                                  initrd_path=opts.initrd_path,
690 25c5878d Alexander Schreiber
                                  hvm_boot_order=hvm_boot_order)
691 a8083063 Iustin Pop
  result = SubmitOpCode(op)
692 a8083063 Iustin Pop
693 a8083063 Iustin Pop
  if result:
694 a8083063 Iustin Pop
    logger.ToStdout("Modified instance %s" % args[0])
695 a8083063 Iustin Pop
    for param, data in result:
696 a8083063 Iustin Pop
      logger.ToStdout(" - %-5s -> %s" % (param, data))
697 a8083063 Iustin Pop
    logger.ToStdout("Please don't forget that these parameters take effect"
698 a8083063 Iustin Pop
                    " only at the next start of the instance.")
699 a8083063 Iustin Pop
  return 0
700 a8083063 Iustin Pop
701 a8083063 Iustin Pop
702 a8083063 Iustin Pop
# options used in more than one cmd
703 a8083063 Iustin Pop
node_opt = make_option("-n", "--node", dest="node", help="Target node",
704 a8083063 Iustin Pop
                       metavar="<node>")
705 a8083063 Iustin Pop
706 d0834de3 Michael Hanselmann
os_opt = cli_option("-o", "--os-type", dest="os", help="What OS to run",
707 739ecd56 Michael Hanselmann
                    metavar="<os>")
708 d0834de3 Michael Hanselmann
709 312ac745 Iustin Pop
# multi-instance selection options
710 804a1e8e Iustin Pop
m_force_multi = make_option("--force-multiple", dest="force_multi",
711 804a1e8e Iustin Pop
                            help="Do not ask for confirmation when more than"
712 804a1e8e Iustin Pop
                            " one instance is affected",
713 804a1e8e Iustin Pop
                            action="store_true", default=False)
714 804a1e8e Iustin Pop
715 312ac745 Iustin Pop
m_pri_node_opt = make_option("--primary", dest="multi_mode",
716 312ac745 Iustin Pop
                             help="Filter by nodes (primary only)",
717 312ac745 Iustin Pop
                             const=_SHUTDOWN_NODES_PRI, action="store_const")
718 312ac745 Iustin Pop
719 312ac745 Iustin Pop
m_sec_node_opt = make_option("--secondary", dest="multi_mode",
720 312ac745 Iustin Pop
                             help="Filter by nodes (secondary only)",
721 312ac745 Iustin Pop
                             const=_SHUTDOWN_NODES_SEC, action="store_const")
722 312ac745 Iustin Pop
723 312ac745 Iustin Pop
m_node_opt = make_option("--node", dest="multi_mode",
724 312ac745 Iustin Pop
                         help="Filter by nodes (primary and secondary)",
725 312ac745 Iustin Pop
                         const=_SHUTDOWN_NODES_BOTH, action="store_const")
726 312ac745 Iustin Pop
727 312ac745 Iustin Pop
m_clust_opt = make_option("--all", dest="multi_mode",
728 312ac745 Iustin Pop
                          help="Select all instances in the cluster",
729 312ac745 Iustin Pop
                          const=_SHUTDOWN_CLUSTER, action="store_const")
730 312ac745 Iustin Pop
731 312ac745 Iustin Pop
m_inst_opt = make_option("--instance", dest="multi_mode",
732 312ac745 Iustin Pop
                         help="Filter by instance name [default]",
733 312ac745 Iustin Pop
                         const=_SHUTDOWN_INSTANCES, action="store_const")
734 312ac745 Iustin Pop
735 312ac745 Iustin Pop
736 a8083063 Iustin Pop
# this is defined separately due to readability only
737 a8083063 Iustin Pop
add_opts = [
738 a8083063 Iustin Pop
  DEBUG_OPT,
739 60d49723 Michael Hanselmann
  make_option("-n", "--node", dest="node",
740 60d49723 Michael Hanselmann
              help="Target node and optional secondary node",
741 60d49723 Michael Hanselmann
              metavar="<pnode>[:<snode>]"),
742 b9ac33e9 Iustin Pop
  cli_option("-s", "--os-size", dest="size", help="Disk size, in MiB unless"
743 b9ac33e9 Iustin Pop
             " a suffix is used",
744 a8083063 Iustin Pop
             default=20 * 1024, type="unit", metavar="<size>"),
745 b9ac33e9 Iustin Pop
  cli_option("--swap-size", dest="swap", help="Swap size, in MiB unless a"
746 b9ac33e9 Iustin Pop
             " suffix is used",
747 a8083063 Iustin Pop
             default=4 * 1024, type="unit", metavar="<size>"),
748 d0834de3 Michael Hanselmann
  os_opt,
749 b9ac33e9 Iustin Pop
  cli_option("-m", "--memory", dest="mem", help="Memory size (in MiB)",
750 a8083063 Iustin Pop
              default=128, type="unit", metavar="<mem>"),
751 a8083063 Iustin Pop
  make_option("-p", "--cpu", dest="vcpus", help="Number of virtual CPUs",
752 a8083063 Iustin Pop
              default=1, type="int", metavar="<PROC>"),
753 a8083063 Iustin Pop
  make_option("-t", "--disk-template", dest="disk_template",
754 a1f445d3 Iustin Pop
              help="Custom disk setup (diskless, plain, local_raid1,"
755 a1f445d3 Iustin Pop
              " remote_raid1 or drbd)", default=None, metavar="TEMPL"),
756 a8083063 Iustin Pop
  make_option("-i", "--ip", dest="ip",
757 a8083063 Iustin Pop
              help="IP address ('none' [default], 'auto', or specify address)",
758 a8083063 Iustin Pop
              default='none', type="string", metavar="<ADDRESS>"),
759 1862d460 Alexander Schreiber
  make_option("--mac", dest="mac",
760 1862d460 Alexander Schreiber
              help="MAC address ('auto' [default], or specify address)",
761 1862d460 Alexander Schreiber
              default='auto', type="string", metavar="<MACADDRESS>"),
762 a8083063 Iustin Pop
  make_option("--no-wait-for-sync", dest="wait_for_sync", default=True,
763 a8083063 Iustin Pop
              action="store_false", help="Don't wait for sync (DANGEROUS!)"),
764 a8083063 Iustin Pop
  make_option("-b", "--bridge", dest="bridge",
765 a8083063 Iustin Pop
              help="Bridge to connect this instance to",
766 bdd55f71 Iustin Pop
              default=None, metavar="<bridge>"),
767 bdd55f71 Iustin Pop
  make_option("--no-start", dest="start", default=True,
768 bdd55f71 Iustin Pop
              action="store_false", help="Don't start the instance after"
769 bdd55f71 Iustin Pop
              " creation"),
770 bdd55f71 Iustin Pop
  make_option("--no-ip-check", dest="ip_check", default=True,
771 bdd55f71 Iustin Pop
              action="store_false", help="Don't check that the instance's IP"
772 bdd55f71 Iustin Pop
              " is alive (only valid with --no-start)"),
773 3b6d8c9b Iustin Pop
  make_option("--kernel", dest="kernel_path",
774 3b6d8c9b Iustin Pop
              help="Path to the instances' kernel (or 'default')",
775 3b6d8c9b Iustin Pop
              default=None,
776 3b6d8c9b Iustin Pop
              type="string", metavar="<FILENAME>"),
777 3b6d8c9b Iustin Pop
  make_option("--initrd", dest="initrd_path",
778 3b6d8c9b Iustin Pop
              help="Path to the instances' initrd (or 'none', or 'default')",
779 3b6d8c9b Iustin Pop
              default=None,
780 3b6d8c9b Iustin Pop
              type="string", metavar="<FILENAME>"),
781 25c5878d Alexander Schreiber
  make_option("--hvm-boot-order", dest="hvm_boot_order",
782 25c5878d Alexander Schreiber
              help="boot device order for HVM (one or more of [acdn])",
783 25c5878d Alexander Schreiber
              default=None, type="string", metavar="<BOOTORDER>"),
784 a8083063 Iustin Pop
  ]
785 a8083063 Iustin Pop
786 a8083063 Iustin Pop
commands = {
787 a8083063 Iustin Pop
  'add': (AddInstance, ARGS_ONE, add_opts,
788 a8083063 Iustin Pop
          "[opts...] <name>",
789 a8083063 Iustin Pop
          "Creates and adds a new instance to the cluster"),
790 a8083063 Iustin Pop
  'add-mirror': (AddMDDRBDComponent, ARGS_ONE,
791 a8083063 Iustin Pop
                [DEBUG_OPT, node_opt,
792 a8083063 Iustin Pop
                 make_option("-b", "--disk", dest="disk", metavar="sdX",
793 a8083063 Iustin Pop
                             help=("The name of the instance disk for which to"
794 a8083063 Iustin Pop
                                   " add the mirror"))],
795 a8083063 Iustin Pop
                "-n node -b disk <instance>",
796 a8083063 Iustin Pop
                "Creates a new mirror for the instance"),
797 a8083063 Iustin Pop
  'console': (ConnectToInstanceConsole, ARGS_ONE, [DEBUG_OPT],
798 a8083063 Iustin Pop
              "<instance>",
799 a8083063 Iustin Pop
              "Opens a console on the specified instance"),
800 80de0e3f Iustin Pop
  'failover': (FailoverInstance, ARGS_ONE,
801 fe7b0351 Michael Hanselmann
               [DEBUG_OPT, FORCE_OPT,
802 a8083063 Iustin Pop
                make_option("--ignore-consistency", dest="ignore_consistency",
803 a8083063 Iustin Pop
                            action="store_true", default=False,
804 a8083063 Iustin Pop
                            help="Ignore the consistency of the disks on"
805 a8083063 Iustin Pop
                            " the secondary"),
806 a8083063 Iustin Pop
                ],
807 a8083063 Iustin Pop
               "[-f] <instance>",
808 a8083063 Iustin Pop
               "Stops the instance and starts it on the backup node, using"
809 a8083063 Iustin Pop
               " the remote mirror (only for instances of type remote_raid1)"),
810 a8083063 Iustin Pop
  'info': (ShowInstanceConfig, ARGS_ANY, [DEBUG_OPT], "[<instance>...]",
811 a8083063 Iustin Pop
           "Show information on the specified instance"),
812 a8083063 Iustin Pop
  'list': (ListInstances, ARGS_NONE,
813 dcb93971 Michael Hanselmann
           [DEBUG_OPT, NOHDR_OPT, SEP_OPT, USEUNITS_OPT, FIELDS_OPT],
814 a8083063 Iustin Pop
           "", "Lists the instances and their status"),
815 d0834de3 Michael Hanselmann
  'reinstall': (ReinstallInstance, ARGS_ONE, [DEBUG_OPT, FORCE_OPT, os_opt],
816 fe7b0351 Michael Hanselmann
                "[-f] <instance>", "Reinstall the instance"),
817 1d67656e Iustin Pop
  'remove': (RemoveInstance, ARGS_ONE,
818 1d67656e Iustin Pop
             [DEBUG_OPT, FORCE_OPT,
819 1d67656e Iustin Pop
              make_option("--ignore-failures", dest="ignore_failures",
820 1d67656e Iustin Pop
                          action="store_true", default=False,
821 1d67656e Iustin Pop
                          help=("Remove the instance from the cluster even"
822 1d67656e Iustin Pop
                                " if there are failures during the removal"
823 1d67656e Iustin Pop
                                " process (shutdown, disk removal, etc.)")),
824 1d67656e Iustin Pop
              ],
825 a8083063 Iustin Pop
             "[-f] <instance>", "Shuts down the instance and removes it"),
826 a8083063 Iustin Pop
  'remove-mirror': (RemoveMDDRBDComponent, ARGS_ONE,
827 a8083063 Iustin Pop
                   [DEBUG_OPT, node_opt,
828 a8083063 Iustin Pop
                    make_option("-b", "--disk", dest="disk", metavar="sdX",
829 a8083063 Iustin Pop
                                help=("The name of the instance disk"
830 a8083063 Iustin Pop
                                      " for which to add the mirror")),
831 a8083063 Iustin Pop
                    make_option("-p", "--port", dest="port", metavar="PORT",
832 a8083063 Iustin Pop
                                help=("The port of the drbd device"
833 a8083063 Iustin Pop
                                      " which to remove from the mirror"),
834 a8083063 Iustin Pop
                                type="int"),
835 a8083063 Iustin Pop
                    ],
836 a8083063 Iustin Pop
                   "-b disk -p port <instance>",
837 a8083063 Iustin Pop
                   "Removes a mirror from the instance"),
838 decd5f45 Iustin Pop
  'rename': (RenameInstance, ARGS_FIXED(2),
839 decd5f45 Iustin Pop
             [DEBUG_OPT,
840 decd5f45 Iustin Pop
              make_option("--no-ip-check", dest="ignore_ip",
841 decd5f45 Iustin Pop
                          help="Do not check that the IP of the new name"
842 decd5f45 Iustin Pop
                          " is alive",
843 decd5f45 Iustin Pop
                          default=False, action="store_true"),
844 decd5f45 Iustin Pop
              ],
845 decd5f45 Iustin Pop
             "<instance> <new_name>", "Rename the instance"),
846 a8083063 Iustin Pop
  'replace-disks': (ReplaceDisks, ARGS_ONE,
847 a8083063 Iustin Pop
                    [DEBUG_OPT,
848 a8083063 Iustin Pop
                     make_option("-n", "--new-secondary", dest="new_secondary",
849 a9e0c397 Iustin Pop
                                 help=("New secondary node (for secondary"
850 a9e0c397 Iustin Pop
                                       " node change)"), metavar="NODE"),
851 a9e0c397 Iustin Pop
                     make_option("-p", "--on-primary", dest="on_primary",
852 a9e0c397 Iustin Pop
                                 default=False, action="store_true",
853 a9e0c397 Iustin Pop
                                 help=("Replace the disk(s) on the primary"
854 12c3449a Michael Hanselmann
                                       " node (only for the drbd template)")),
855 a9e0c397 Iustin Pop
                     make_option("-s", "--on-secondary", dest="on_secondary",
856 a9e0c397 Iustin Pop
                                 default=False, action="store_true",
857 a9e0c397 Iustin Pop
                                 help=("Replace the disk(s) on the secondary"
858 12c3449a Michael Hanselmann
                                       " node (only for the drbd template)")),
859 a9e0c397 Iustin Pop
                     make_option("--disks", dest="disks", default=None,
860 a9e0c397 Iustin Pop
                                 help=("Comma-separated list of disks"
861 a9e0c397 Iustin Pop
                                       " to replace (e.g. sda) (optional,"
862 a9e0c397 Iustin Pop
                                       " defaults to all disks")),
863 a9e0c397 Iustin Pop
                     ],
864 a8083063 Iustin Pop
                    "[-n NODE] <instance>",
865 a8083063 Iustin Pop
                    "Replaces all disks for the instance"),
866 a8083063 Iustin Pop
  'modify': (SetInstanceParms, ARGS_ONE,
867 fe7b0351 Michael Hanselmann
             [DEBUG_OPT, FORCE_OPT,
868 a8083063 Iustin Pop
              cli_option("-m", "--memory", dest="mem",
869 a8083063 Iustin Pop
                         help="Memory size",
870 a8083063 Iustin Pop
                         default=None, type="unit", metavar="<mem>"),
871 a8083063 Iustin Pop
              make_option("-p", "--cpu", dest="vcpus",
872 a8083063 Iustin Pop
                          help="Number of virtual CPUs",
873 a8083063 Iustin Pop
                          default=None, type="int", metavar="<PROC>"),
874 a8083063 Iustin Pop
              make_option("-i", "--ip", dest="ip",
875 a8083063 Iustin Pop
                          help="IP address ('none' or numeric IP)",
876 a8083063 Iustin Pop
                          default=None, type="string", metavar="<ADDRESS>"),
877 a8083063 Iustin Pop
              make_option("-b", "--bridge", dest="bridge",
878 a8083063 Iustin Pop
                          help="Bridge to connect this instance to",
879 decd5f45 Iustin Pop
                          default=None, type="string", metavar="<bridge>"),
880 1862d460 Alexander Schreiber
              make_option("--mac", dest="mac",
881 1862d460 Alexander Schreiber
                          help="MAC address", default=None,
882 1862d460 Alexander Schreiber
                          type="string", metavar="<MACADDRESS>"),
883 973d7867 Iustin Pop
              make_option("--kernel", dest="kernel_path",
884 973d7867 Iustin Pop
                          help="Path to the instances' kernel (or"
885 973d7867 Iustin Pop
                          " 'default')", default=None,
886 973d7867 Iustin Pop
                          type="string", metavar="<FILENAME>"),
887 973d7867 Iustin Pop
              make_option("--initrd", dest="initrd_path",
888 973d7867 Iustin Pop
                          help="Path to the instances' initrd (or 'none', or"
889 973d7867 Iustin Pop
                          " 'default')", default=None,
890 973d7867 Iustin Pop
                          type="string", metavar="<FILENAME>"),
891 25c5878d Alexander Schreiber
              make_option("--hvm-boot-order", dest="hvm_boot_order",
892 25c5878d Alexander Schreiber
                          help="boot device order for HVM"
893 25c5878d Alexander Schreiber
                          "(either one or more of [acdn] or 'default')",
894 25c5878d Alexander Schreiber
                          default=None, type="string", metavar="<BOOTORDER>"),
895 a8083063 Iustin Pop
              ],
896 a8083063 Iustin Pop
             "<instance>", "Alters the parameters of an instance"),
897 312ac745 Iustin Pop
  'shutdown': (ShutdownInstance, ARGS_ANY,
898 312ac745 Iustin Pop
               [DEBUG_OPT, m_node_opt, m_pri_node_opt, m_sec_node_opt,
899 804a1e8e Iustin Pop
                m_clust_opt, m_inst_opt, m_force_multi],
900 a8083063 Iustin Pop
               "<instance>", "Stops an instance"),
901 312ac745 Iustin Pop
  'startup': (StartupInstance, ARGS_ANY,
902 804a1e8e Iustin Pop
              [DEBUG_OPT, FORCE_OPT, m_force_multi,
903 a8083063 Iustin Pop
               make_option("-e", "--extra", dest="extra_args",
904 a8083063 Iustin Pop
                           help="Extra arguments for the instance's kernel",
905 a8083063 Iustin Pop
                           default=None, type="string", metavar="<PARAMS>"),
906 312ac745 Iustin Pop
               m_node_opt, m_pri_node_opt, m_sec_node_opt,
907 312ac745 Iustin Pop
               m_clust_opt, m_inst_opt,
908 a8083063 Iustin Pop
               ],
909 a8083063 Iustin Pop
            "<instance>", "Starts an instance"),
910 579d4337 Alexander Schreiber
911 579d4337 Alexander Schreiber
  'reboot': (RebootInstance, ARGS_ANY,
912 579d4337 Alexander Schreiber
              [DEBUG_OPT, m_force_multi,
913 579d4337 Alexander Schreiber
               make_option("-e", "--extra", dest="extra_args",
914 579d4337 Alexander Schreiber
                           help="Extra arguments for the instance's kernel",
915 579d4337 Alexander Schreiber
                           default=None, type="string", metavar="<PARAMS>"),
916 579d4337 Alexander Schreiber
               make_option("-t", "--type", dest="reboot_type",
917 579d4337 Alexander Schreiber
                           help="Type of reboot: soft/hard/full",
918 579d4337 Alexander Schreiber
                           default=constants.INSTANCE_REBOOT_SOFT,
919 579d4337 Alexander Schreiber
                           type="string", metavar="<REBOOT>"),
920 579d4337 Alexander Schreiber
               make_option("--ignore-secondaries", dest="ignore_secondaries",
921 579d4337 Alexander Schreiber
                           default=False, action="store_true",
922 579d4337 Alexander Schreiber
                           help="Ignore errors from secondaries"),
923 579d4337 Alexander Schreiber
               m_node_opt, m_pri_node_opt, m_sec_node_opt,
924 579d4337 Alexander Schreiber
               m_clust_opt, m_inst_opt,
925 579d4337 Alexander Schreiber
               ],
926 579d4337 Alexander Schreiber
            "<instance>", "Reboots an instance"),
927 a8083063 Iustin Pop
  'activate-disks': (ActivateDisks, ARGS_ONE, [DEBUG_OPT],
928 a8083063 Iustin Pop
                     "<instance>",
929 a8083063 Iustin Pop
                     "Activate an instance's disks"),
930 a8083063 Iustin Pop
  'deactivate-disks': (DeactivateDisks, ARGS_ONE, [DEBUG_OPT],
931 a8083063 Iustin Pop
                       "<instance>",
932 a8083063 Iustin Pop
                       "Deactivate an instance's disks"),
933 846baef9 Iustin Pop
  'list-tags': (ListTags, ARGS_ONE, [DEBUG_OPT],
934 846baef9 Iustin Pop
                "<node_name>", "List the tags of the given instance"),
935 810c50b7 Iustin Pop
  'add-tags': (AddTags, ARGS_ATLEAST(1), [DEBUG_OPT, TAG_SRC_OPT],
936 846baef9 Iustin Pop
               "<node_name> tag...", "Add tags to the given instance"),
937 810c50b7 Iustin Pop
  'remove-tags': (RemoveTags, ARGS_ATLEAST(1), [DEBUG_OPT, TAG_SRC_OPT],
938 846baef9 Iustin Pop
                  "<node_name> tag...", "Remove tags from given instance"),
939 a8083063 Iustin Pop
  }
940 a8083063 Iustin Pop
941 dbfd89dd Guido Trotter
aliases = {
942 dbfd89dd Guido Trotter
  'activate_block_devs': 'activate-disks',
943 dbfd89dd Guido Trotter
  }
944 dbfd89dd Guido Trotter
945 a8083063 Iustin Pop
if __name__ == '__main__':
946 dbfd89dd Guido Trotter
  sys.exit(GenericMain(commands, aliases=aliases,
947 846baef9 Iustin Pop
                       override={"tag_type": constants.TAG_INSTANCE}))