Statistics
| Branch: | Tag: | Revision:

root / scripts / gnt-instance @ c0e4a2c3

History | View | Annotate | Download (53.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 2f79bd34 Iustin Pop
# pylint: disable-msg=W0401,W0614
23 2f79bd34 Iustin Pop
# W0401: Wildcard import ganeti.cli
24 2f79bd34 Iustin Pop
# W0614: Unused import %s from wildcard import (since we need cli)
25 2f79bd34 Iustin Pop
26 a8083063 Iustin Pop
import sys
27 a8083063 Iustin Pop
import os
28 312ac745 Iustin Pop
import itertools
29 0d0e9090 René Nussbaumer
import simplejson
30 a8083063 Iustin Pop
from optparse import make_option
31 a8083063 Iustin Pop
from cStringIO import StringIO
32 a8083063 Iustin Pop
33 a8083063 Iustin Pop
from ganeti.cli import *
34 0d0e9090 René Nussbaumer
from ganeti import cli
35 a8083063 Iustin Pop
from ganeti import opcodes
36 a8083063 Iustin Pop
from ganeti import constants
37 a8083063 Iustin Pop
from ganeti import utils
38 312ac745 Iustin Pop
from ganeti import errors
39 312ac745 Iustin Pop
40 312ac745 Iustin Pop
41 312ac745 Iustin Pop
_SHUTDOWN_CLUSTER = "cluster"
42 312ac745 Iustin Pop
_SHUTDOWN_NODES_BOTH = "nodes"
43 312ac745 Iustin Pop
_SHUTDOWN_NODES_PRI = "nodes-pri"
44 312ac745 Iustin Pop
_SHUTDOWN_NODES_SEC = "nodes-sec"
45 312ac745 Iustin Pop
_SHUTDOWN_INSTANCES = "instances"
46 312ac745 Iustin Pop
47 7c0d6283 Michael Hanselmann
48 31a853d2 Iustin Pop
_VALUE_TRUE = "true"
49 31a853d2 Iustin Pop
50 7232c04c Iustin Pop
#: default list of options for L{ListInstances}
51 48c4dfa8 Iustin Pop
_LIST_DEF_FIELDS = [
52 e69d05fd Iustin Pop
  "name", "hypervisor", "os", "pnode", "status", "oper_ram",
53 48c4dfa8 Iustin Pop
  ]
54 48c4dfa8 Iustin Pop
55 bdb7d4e8 Michael Hanselmann
56 479636a3 Iustin Pop
def _ExpandMultiNames(mode, names, client=None):
57 312ac745 Iustin Pop
  """Expand the given names using the passed mode.
58 312ac745 Iustin Pop
59 312ac745 Iustin Pop
  For _SHUTDOWN_CLUSTER, all instances will be returned. For
60 312ac745 Iustin Pop
  _SHUTDOWN_NODES_PRI/SEC, all instances having those nodes as
61 7232c04c Iustin Pop
  primary/secondary will be returned. For _SHUTDOWN_NODES_BOTH, all
62 312ac745 Iustin Pop
  instances having those nodes as either primary or secondary will be
63 312ac745 Iustin Pop
  returned. For _SHUTDOWN_INSTANCES, the given instances will be
64 312ac745 Iustin Pop
  returned.
65 312ac745 Iustin Pop
66 7232c04c Iustin Pop
  @param mode: one of L{_SHUTDOWN_CLUSTER}, L{_SHUTDOWN_NODES_BOTH},
67 7232c04c Iustin Pop
      L{_SHUTDOWN_NODES_PRI}, L{_SHUTDOWN_NODES_SEC} or
68 7232c04c Iustin Pop
      L{_SHUTDOWN_INSTANCES}
69 7232c04c Iustin Pop
  @param names: a list of names; for cluster, it must be empty,
70 7232c04c Iustin Pop
      and for node and instance it must be a list of valid item
71 7232c04c Iustin Pop
      names (short names are valid as usual, e.g. node1 instead of
72 7232c04c Iustin Pop
      node1.example.com)
73 7232c04c Iustin Pop
  @rtype: list
74 7232c04c Iustin Pop
  @return: the list of names after the expansion
75 7232c04c Iustin Pop
  @raise errors.ProgrammerError: for unknown selection type
76 7232c04c Iustin Pop
  @raise errors.OpPrereqError: for invalid input parameters
77 7232c04c Iustin Pop
78 312ac745 Iustin Pop
  """
79 479636a3 Iustin Pop
  if client is None:
80 479636a3 Iustin Pop
    client = GetClient()
81 312ac745 Iustin Pop
  if mode == _SHUTDOWN_CLUSTER:
82 312ac745 Iustin Pop
    if names:
83 312ac745 Iustin Pop
      raise errors.OpPrereqError("Cluster filter mode takes no arguments")
84 ec79568d Iustin Pop
    idata = client.QueryInstances([], ["name"], False)
85 312ac745 Iustin Pop
    inames = [row[0] for row in idata]
86 312ac745 Iustin Pop
87 312ac745 Iustin Pop
  elif mode in (_SHUTDOWN_NODES_BOTH,
88 312ac745 Iustin Pop
                _SHUTDOWN_NODES_PRI,
89 312ac745 Iustin Pop
                _SHUTDOWN_NODES_SEC):
90 312ac745 Iustin Pop
    if not names:
91 312ac745 Iustin Pop
      raise errors.OpPrereqError("No node names passed")
92 ec79568d Iustin Pop
    ndata = client.QueryNodes(names, ["name", "pinst_list", "sinst_list"],
93 ec79568d Iustin Pop
                              True)
94 312ac745 Iustin Pop
    ipri = [row[1] for row in ndata]
95 312ac745 Iustin Pop
    pri_names = list(itertools.chain(*ipri))
96 312ac745 Iustin Pop
    isec = [row[2] for row in ndata]
97 312ac745 Iustin Pop
    sec_names = list(itertools.chain(*isec))
98 312ac745 Iustin Pop
    if mode == _SHUTDOWN_NODES_BOTH:
99 312ac745 Iustin Pop
      inames = pri_names + sec_names
100 312ac745 Iustin Pop
    elif mode == _SHUTDOWN_NODES_PRI:
101 312ac745 Iustin Pop
      inames = pri_names
102 312ac745 Iustin Pop
    elif mode == _SHUTDOWN_NODES_SEC:
103 312ac745 Iustin Pop
      inames = sec_names
104 312ac745 Iustin Pop
    else:
105 312ac745 Iustin Pop
      raise errors.ProgrammerError("Unhandled shutdown type")
106 312ac745 Iustin Pop
107 312ac745 Iustin Pop
  elif mode == _SHUTDOWN_INSTANCES:
108 312ac745 Iustin Pop
    if not names:
109 312ac745 Iustin Pop
      raise errors.OpPrereqError("No instance names passed")
110 ec79568d Iustin Pop
    idata = client.QueryInstances(names, ["name"], False)
111 312ac745 Iustin Pop
    inames = [row[0] for row in idata]
112 312ac745 Iustin Pop
113 312ac745 Iustin Pop
  else:
114 312ac745 Iustin Pop
    raise errors.OpPrereqError("Unknown mode '%s'" % mode)
115 312ac745 Iustin Pop
116 312ac745 Iustin Pop
  return inames
117 a8083063 Iustin Pop
118 a8083063 Iustin Pop
119 804a1e8e Iustin Pop
def _ConfirmOperation(inames, text):
120 804a1e8e Iustin Pop
  """Ask the user to confirm an operation on a list of instances.
121 804a1e8e Iustin Pop
122 804a1e8e Iustin Pop
  This function is used to request confirmation for doing an operation
123 804a1e8e Iustin Pop
  on a given list of instances.
124 804a1e8e Iustin Pop
125 7232c04c Iustin Pop
  @type inames: list
126 7232c04c Iustin Pop
  @param inames: the list of names that we display when
127 7232c04c Iustin Pop
      we ask for confirmation
128 7232c04c Iustin Pop
  @type text: str
129 7232c04c Iustin Pop
  @param text: the operation that the user should confirm
130 7232c04c Iustin Pop
      (e.g. I{shutdown} or I{startup})
131 7232c04c Iustin Pop
  @rtype: boolean
132 7232c04c Iustin Pop
  @return: True or False depending on user's confirmation.
133 804a1e8e Iustin Pop
134 804a1e8e Iustin Pop
  """
135 804a1e8e Iustin Pop
  count = len(inames)
136 804a1e8e Iustin Pop
  msg = ("The %s will operate on %d instances.\n"
137 804a1e8e Iustin Pop
         "Do you want to continue?" % (text, count))
138 804a1e8e Iustin Pop
  affected = ("\nAffected instances:\n" +
139 804a1e8e Iustin Pop
              "\n".join(["  %s" % name for name in inames]))
140 804a1e8e Iustin Pop
141 804a1e8e Iustin Pop
  choices = [('y', True, 'Yes, execute the %s' % text),
142 804a1e8e Iustin Pop
             ('n', False, 'No, abort the %s' % text)]
143 804a1e8e Iustin Pop
144 804a1e8e Iustin Pop
  if count > 20:
145 804a1e8e Iustin Pop
    choices.insert(1, ('v', 'v', 'View the list of affected instances'))
146 804a1e8e Iustin Pop
    ask = msg
147 804a1e8e Iustin Pop
  else:
148 804a1e8e Iustin Pop
    ask = msg + affected
149 804a1e8e Iustin Pop
150 804a1e8e Iustin Pop
  choice = AskUser(ask, choices)
151 804a1e8e Iustin Pop
  if choice == 'v':
152 804a1e8e Iustin Pop
    choices.pop(1)
153 5e66b7e6 Iustin Pop
    choice = AskUser(msg + affected, choices)
154 804a1e8e Iustin Pop
  return choice
155 804a1e8e Iustin Pop
156 804a1e8e Iustin Pop
157 973d7867 Iustin Pop
def _TransformPath(user_input):
158 973d7867 Iustin Pop
  """Transform a user path into a canonical value.
159 973d7867 Iustin Pop
160 973d7867 Iustin Pop
  This function transforms the a path passed as textual information
161 973d7867 Iustin Pop
  into the constants that the LU code expects.
162 973d7867 Iustin Pop
163 973d7867 Iustin Pop
  """
164 973d7867 Iustin Pop
  if user_input:
165 973d7867 Iustin Pop
    if user_input.lower() == "default":
166 973d7867 Iustin Pop
      result_path = constants.VALUE_DEFAULT
167 973d7867 Iustin Pop
    elif user_input.lower() == "none":
168 973d7867 Iustin Pop
      result_path = constants.VALUE_NONE
169 973d7867 Iustin Pop
    else:
170 973d7867 Iustin Pop
      if not os.path.isabs(user_input):
171 973d7867 Iustin Pop
        raise errors.OpPrereqError("Path '%s' is not an absolute filename" %
172 973d7867 Iustin Pop
                                   user_input)
173 973d7867 Iustin Pop
      result_path = user_input
174 973d7867 Iustin Pop
  else:
175 973d7867 Iustin Pop
    result_path = constants.VALUE_DEFAULT
176 973d7867 Iustin Pop
177 973d7867 Iustin Pop
  return result_path
178 973d7867 Iustin Pop
179 973d7867 Iustin Pop
180 a76f0c4a Iustin Pop
def _EnsureInstancesExist(client, names):
181 a76f0c4a Iustin Pop
  """Check for and ensure the given instance names exist.
182 a76f0c4a Iustin Pop
183 a76f0c4a Iustin Pop
  This function will raise an OpPrereqError in case they don't
184 a76f0c4a Iustin Pop
  exist. Otherwise it will exit cleanly.
185 a76f0c4a Iustin Pop
186 a76f0c4a Iustin Pop
  @type client: L{luxi.Client}
187 a76f0c4a Iustin Pop
  @param client: the client to use for the query
188 a76f0c4a Iustin Pop
  @type names: list
189 a76f0c4a Iustin Pop
  @param names: the list of instance names to query
190 a76f0c4a Iustin Pop
  @raise errors.OpPrereqError: in case any instance is missing
191 a76f0c4a Iustin Pop
192 a76f0c4a Iustin Pop
  """
193 a76f0c4a Iustin Pop
  # TODO: change LUQueryInstances to that it actually returns None
194 a76f0c4a Iustin Pop
  # instead of raising an exception, or devise a better mechanism
195 ec79568d Iustin Pop
  result = client.QueryInstances(names, ["name"], False)
196 a76f0c4a Iustin Pop
  for orig_name, row in zip(names, result):
197 a76f0c4a Iustin Pop
    if row[0] is None:
198 a76f0c4a Iustin Pop
      raise errors.OpPrereqError("Instance '%s' does not exist" % orig_name)
199 a76f0c4a Iustin Pop
200 a76f0c4a Iustin Pop
201 a8083063 Iustin Pop
def ListInstances(opts, args):
202 f5abe9bd Oleksiy Mishchenko
  """List instances and their properties.
203 a8083063 Iustin Pop
204 7232c04c Iustin Pop
  @param opts: the command line options selected by the user
205 7232c04c Iustin Pop
  @type args: list
206 7232c04c Iustin Pop
  @param args: should be an empty list
207 7232c04c Iustin Pop
  @rtype: int
208 7232c04c Iustin Pop
  @return: the desired exit code
209 7232c04c Iustin Pop
210 a8083063 Iustin Pop
  """
211 a8083063 Iustin Pop
  if opts.output is None:
212 48c4dfa8 Iustin Pop
    selected_fields = _LIST_DEF_FIELDS
213 48c4dfa8 Iustin Pop
  elif opts.output.startswith("+"):
214 48c4dfa8 Iustin Pop
    selected_fields = _LIST_DEF_FIELDS + opts.output[1:].split(",")
215 a8083063 Iustin Pop
  else:
216 a8083063 Iustin Pop
    selected_fields = opts.output.split(",")
217 a8083063 Iustin Pop
218 ec79568d Iustin Pop
  output = GetClient().QueryInstances(args, selected_fields, opts.do_locking)
219 a8083063 Iustin Pop
220 a8083063 Iustin Pop
  if not opts.no_headers:
221 d8052456 Iustin Pop
    headers = {
222 d8052456 Iustin Pop
      "name": "Instance", "os": "OS", "pnode": "Primary_node",
223 d8052456 Iustin Pop
      "snodes": "Secondary_Nodes", "admin_state": "Autostart",
224 338e51e8 Iustin Pop
      "oper_state": "Running",
225 d8052456 Iustin Pop
      "oper_ram": "Memory", "disk_template": "Disk_template",
226 3fb1e1c5 Alexander Schreiber
      "ip": "IP_address", "mac": "MAC_address",
227 338e51e8 Iustin Pop
      "bridge": "Bridge",
228 d8052456 Iustin Pop
      "sda_size": "Disk/0", "sdb_size": "Disk/1",
229 024e157f Iustin Pop
      "disk_usage": "DiskUsage",
230 130a6a6f Iustin Pop
      "status": "Status", "tags": "Tags",
231 3fb1e1c5 Alexander Schreiber
      "network_port": "Network_port",
232 5018a335 Iustin Pop
      "hv/kernel_path": "Kernel_path",
233 5018a335 Iustin Pop
      "hv/initrd_path": "Initrd_path",
234 5018a335 Iustin Pop
      "hv/boot_order": "HVM_boot_order",
235 5018a335 Iustin Pop
      "hv/acpi": "HVM_ACPI",
236 5018a335 Iustin Pop
      "hv/pae": "HVM_PAE",
237 5018a335 Iustin Pop
      "hv/cdrom_image_path": "HVM_CDROM_image_path",
238 5018a335 Iustin Pop
      "hv/nic_type": "HVM_NIC_type",
239 5018a335 Iustin Pop
      "hv/disk_type": "HVM_Disk_type",
240 7ac1fc45 Guido Trotter
      "hv/vnc_bind_address": "VNC_bind_address",
241 e69d05fd Iustin Pop
      "serial_no": "SerialNo", "hypervisor": "Hypervisor",
242 5018a335 Iustin Pop
      "hvparams": "Hypervisor_parameters",
243 338e51e8 Iustin Pop
      "be/memory": "Configured_memory",
244 338e51e8 Iustin Pop
      "be/vcpus": "VCPUs",
245 c0f2b229 Iustin Pop
      "be/auto_balance": "Auto_balance",
246 23b8c8d6 Iustin Pop
      "disk.count": "Disks", "disk.sizes": "Disk_sizes",
247 23b8c8d6 Iustin Pop
      "nic.count": "NICs", "nic.ips": "NIC_IPs",
248 23b8c8d6 Iustin Pop
      "nic.bridges": "NIC_bridges", "nic.macs": "NIC_MACs",
249 d8052456 Iustin Pop
      }
250 137161c9 Michael Hanselmann
  else:
251 137161c9 Michael Hanselmann
    headers = None
252 137161c9 Michael Hanselmann
253 9fbfbb7b Iustin Pop
  unitfields = ["be/memory", "oper_ram", "sd(a|b)_size", "disk\.size/.*"]
254 00430f8e Iustin Pop
  numfields = ["be/memory", "oper_ram", "sd(a|b)_size", "be/vcpus",
255 23b8c8d6 Iustin Pop
               "serial_no", "(disk|nic)\.count", "disk\.size/.*"]
256 137161c9 Michael Hanselmann
257 23b8c8d6 Iustin Pop
  list_type_fields = ("tags", "disk.sizes",
258 23b8c8d6 Iustin Pop
                      "nic.macs", "nic.ips", "nic.bridges")
259 8a23d2d3 Iustin Pop
  # change raw values to nicer strings
260 8a23d2d3 Iustin Pop
  for row in output:
261 8a23d2d3 Iustin Pop
    for idx, field in enumerate(selected_fields):
262 8a23d2d3 Iustin Pop
      val = row[idx]
263 8a23d2d3 Iustin Pop
      if field == "snodes":
264 8a23d2d3 Iustin Pop
        val = ",".join(val) or "-"
265 8a23d2d3 Iustin Pop
      elif field == "admin_state":
266 8a23d2d3 Iustin Pop
        if val:
267 8a23d2d3 Iustin Pop
          val = "yes"
268 8a23d2d3 Iustin Pop
        else:
269 8a23d2d3 Iustin Pop
          val = "no"
270 8a23d2d3 Iustin Pop
      elif field == "oper_state":
271 8a23d2d3 Iustin Pop
        if val is None:
272 8a23d2d3 Iustin Pop
          val = "(node down)"
273 8a23d2d3 Iustin Pop
        elif val: # True
274 8a23d2d3 Iustin Pop
          val = "running"
275 8a23d2d3 Iustin Pop
        else:
276 8a23d2d3 Iustin Pop
          val = "stopped"
277 8a23d2d3 Iustin Pop
      elif field == "oper_ram":
278 8a23d2d3 Iustin Pop
        if val is None:
279 8a23d2d3 Iustin Pop
          val = "(node down)"
280 8a23d2d3 Iustin Pop
      elif field == "sda_size" or field == "sdb_size":
281 8a23d2d3 Iustin Pop
        if val is None:
282 8a23d2d3 Iustin Pop
          val = "N/A"
283 130a6a6f Iustin Pop
      elif field in list_type_fields:
284 23b8c8d6 Iustin Pop
        val = ",".join(str(item) for item in val)
285 5018a335 Iustin Pop
      elif val is None:
286 5018a335 Iustin Pop
        val = "-"
287 8a23d2d3 Iustin Pop
      row[idx] = str(val)
288 8a23d2d3 Iustin Pop
289 16be8703 Iustin Pop
  data = GenerateTable(separator=opts.separator, headers=headers,
290 16be8703 Iustin Pop
                       fields=selected_fields, unitfields=unitfields,
291 9fbfbb7b Iustin Pop
                       numfields=numfields, data=output, units=opts.units)
292 16be8703 Iustin Pop
293 16be8703 Iustin Pop
  for line in data:
294 3a24c527 Iustin Pop
    ToStdout(line)
295 a8083063 Iustin Pop
296 a8083063 Iustin Pop
  return 0
297 a8083063 Iustin Pop
298 a8083063 Iustin Pop
299 a8083063 Iustin Pop
def AddInstance(opts, args):
300 a8083063 Iustin Pop
  """Add an instance to the cluster.
301 a8083063 Iustin Pop
302 7232c04c Iustin Pop
  @param opts: the command line options selected by the user
303 7232c04c Iustin Pop
  @type args: list
304 7232c04c Iustin Pop
  @param args: should contain only one element, the new instance name
305 7232c04c Iustin Pop
  @rtype: int
306 7232c04c Iustin Pop
  @return: the desired exit code
307 a8083063 Iustin Pop
308 a8083063 Iustin Pop
  """
309 a8083063 Iustin Pop
  instance = args[0]
310 a8083063 Iustin Pop
311 60d49723 Michael Hanselmann
  (pnode, snode) = SplitNodeOption(opts.node)
312 60d49723 Michael Hanselmann
313 6785674e Iustin Pop
  hypervisor = None
314 6785674e Iustin Pop
  hvparams = {}
315 6785674e Iustin Pop
  if opts.hypervisor:
316 6785674e Iustin Pop
    hypervisor, hvparams = opts.hypervisor
317 3b6d8c9b Iustin Pop
318 08db7c5c Iustin Pop
  if opts.nics:
319 08db7c5c Iustin Pop
    try:
320 08db7c5c Iustin Pop
      nic_max = max(int(nidx[0])+1 for nidx in opts.nics)
321 08db7c5c Iustin Pop
    except ValueError, err:
322 08db7c5c Iustin Pop
      raise errors.OpPrereqError("Invalid NIC index passed: %s" % str(err))
323 08db7c5c Iustin Pop
    nics = [{}] * nic_max
324 08db7c5c Iustin Pop
    for nidx, ndict in opts.nics.items():
325 08db7c5c Iustin Pop
      nidx = int(nidx)
326 08db7c5c Iustin Pop
      nics[nidx] = ndict
327 e0e31530 Iustin Pop
  elif opts.no_nics:
328 e0e31530 Iustin Pop
    # no nics
329 e0e31530 Iustin Pop
    nics = []
330 08db7c5c Iustin Pop
  else:
331 08db7c5c Iustin Pop
    # default of one nic, all auto
332 08db7c5c Iustin Pop
    nics = [{}]
333 08db7c5c Iustin Pop
334 112050d9 Iustin Pop
  if opts.disk_template == constants.DT_DISKLESS:
335 c0e4a2c3 Iustin Pop
    if opts.disks or opts.sd_size is not None:
336 112050d9 Iustin Pop
      raise errors.OpPrereqError("Diskless instance but disk"
337 112050d9 Iustin Pop
                                 " information passed")
338 112050d9 Iustin Pop
    disks = []
339 08db7c5c Iustin Pop
  else:
340 c0e4a2c3 Iustin Pop
    if not opts.disks and not opts.sd_size:
341 112050d9 Iustin Pop
      raise errors.OpPrereqError("No disk information specified")
342 c0e4a2c3 Iustin Pop
    if opts.disks and opts.sd_size is not None:
343 c0e4a2c3 Iustin Pop
      raise errors.OpPrereqError("Please use either the '--disk' or"
344 c0e4a2c3 Iustin Pop
                                 " '-s' option")
345 c0e4a2c3 Iustin Pop
    if opts.sd_size is not None:
346 c0e4a2c3 Iustin Pop
      opts.disks = [(0, {"size": opts.sd_size})]
347 08db7c5c Iustin Pop
    try:
348 08db7c5c Iustin Pop
      disk_max = max(int(didx[0])+1 for didx in opts.disks)
349 08db7c5c Iustin Pop
    except ValueError, err:
350 08db7c5c Iustin Pop
      raise errors.OpPrereqError("Invalid disk index passed: %s" % str(err))
351 08db7c5c Iustin Pop
    disks = [{}] * disk_max
352 08db7c5c Iustin Pop
    for didx, ddict in opts.disks:
353 08db7c5c Iustin Pop
      didx = int(didx)
354 08db7c5c Iustin Pop
      if "size" not in ddict:
355 08db7c5c Iustin Pop
        raise errors.OpPrereqError("Missing size for disk %d" % didx)
356 08db7c5c Iustin Pop
      try:
357 08db7c5c Iustin Pop
        ddict["size"] = utils.ParseUnit(ddict["size"])
358 08db7c5c Iustin Pop
      except ValueError, err:
359 08db7c5c Iustin Pop
        raise errors.OpPrereqError("Invalid disk size for disk %d: %s" %
360 08db7c5c Iustin Pop
                                   (didx, err))
361 08db7c5c Iustin Pop
      disks[didx] = ddict
362 08db7c5c Iustin Pop
363 a5728081 Guido Trotter
  utils.ForceDictType(opts.beparams, constants.BES_PARAMETER_TYPES)
364 6633774e Guido Trotter
  utils.ForceDictType(hvparams, constants.HVS_PARAMETER_TYPES)
365 31a853d2 Iustin Pop
366 338e51e8 Iustin Pop
  op = opcodes.OpCreateInstance(instance_name=instance,
367 08db7c5c Iustin Pop
                                disks=disks,
368 a8083063 Iustin Pop
                                disk_template=opts.disk_template,
369 08db7c5c Iustin Pop
                                nics=nics,
370 a8083063 Iustin Pop
                                mode=constants.INSTANCE_CREATE,
371 60d49723 Michael Hanselmann
                                os_type=opts.os, pnode=pnode,
372 338e51e8 Iustin Pop
                                snode=snode,
373 bdd55f71 Iustin Pop
                                start=opts.start, ip_check=opts.ip_check,
374 3b6d8c9b Iustin Pop
                                wait_for_sync=opts.wait_for_sync,
375 6785674e Iustin Pop
                                hypervisor=hypervisor,
376 6785674e Iustin Pop
                                hvparams=hvparams,
377 338e51e8 Iustin Pop
                                beparams=opts.beparams,
378 31a853d2 Iustin Pop
                                iallocator=opts.iallocator,
379 35a0d128 Iustin Pop
                                file_storage_dir=opts.file_storage_dir,
380 35a0d128 Iustin Pop
                                file_driver=opts.file_driver,
381 6785674e Iustin Pop
                                )
382 31a853d2 Iustin Pop
383 6340bb0a Iustin Pop
  SubmitOrSend(op, opts)
384 a8083063 Iustin Pop
  return 0
385 a8083063 Iustin Pop
386 a8083063 Iustin Pop
387 0d0e9090 René Nussbaumer
def BatchCreate(opts, args):
388 7232c04c Iustin Pop
  """Create instances using a definition file.
389 7232c04c Iustin Pop
390 7232c04c Iustin Pop
  This function reads a json file with instances defined
391 7232c04c Iustin Pop
  in the form::
392 7232c04c Iustin Pop
393 7232c04c Iustin Pop
    {"instance-name":{
394 9939547b Iustin Pop
      "disk_size": [20480],
395 7232c04c Iustin Pop
      "template": "drbd",
396 7232c04c Iustin Pop
      "backend": {
397 7232c04c Iustin Pop
        "memory": 512,
398 7232c04c Iustin Pop
        "vcpus": 1 },
399 9939547b Iustin Pop
      "os": "debootstrap",
400 7232c04c Iustin Pop
      "primary_node": "firstnode",
401 7232c04c Iustin Pop
      "secondary_node": "secondnode",
402 7232c04c Iustin Pop
      "iallocator": "dumb"}
403 7232c04c Iustin Pop
    }
404 7232c04c Iustin Pop
405 7232c04c Iustin Pop
  Note that I{primary_node} and I{secondary_node} have precedence over
406 7232c04c Iustin Pop
  I{iallocator}.
407 7232c04c Iustin Pop
408 7232c04c Iustin Pop
  @param opts: the command line options selected by the user
409 7232c04c Iustin Pop
  @type args: list
410 7232c04c Iustin Pop
  @param args: should contain one element, the json filename
411 7232c04c Iustin Pop
  @rtype: int
412 7232c04c Iustin Pop
  @return: the desired exit code
413 0d0e9090 René Nussbaumer
414 0d0e9090 René Nussbaumer
  """
415 9939547b Iustin Pop
  _DEFAULT_SPECS = {"disk_size": [20 * 1024],
416 0d0e9090 René Nussbaumer
                    "backend": {},
417 0d0e9090 René Nussbaumer
                    "iallocator": None,
418 0d0e9090 René Nussbaumer
                    "primary_node": None,
419 0d0e9090 René Nussbaumer
                    "secondary_node": None,
420 0d0e9090 René Nussbaumer
                    "ip": 'none',
421 0d0e9090 René Nussbaumer
                    "mac": 'auto',
422 0d0e9090 René Nussbaumer
                    "bridge": None,
423 0d0e9090 René Nussbaumer
                    "start": True,
424 0d0e9090 René Nussbaumer
                    "ip_check": True,
425 0d0e9090 René Nussbaumer
                    "hypervisor": None,
426 4082e6f9 Iustin Pop
                    "hvparams": {},
427 0d0e9090 René Nussbaumer
                    "file_storage_dir": None,
428 0d0e9090 René Nussbaumer
                    "file_driver": 'loop'}
429 0d0e9090 René Nussbaumer
430 0d0e9090 René Nussbaumer
  def _PopulateWithDefaults(spec):
431 0d0e9090 René Nussbaumer
    """Returns a new hash combined with default values."""
432 2f79bd34 Iustin Pop
    mydict = _DEFAULT_SPECS.copy()
433 2f79bd34 Iustin Pop
    mydict.update(spec)
434 2f79bd34 Iustin Pop
    return mydict
435 0d0e9090 René Nussbaumer
436 0d0e9090 René Nussbaumer
  def _Validate(spec):
437 0d0e9090 René Nussbaumer
    """Validate the instance specs."""
438 0d0e9090 René Nussbaumer
    # Validate fields required under any circumstances
439 0d0e9090 René Nussbaumer
    for required_field in ('os', 'template'):
440 0d0e9090 René Nussbaumer
      if required_field not in spec:
441 0d0e9090 René Nussbaumer
        raise errors.OpPrereqError('Required field "%s" is missing.' %
442 0d0e9090 René Nussbaumer
                                   required_field)
443 0d0e9090 René Nussbaumer
    # Validate special fields
444 0d0e9090 René Nussbaumer
    if spec['primary_node'] is not None:
445 0d0e9090 René Nussbaumer
      if (spec['template'] in constants.DTS_NET_MIRROR and
446 0d0e9090 René Nussbaumer
          spec['secondary_node'] is None):
447 0d0e9090 René Nussbaumer
        raise errors.OpPrereqError('Template requires secondary node, but'
448 0d0e9090 René Nussbaumer
                                   ' there was no secondary provided.')
449 0d0e9090 René Nussbaumer
    elif spec['iallocator'] is None:
450 0d0e9090 René Nussbaumer
      raise errors.OpPrereqError('You have to provide at least a primary_node'
451 0d0e9090 René Nussbaumer
                                 ' or an iallocator.')
452 0d0e9090 René Nussbaumer
453 4082e6f9 Iustin Pop
    if (spec['hvparams'] and
454 4082e6f9 Iustin Pop
        not isinstance(spec['hvparams'], dict)):
455 0d0e9090 René Nussbaumer
      raise errors.OpPrereqError('Hypervisor parameters must be a dict.')
456 0d0e9090 René Nussbaumer
457 0d0e9090 René Nussbaumer
  json_filename = args[0]
458 0d0e9090 René Nussbaumer
  try:
459 4082e6f9 Iustin Pop
    fd = open(json_filename, 'r')
460 0d0e9090 René Nussbaumer
    instance_data = simplejson.load(fd)
461 0d0e9090 René Nussbaumer
    fd.close()
462 4082e6f9 Iustin Pop
  except Exception, err:
463 4082e6f9 Iustin Pop
    ToStderr("Can't parse the instance definition file: %s" % str(err))
464 4082e6f9 Iustin Pop
    return 1
465 0d0e9090 René Nussbaumer
466 0d0e9090 René Nussbaumer
  # Iterate over the instances and do:
467 0d0e9090 René Nussbaumer
  #  * Populate the specs with default value
468 0d0e9090 René Nussbaumer
  #  * Validate the instance specs
469 7312b33d Iustin Pop
  i_names = utils.NiceSort(instance_data.keys())
470 7312b33d Iustin Pop
  for name in i_names:
471 7312b33d Iustin Pop
    specs = instance_data[name]
472 0d0e9090 René Nussbaumer
    specs = _PopulateWithDefaults(specs)
473 0d0e9090 René Nussbaumer
    _Validate(specs)
474 0d0e9090 René Nussbaumer
475 4082e6f9 Iustin Pop
    hypervisor = specs['hypervisor']
476 4082e6f9 Iustin Pop
    hvparams = specs['hvparams']
477 0d0e9090 René Nussbaumer
478 9939547b Iustin Pop
    disks = []
479 9939547b Iustin Pop
    for elem in specs['disk_size']:
480 9939547b Iustin Pop
      try:
481 9939547b Iustin Pop
        size = utils.ParseUnit(elem)
482 9939547b Iustin Pop
      except ValueError, err:
483 9939547b Iustin Pop
        raise errors.OpPrereqError("Invalid disk size '%s' for"
484 9939547b Iustin Pop
                                   " instance %s: %s" %
485 9939547b Iustin Pop
                                   (elem, name, err))
486 9939547b Iustin Pop
      disks.append({"size": size})
487 9939547b Iustin Pop
488 9939547b Iustin Pop
    nic0 = {'ip': specs['ip'], 'bridge': specs['bridge'], 'mac': specs['mac']}
489 9939547b Iustin Pop
490 a5728081 Guido Trotter
    utils.ForceDictType(specs['backend'], constants.BES_PARAMETER_TYPES)
491 a5728081 Guido Trotter
    utils.ForceDictType(hvparams, constants.HVS_PARAMETER_TYPES)
492 a5728081 Guido Trotter
493 0d0e9090 René Nussbaumer
    op = opcodes.OpCreateInstance(instance_name=name,
494 9939547b Iustin Pop
                                  disks=disks,
495 0d0e9090 René Nussbaumer
                                  disk_template=specs['template'],
496 0d0e9090 René Nussbaumer
                                  mode=constants.INSTANCE_CREATE,
497 0d0e9090 René Nussbaumer
                                  os_type=specs['os'],
498 0d0e9090 René Nussbaumer
                                  pnode=specs['primary_node'],
499 0d0e9090 René Nussbaumer
                                  snode=specs['secondary_node'],
500 9939547b Iustin Pop
                                  nics=[nic0],
501 0d0e9090 René Nussbaumer
                                  start=specs['start'],
502 0d0e9090 René Nussbaumer
                                  ip_check=specs['ip_check'],
503 0d0e9090 René Nussbaumer
                                  wait_for_sync=True,
504 0d0e9090 René Nussbaumer
                                  iallocator=specs['iallocator'],
505 0d0e9090 René Nussbaumer
                                  hypervisor=hypervisor,
506 0d0e9090 René Nussbaumer
                                  hvparams=hvparams,
507 0d0e9090 René Nussbaumer
                                  beparams=specs['backend'],
508 0d0e9090 René Nussbaumer
                                  file_storage_dir=specs['file_storage_dir'],
509 0d0e9090 René Nussbaumer
                                  file_driver=specs['file_driver'])
510 0d0e9090 René Nussbaumer
511 3a24c527 Iustin Pop
    ToStdout("%s: %s", name, cli.SendJob([op]))
512 0d0e9090 René Nussbaumer
513 0d0e9090 René Nussbaumer
  return 0
514 0d0e9090 René Nussbaumer
515 0d0e9090 René Nussbaumer
516 fe7b0351 Michael Hanselmann
def ReinstallInstance(opts, args):
517 fe7b0351 Michael Hanselmann
  """Reinstall an instance.
518 fe7b0351 Michael Hanselmann
519 7232c04c Iustin Pop
  @param opts: the command line options selected by the user
520 7232c04c Iustin Pop
  @type args: list
521 7232c04c Iustin Pop
  @param args: should contain only one element, the name of the
522 7232c04c Iustin Pop
      instance to be reinstalled
523 7232c04c Iustin Pop
  @rtype: int
524 7232c04c Iustin Pop
  @return: the desired exit code
525 fe7b0351 Michael Hanselmann
526 fe7b0351 Michael Hanselmann
  """
527 fe7b0351 Michael Hanselmann
  instance_name = args[0]
528 fe7b0351 Michael Hanselmann
529 20e23543 Alexander Schreiber
  if opts.select_os is True:
530 20e23543 Alexander Schreiber
    op = opcodes.OpDiagnoseOS(output_fields=["name", "valid"], names=[])
531 20e23543 Alexander Schreiber
    result = SubmitOpCode(op)
532 20e23543 Alexander Schreiber
533 20e23543 Alexander Schreiber
    if not result:
534 3a24c527 Iustin Pop
      ToStdout("Can't get the OS list")
535 20e23543 Alexander Schreiber
      return 1
536 20e23543 Alexander Schreiber
537 3a24c527 Iustin Pop
    ToStdout("Available OS templates:")
538 20e23543 Alexander Schreiber
    number = 0
539 20e23543 Alexander Schreiber
    choices = []
540 20e23543 Alexander Schreiber
    for entry in result:
541 3a24c527 Iustin Pop
      ToStdout("%3s: %s", number, entry[0])
542 20e23543 Alexander Schreiber
      choices.append(("%s" % number, entry[0], entry[0]))
543 20e23543 Alexander Schreiber
      number = number + 1
544 20e23543 Alexander Schreiber
545 20e23543 Alexander Schreiber
    choices.append(('x', 'exit', 'Exit gnt-instance reinstall'))
546 20e23543 Alexander Schreiber
    selected = AskUser("Enter OS template name or number (or x to abort):",
547 20e23543 Alexander Schreiber
                       choices)
548 20e23543 Alexander Schreiber
549 20e23543 Alexander Schreiber
    if selected == 'exit':
550 3a24c527 Iustin Pop
      ToStdout("User aborted reinstall, exiting")
551 20e23543 Alexander Schreiber
      return 1
552 20e23543 Alexander Schreiber
553 2f79bd34 Iustin Pop
    os_name = selected
554 20e23543 Alexander Schreiber
  else:
555 2f79bd34 Iustin Pop
    os_name = opts.os
556 20e23543 Alexander Schreiber
557 fe7b0351 Michael Hanselmann
  if not opts.force:
558 f4bc1f2c Michael Hanselmann
    usertext = ("This will reinstall the instance %s and remove"
559 f4bc1f2c Michael Hanselmann
                " all data. Continue?") % instance_name
560 47988778 Iustin Pop
    if not AskUser(usertext):
561 fe7b0351 Michael Hanselmann
      return 1
562 fe7b0351 Michael Hanselmann
563 d0834de3 Michael Hanselmann
  op = opcodes.OpReinstallInstance(instance_name=instance_name,
564 2f79bd34 Iustin Pop
                                   os_type=os_name)
565 6340bb0a Iustin Pop
  SubmitOrSend(op, opts)
566 fe7b0351 Michael Hanselmann
567 fe7b0351 Michael Hanselmann
  return 0
568 fe7b0351 Michael Hanselmann
569 fe7b0351 Michael Hanselmann
570 a8083063 Iustin Pop
def RemoveInstance(opts, args):
571 a8083063 Iustin Pop
  """Remove an instance.
572 a8083063 Iustin Pop
573 7232c04c Iustin Pop
  @param opts: the command line options selected by the user
574 7232c04c Iustin Pop
  @type args: list
575 7232c04c Iustin Pop
  @param args: should contain only one element, the name of
576 7232c04c Iustin Pop
      the instance to be removed
577 7232c04c Iustin Pop
  @rtype: int
578 7232c04c Iustin Pop
  @return: the desired exit code
579 a8083063 Iustin Pop
580 a8083063 Iustin Pop
  """
581 a8083063 Iustin Pop
  instance_name = args[0]
582 a8083063 Iustin Pop
  force = opts.force
583 a76f0c4a Iustin Pop
  cl = GetClient()
584 a8083063 Iustin Pop
585 a8083063 Iustin Pop
  if not force:
586 a76f0c4a Iustin Pop
    _EnsureInstancesExist(cl, [instance_name])
587 a76f0c4a Iustin Pop
588 a8083063 Iustin Pop
    usertext = ("This will remove the volumes of the instance %s"
589 a8083063 Iustin Pop
                " (including mirrors), thus removing all the data"
590 a8083063 Iustin Pop
                " of the instance. Continue?") % instance_name
591 47988778 Iustin Pop
    if not AskUser(usertext):
592 a8083063 Iustin Pop
      return 1
593 a8083063 Iustin Pop
594 1d67656e Iustin Pop
  op = opcodes.OpRemoveInstance(instance_name=instance_name,
595 1d67656e Iustin Pop
                                ignore_failures=opts.ignore_failures)
596 a76f0c4a Iustin Pop
  SubmitOrSend(op, opts, cl=cl)
597 a8083063 Iustin Pop
  return 0
598 a8083063 Iustin Pop
599 a8083063 Iustin Pop
600 decd5f45 Iustin Pop
def RenameInstance(opts, args):
601 4ab0b9e3 Guido Trotter
  """Rename an instance.
602 decd5f45 Iustin Pop
603 7232c04c Iustin Pop
  @param opts: the command line options selected by the user
604 7232c04c Iustin Pop
  @type args: list
605 7232c04c Iustin Pop
  @param args: should contain two elements, the old and the
606 7232c04c Iustin Pop
      new instance names
607 7232c04c Iustin Pop
  @rtype: int
608 7232c04c Iustin Pop
  @return: the desired exit code
609 decd5f45 Iustin Pop
610 decd5f45 Iustin Pop
  """
611 decd5f45 Iustin Pop
  op = opcodes.OpRenameInstance(instance_name=args[0],
612 decd5f45 Iustin Pop
                                new_name=args[1],
613 decd5f45 Iustin Pop
                                ignore_ip=opts.ignore_ip)
614 6340bb0a Iustin Pop
  SubmitOrSend(op, opts)
615 decd5f45 Iustin Pop
  return 0
616 decd5f45 Iustin Pop
617 decd5f45 Iustin Pop
618 a8083063 Iustin Pop
def ActivateDisks(opts, args):
619 a8083063 Iustin Pop
  """Activate an instance's disks.
620 a8083063 Iustin Pop
621 a8083063 Iustin Pop
  This serves two purposes:
622 7232c04c Iustin Pop
    - it allows (as long as the instance is not running)
623 7232c04c Iustin Pop
      mounting the disks and modifying them from the node
624 a8083063 Iustin Pop
    - it repairs inactive secondary drbds
625 a8083063 Iustin Pop
626 7232c04c Iustin Pop
  @param opts: the command line options selected by the user
627 7232c04c Iustin Pop
  @type args: list
628 7232c04c Iustin Pop
  @param args: should contain only one element, the instance name
629 7232c04c Iustin Pop
  @rtype: int
630 7232c04c Iustin Pop
  @return: the desired exit code
631 7232c04c Iustin Pop
632 a8083063 Iustin Pop
  """
633 a8083063 Iustin Pop
  instance_name = args[0]
634 a8083063 Iustin Pop
  op = opcodes.OpActivateInstanceDisks(instance_name=instance_name)
635 6340bb0a Iustin Pop
  disks_info = SubmitOrSend(op, opts)
636 a8083063 Iustin Pop
  for host, iname, nname in disks_info:
637 3a24c527 Iustin Pop
    ToStdout("%s:%s:%s", host, iname, nname)
638 a8083063 Iustin Pop
  return 0
639 a8083063 Iustin Pop
640 a8083063 Iustin Pop
641 a8083063 Iustin Pop
def DeactivateDisks(opts, args):
642 7232c04c Iustin Pop
  """Deactivate an instance's disks..
643 a8083063 Iustin Pop
644 a8083063 Iustin Pop
  This function takes the instance name, looks for its primary node
645 a8083063 Iustin Pop
  and the tries to shutdown its block devices on that node.
646 a8083063 Iustin Pop
647 7232c04c Iustin Pop
  @param opts: the command line options selected by the user
648 7232c04c Iustin Pop
  @type args: list
649 7232c04c Iustin Pop
  @param args: should contain only one element, the instance name
650 7232c04c Iustin Pop
  @rtype: int
651 7232c04c Iustin Pop
  @return: the desired exit code
652 7232c04c Iustin Pop
653 a8083063 Iustin Pop
  """
654 a8083063 Iustin Pop
  instance_name = args[0]
655 a8083063 Iustin Pop
  op = opcodes.OpDeactivateInstanceDisks(instance_name=instance_name)
656 6340bb0a Iustin Pop
  SubmitOrSend(op, opts)
657 a8083063 Iustin Pop
  return 0
658 a8083063 Iustin Pop
659 a8083063 Iustin Pop
660 c6e911bc Iustin Pop
def GrowDisk(opts, args):
661 7232c04c Iustin Pop
  """Grow an instance's disks.
662 c6e911bc Iustin Pop
663 7232c04c Iustin Pop
  @param opts: the command line options selected by the user
664 7232c04c Iustin Pop
  @type args: list
665 7232c04c Iustin Pop
  @param args: should contain two elements, the instance name
666 7232c04c Iustin Pop
      whose disks we grow and the disk name, e.g. I{sda}
667 7232c04c Iustin Pop
  @rtype: int
668 7232c04c Iustin Pop
  @return: the desired exit code
669 c6e911bc Iustin Pop
670 c6e911bc Iustin Pop
  """
671 c6e911bc Iustin Pop
  instance = args[0]
672 c6e911bc Iustin Pop
  disk = args[1]
673 ad24e046 Iustin Pop
  try:
674 ad24e046 Iustin Pop
    disk = int(disk)
675 ad24e046 Iustin Pop
  except ValueError, err:
676 ad24e046 Iustin Pop
    raise errors.OpPrereqError("Invalid disk index: %s" % str(err))
677 c6e911bc Iustin Pop
  amount = utils.ParseUnit(args[2])
678 6605411d Iustin Pop
  op = opcodes.OpGrowDisk(instance_name=instance, disk=disk, amount=amount,
679 6605411d Iustin Pop
                          wait_for_sync=opts.wait_for_sync)
680 6340bb0a Iustin Pop
  SubmitOrSend(op, opts)
681 c6e911bc Iustin Pop
  return 0
682 c6e911bc Iustin Pop
683 c6e911bc Iustin Pop
684 a8083063 Iustin Pop
def StartupInstance(opts, args):
685 7232c04c Iustin Pop
  """Startup instances.
686 a8083063 Iustin Pop
687 7232c04c Iustin Pop
  Depending on the options given, this will start one or more
688 7232c04c Iustin Pop
  instances.
689 7232c04c Iustin Pop
690 7232c04c Iustin Pop
  @param opts: the command line options selected by the user
691 7232c04c Iustin Pop
  @type args: list
692 7232c04c Iustin Pop
  @param args: the instance or node names based on which we
693 7232c04c Iustin Pop
      create the final selection (in conjunction with the
694 7232c04c Iustin Pop
      opts argument)
695 7232c04c Iustin Pop
  @rtype: int
696 7232c04c Iustin Pop
  @return: the desired exit code
697 a8083063 Iustin Pop
698 a8083063 Iustin Pop
  """
699 479636a3 Iustin Pop
  cl = GetClient()
700 312ac745 Iustin Pop
  if opts.multi_mode is None:
701 312ac745 Iustin Pop
    opts.multi_mode = _SHUTDOWN_INSTANCES
702 479636a3 Iustin Pop
  inames = _ExpandMultiNames(opts.multi_mode, args, client=cl)
703 bcee9cb4 Iustin Pop
  if not inames:
704 bcee9cb4 Iustin Pop
    raise errors.OpPrereqError("Selection filter does not match any instances")
705 804a1e8e Iustin Pop
  multi_on = opts.multi_mode != _SHUTDOWN_INSTANCES or len(inames) > 1
706 804a1e8e Iustin Pop
  if not (opts.force_multi or not multi_on
707 804a1e8e Iustin Pop
          or _ConfirmOperation(inames, "startup")):
708 804a1e8e Iustin Pop
    return 1
709 479636a3 Iustin Pop
  jex = cli.JobExecutor(verbose=multi_on, cl=cl)
710 312ac745 Iustin Pop
  for name in inames:
711 312ac745 Iustin Pop
    op = opcodes.OpStartupInstance(instance_name=name,
712 312ac745 Iustin Pop
                                   force=opts.force,
713 312ac745 Iustin Pop
                                   extra_args=opts.extra_args)
714 479636a3 Iustin Pop
    jex.QueueJob(name, op)
715 479636a3 Iustin Pop
  jex.WaitOrShow(not opts.submit_only)
716 a8083063 Iustin Pop
  return 0
717 a8083063 Iustin Pop
718 7c0d6283 Michael Hanselmann
719 579d4337 Alexander Schreiber
def RebootInstance(opts, args):
720 7232c04c Iustin Pop
  """Reboot instance(s).
721 7232c04c Iustin Pop
722 7232c04c Iustin Pop
  Depending on the parameters given, this will reboot one or more
723 7232c04c Iustin Pop
  instances.
724 579d4337 Alexander Schreiber
725 7232c04c Iustin Pop
  @param opts: the command line options selected by the user
726 7232c04c Iustin Pop
  @type args: list
727 7232c04c Iustin Pop
  @param args: the instance or node names based on which we
728 7232c04c Iustin Pop
      create the final selection (in conjunction with the
729 7232c04c Iustin Pop
      opts argument)
730 7232c04c Iustin Pop
  @rtype: int
731 7232c04c Iustin Pop
  @return: the desired exit code
732 579d4337 Alexander Schreiber
733 579d4337 Alexander Schreiber
  """
734 479636a3 Iustin Pop
  cl = GetClient()
735 579d4337 Alexander Schreiber
  if opts.multi_mode is None:
736 579d4337 Alexander Schreiber
    opts.multi_mode = _SHUTDOWN_INSTANCES
737 479636a3 Iustin Pop
  inames = _ExpandMultiNames(opts.multi_mode, args, client=cl)
738 bcee9cb4 Iustin Pop
  if not inames:
739 bcee9cb4 Iustin Pop
    raise errors.OpPrereqError("Selection filter does not match any instances")
740 579d4337 Alexander Schreiber
  multi_on = opts.multi_mode != _SHUTDOWN_INSTANCES or len(inames) > 1
741 579d4337 Alexander Schreiber
  if not (opts.force_multi or not multi_on
742 579d4337 Alexander Schreiber
          or _ConfirmOperation(inames, "reboot")):
743 579d4337 Alexander Schreiber
    return 1
744 479636a3 Iustin Pop
  jex = JobExecutor(verbose=multi_on, cl=cl)
745 579d4337 Alexander Schreiber
  for name in inames:
746 579d4337 Alexander Schreiber
    op = opcodes.OpRebootInstance(instance_name=name,
747 579d4337 Alexander Schreiber
                                  reboot_type=opts.reboot_type,
748 579d4337 Alexander Schreiber
                                  ignore_secondaries=opts.ignore_secondaries)
749 479636a3 Iustin Pop
    jex.QueueJob(name, op)
750 479636a3 Iustin Pop
  jex.WaitOrShow(not opts.submit_only)
751 579d4337 Alexander Schreiber
  return 0
752 a8083063 Iustin Pop
753 7c0d6283 Michael Hanselmann
754 a8083063 Iustin Pop
def ShutdownInstance(opts, args):
755 a8083063 Iustin Pop
  """Shutdown an instance.
756 a8083063 Iustin Pop
757 7232c04c Iustin Pop
  @param opts: the command line options selected by the user
758 7232c04c Iustin Pop
  @type args: list
759 7232c04c Iustin Pop
  @param args: the instance or node names based on which we
760 7232c04c Iustin Pop
      create the final selection (in conjunction with the
761 7232c04c Iustin Pop
      opts argument)
762 7232c04c Iustin Pop
  @rtype: int
763 7232c04c Iustin Pop
  @return: the desired exit code
764 a8083063 Iustin Pop
765 a8083063 Iustin Pop
  """
766 479636a3 Iustin Pop
  cl = GetClient()
767 312ac745 Iustin Pop
  if opts.multi_mode is None:
768 312ac745 Iustin Pop
    opts.multi_mode = _SHUTDOWN_INSTANCES
769 479636a3 Iustin Pop
  inames = _ExpandMultiNames(opts.multi_mode, args, client=cl)
770 bcee9cb4 Iustin Pop
  if not inames:
771 bcee9cb4 Iustin Pop
    raise errors.OpPrereqError("Selection filter does not match any instances")
772 804a1e8e Iustin Pop
  multi_on = opts.multi_mode != _SHUTDOWN_INSTANCES or len(inames) > 1
773 804a1e8e Iustin Pop
  if not (opts.force_multi or not multi_on
774 804a1e8e Iustin Pop
          or _ConfirmOperation(inames, "shutdown")):
775 804a1e8e Iustin Pop
    return 1
776 479636a3 Iustin Pop
777 479636a3 Iustin Pop
  jex = cli.JobExecutor(verbose=multi_on, cl=cl)
778 312ac745 Iustin Pop
  for name in inames:
779 312ac745 Iustin Pop
    op = opcodes.OpShutdownInstance(instance_name=name)
780 479636a3 Iustin Pop
    jex.QueueJob(name, op)
781 479636a3 Iustin Pop
  jex.WaitOrShow(not opts.submit_only)
782 a8083063 Iustin Pop
  return 0
783 a8083063 Iustin Pop
784 a8083063 Iustin Pop
785 a8083063 Iustin Pop
def ReplaceDisks(opts, args):
786 a8083063 Iustin Pop
  """Replace the disks of an instance
787 a8083063 Iustin Pop
788 7232c04c Iustin Pop
  @param opts: the command line options selected by the user
789 7232c04c Iustin Pop
  @type args: list
790 7232c04c Iustin Pop
  @param args: should contain only one element, the instance name
791 7232c04c Iustin Pop
  @rtype: int
792 7232c04c Iustin Pop
  @return: the desired exit code
793 a8083063 Iustin Pop
794 a8083063 Iustin Pop
  """
795 a8083063 Iustin Pop
  instance_name = args[0]
796 a9e0c397 Iustin Pop
  new_2ndary = opts.new_secondary
797 b6e82a65 Iustin Pop
  iallocator = opts.iallocator
798 a9e0c397 Iustin Pop
  if opts.disks is None:
799 54155f52 Iustin Pop
    disks = []
800 a9e0c397 Iustin Pop
  else:
801 54155f52 Iustin Pop
    try:
802 54155f52 Iustin Pop
      disks = [int(i) for i in opts.disks.split(",")]
803 54155f52 Iustin Pop
    except ValueError, err:
804 54155f52 Iustin Pop
      raise errors.OpPrereqError("Invalid disk index passed: %s" % str(err))
805 7e9366f7 Iustin Pop
  cnt = [opts.on_primary, opts.on_secondary,
806 7e9366f7 Iustin Pop
         new_2ndary is not None, iallocator is not None].count(True)
807 7e9366f7 Iustin Pop
  if cnt != 1:
808 7e9366f7 Iustin Pop
    raise errors.OpPrereqError("One and only one of the -p, -s, -n and -i"
809 7e9366f7 Iustin Pop
                               " options must be passed")
810 7e9366f7 Iustin Pop
  elif opts.on_primary:
811 a9e0c397 Iustin Pop
    mode = constants.REPLACE_DISK_PRI
812 7e9366f7 Iustin Pop
  elif opts.on_secondary:
813 a9e0c397 Iustin Pop
    mode = constants.REPLACE_DISK_SEC
814 7e9366f7 Iustin Pop
  elif new_2ndary is not None or iallocator is not None:
815 7e9366f7 Iustin Pop
    # replace secondary
816 7e9366f7 Iustin Pop
    mode = constants.REPLACE_DISK_CHG
817 a9e0c397 Iustin Pop
818 a9e0c397 Iustin Pop
  op = opcodes.OpReplaceDisks(instance_name=args[0], disks=disks,
819 b6e82a65 Iustin Pop
                              remote_node=new_2ndary, mode=mode,
820 b6e82a65 Iustin Pop
                              iallocator=iallocator)
821 6340bb0a Iustin Pop
  SubmitOrSend(op, opts)
822 a8083063 Iustin Pop
  return 0
823 a8083063 Iustin Pop
824 a8083063 Iustin Pop
825 a8083063 Iustin Pop
def FailoverInstance(opts, args):
826 a8083063 Iustin Pop
  """Failover an instance.
827 a8083063 Iustin Pop
828 a8083063 Iustin Pop
  The failover is done by shutting it down on its present node and
829 a8083063 Iustin Pop
  starting it on the secondary.
830 a8083063 Iustin Pop
831 7232c04c Iustin Pop
  @param opts: the command line options selected by the user
832 7232c04c Iustin Pop
  @type args: list
833 7232c04c Iustin Pop
  @param args: should contain only one element, the instance name
834 7232c04c Iustin Pop
  @rtype: int
835 7232c04c Iustin Pop
  @return: the desired exit code
836 a8083063 Iustin Pop
837 a8083063 Iustin Pop
  """
838 a76f0c4a Iustin Pop
  cl = GetClient()
839 80de0e3f Iustin Pop
  instance_name = args[0]
840 80de0e3f Iustin Pop
  force = opts.force
841 a8083063 Iustin Pop
842 80de0e3f Iustin Pop
  if not force:
843 a76f0c4a Iustin Pop
    _EnsureInstancesExist(cl, [instance_name])
844 a76f0c4a Iustin Pop
845 80de0e3f Iustin Pop
    usertext = ("Failover will happen to image %s."
846 80de0e3f Iustin Pop
                " This requires a shutdown of the instance. Continue?" %
847 80de0e3f Iustin Pop
                (instance_name,))
848 80de0e3f Iustin Pop
    if not AskUser(usertext):
849 80de0e3f Iustin Pop
      return 1
850 a8083063 Iustin Pop
851 80de0e3f Iustin Pop
  op = opcodes.OpFailoverInstance(instance_name=instance_name,
852 80de0e3f Iustin Pop
                                  ignore_consistency=opts.ignore_consistency)
853 a76f0c4a Iustin Pop
  SubmitOrSend(op, opts, cl=cl)
854 80de0e3f Iustin Pop
  return 0
855 a8083063 Iustin Pop
856 a8083063 Iustin Pop
857 53c776b5 Iustin Pop
def MigrateInstance(opts, args):
858 53c776b5 Iustin Pop
  """Migrate an instance.
859 53c776b5 Iustin Pop
860 53c776b5 Iustin Pop
  The migrate is done without shutdown.
861 53c776b5 Iustin Pop
862 2f907a8c Iustin Pop
  @param opts: the command line options selected by the user
863 2f907a8c Iustin Pop
  @type args: list
864 2f907a8c Iustin Pop
  @param args: should contain only one element, the instance name
865 2f907a8c Iustin Pop
  @rtype: int
866 2f907a8c Iustin Pop
  @return: the desired exit code
867 53c776b5 Iustin Pop
868 53c776b5 Iustin Pop
  """
869 a76f0c4a Iustin Pop
  cl = GetClient()
870 53c776b5 Iustin Pop
  instance_name = args[0]
871 53c776b5 Iustin Pop
  force = opts.force
872 53c776b5 Iustin Pop
873 53c776b5 Iustin Pop
  if not force:
874 a76f0c4a Iustin Pop
    _EnsureInstancesExist(cl, [instance_name])
875 a76f0c4a Iustin Pop
876 53c776b5 Iustin Pop
    if opts.cleanup:
877 53c776b5 Iustin Pop
      usertext = ("Instance %s will be recovered from a failed migration."
878 53c776b5 Iustin Pop
                  " Note that the migration procedure (including cleanup)" %
879 53c776b5 Iustin Pop
                  (instance_name,))
880 53c776b5 Iustin Pop
    else:
881 53c776b5 Iustin Pop
      usertext = ("Instance %s will be migrated. Note that migration" %
882 53c776b5 Iustin Pop
                  (instance_name,))
883 53c776b5 Iustin Pop
    usertext += (" is **experimental** in this version."
884 53c776b5 Iustin Pop
                " This might impact the instance if anything goes wrong."
885 53c776b5 Iustin Pop
                " Continue?")
886 53c776b5 Iustin Pop
    if not AskUser(usertext):
887 53c776b5 Iustin Pop
      return 1
888 53c776b5 Iustin Pop
889 53c776b5 Iustin Pop
  op = opcodes.OpMigrateInstance(instance_name=instance_name, live=opts.live,
890 53c776b5 Iustin Pop
                                 cleanup=opts.cleanup)
891 a76f0c4a Iustin Pop
  SubmitOpCode(op, cl=cl)
892 53c776b5 Iustin Pop
  return 0
893 53c776b5 Iustin Pop
894 53c776b5 Iustin Pop
895 a8083063 Iustin Pop
def ConnectToInstanceConsole(opts, args):
896 a8083063 Iustin Pop
  """Connect to the console of an instance.
897 a8083063 Iustin Pop
898 7232c04c Iustin Pop
  @param opts: the command line options selected by the user
899 7232c04c Iustin Pop
  @type args: list
900 7232c04c Iustin Pop
  @param args: should contain only one element, the instance name
901 7232c04c Iustin Pop
  @rtype: int
902 7232c04c Iustin Pop
  @return: the desired exit code
903 a8083063 Iustin Pop
904 a8083063 Iustin Pop
  """
905 a8083063 Iustin Pop
  instance_name = args[0]
906 a8083063 Iustin Pop
907 a8083063 Iustin Pop
  op = opcodes.OpConnectConsole(instance_name=instance_name)
908 0a80a26f Michael Hanselmann
  cmd = SubmitOpCode(op)
909 51c6e7b5 Michael Hanselmann
910 51c6e7b5 Michael Hanselmann
  if opts.show_command:
911 3a24c527 Iustin Pop
    ToStdout("%s", utils.ShellQuoteArgs(cmd))
912 51c6e7b5 Michael Hanselmann
  else:
913 51c6e7b5 Michael Hanselmann
    try:
914 51c6e7b5 Michael Hanselmann
      os.execvp(cmd[0], cmd)
915 51c6e7b5 Michael Hanselmann
    finally:
916 3a24c527 Iustin Pop
      ToStderr("Can't run console command %s with arguments:\n'%s'",
917 2f79bd34 Iustin Pop
               cmd[0], " ".join(cmd))
918 51c6e7b5 Michael Hanselmann
      os._exit(1)
919 a8083063 Iustin Pop
920 a8083063 Iustin Pop
921 19708787 Iustin Pop
def _FormatLogicalID(dev_type, logical_id):
922 19708787 Iustin Pop
  """Formats the logical_id of a disk.
923 19708787 Iustin Pop
924 19708787 Iustin Pop
  """
925 19708787 Iustin Pop
  if dev_type == constants.LD_DRBD8:
926 19708787 Iustin Pop
    node_a, node_b, port, minor_a, minor_b, key = logical_id
927 19708787 Iustin Pop
    data = [
928 19708787 Iustin Pop
      ("nodeA", "%s, minor=%s" % (node_a, minor_a)),
929 19708787 Iustin Pop
      ("nodeB", "%s, minor=%s" % (node_b, minor_b)),
930 19708787 Iustin Pop
      ("port", port),
931 19708787 Iustin Pop
      ("auth key", key),
932 19708787 Iustin Pop
      ]
933 19708787 Iustin Pop
  elif dev_type == constants.LD_LV:
934 19708787 Iustin Pop
    vg_name, lv_name = logical_id
935 19708787 Iustin Pop
    data = ["%s/%s" % (vg_name, lv_name)]
936 19708787 Iustin Pop
  else:
937 19708787 Iustin Pop
    data = [str(logical_id)]
938 19708787 Iustin Pop
939 19708787 Iustin Pop
  return data
940 19708787 Iustin Pop
941 19708787 Iustin Pop
942 19708787 Iustin Pop
def _FormatBlockDevInfo(idx, top_level, dev, static):
943 a8083063 Iustin Pop
  """Show block device information.
944 a8083063 Iustin Pop
945 7232c04c Iustin Pop
  This is only used by L{ShowInstanceConfig}, but it's too big to be
946 a8083063 Iustin Pop
  left for an inline definition.
947 a8083063 Iustin Pop
948 19708787 Iustin Pop
  @type idx: int
949 19708787 Iustin Pop
  @param idx: the index of the current disk
950 19708787 Iustin Pop
  @type top_level: boolean
951 19708787 Iustin Pop
  @param top_level: if this a top-level disk?
952 7232c04c Iustin Pop
  @type dev: dict
953 7232c04c Iustin Pop
  @param dev: dictionary with disk information
954 7232c04c Iustin Pop
  @type static: boolean
955 7232c04c Iustin Pop
  @param static: wheter the device information doesn't contain
956 7232c04c Iustin Pop
      runtime information but only static data
957 19708787 Iustin Pop
  @return: a list of either strings, tuples or lists
958 19708787 Iustin Pop
      (which should be formatted at a higher indent level)
959 7232c04c Iustin Pop
960 a8083063 Iustin Pop
  """
961 19708787 Iustin Pop
  def helper(dtype, status):
962 7232c04c Iustin Pop
    """Format one line for physical device status.
963 7232c04c Iustin Pop
964 7232c04c Iustin Pop
    @type dtype: str
965 7232c04c Iustin Pop
    @param dtype: a constant from the L{constants.LDS_BLOCK} set
966 7232c04c Iustin Pop
    @type status: tuple
967 7232c04c Iustin Pop
    @param status: a tuple as returned from L{backend.FindBlockDevice}
968 19708787 Iustin Pop
    @return: the string representing the status
969 7232c04c Iustin Pop
970 7232c04c Iustin Pop
    """
971 a8083063 Iustin Pop
    if not status:
972 19708787 Iustin Pop
      return "not active"
973 19708787 Iustin Pop
    txt = ""
974 19708787 Iustin Pop
    (path, major, minor, syncp, estt, degr, ldisk) = status
975 19708787 Iustin Pop
    if major is None:
976 19708787 Iustin Pop
      major_string = "N/A"
977 a8083063 Iustin Pop
    else:
978 19708787 Iustin Pop
      major_string = str(major)
979 fd38ef95 Manuel Franceschini
980 19708787 Iustin Pop
    if minor is None:
981 19708787 Iustin Pop
      minor_string = "N/A"
982 19708787 Iustin Pop
    else:
983 19708787 Iustin Pop
      minor_string = str(minor)
984 19708787 Iustin Pop
985 19708787 Iustin Pop
    txt += ("%s (%s:%s)" % (path, major_string, minor_string))
986 19708787 Iustin Pop
    if dtype in (constants.LD_DRBD8, ):
987 19708787 Iustin Pop
      if syncp is not None:
988 19708787 Iustin Pop
        sync_text = "*RECOVERING* %5.2f%%," % syncp
989 19708787 Iustin Pop
        if estt:
990 19708787 Iustin Pop
          sync_text += " ETA %ds" % estt
991 9db6dbce Iustin Pop
        else:
992 19708787 Iustin Pop
          sync_text += " ETA unknown"
993 19708787 Iustin Pop
      else:
994 19708787 Iustin Pop
        sync_text = "in sync"
995 19708787 Iustin Pop
      if degr:
996 19708787 Iustin Pop
        degr_text = "*DEGRADED*"
997 19708787 Iustin Pop
      else:
998 19708787 Iustin Pop
        degr_text = "ok"
999 19708787 Iustin Pop
      if ldisk:
1000 19708787 Iustin Pop
        ldisk_text = " *MISSING DISK*"
1001 19708787 Iustin Pop
      else:
1002 19708787 Iustin Pop
        ldisk_text = ""
1003 19708787 Iustin Pop
      txt += (" %s, status %s%s" % (sync_text, degr_text, ldisk_text))
1004 19708787 Iustin Pop
    elif dtype == constants.LD_LV:
1005 19708787 Iustin Pop
      if ldisk:
1006 19708787 Iustin Pop
        ldisk_text = " *FAILED* (failed drive?)"
1007 19708787 Iustin Pop
      else:
1008 19708787 Iustin Pop
        ldisk_text = ""
1009 19708787 Iustin Pop
      txt += ldisk_text
1010 19708787 Iustin Pop
    return txt
1011 19708787 Iustin Pop
1012 19708787 Iustin Pop
  # the header
1013 19708787 Iustin Pop
  if top_level:
1014 19708787 Iustin Pop
    if dev["iv_name"] is not None:
1015 19708787 Iustin Pop
      txt = dev["iv_name"]
1016 19708787 Iustin Pop
    else:
1017 19708787 Iustin Pop
      txt = "disk %d" % idx
1018 a8083063 Iustin Pop
  else:
1019 19708787 Iustin Pop
    txt = "child %d" % idx
1020 19708787 Iustin Pop
  d1 = ["- %s: %s" % (txt, dev["dev_type"])]
1021 19708787 Iustin Pop
  data = []
1022 19708787 Iustin Pop
  if top_level:
1023 19708787 Iustin Pop
    data.append(("access mode", dev["mode"]))
1024 a8083063 Iustin Pop
  if dev["logical_id"] is not None:
1025 19708787 Iustin Pop
    try:
1026 19708787 Iustin Pop
      l_id = _FormatLogicalID(dev["dev_type"], dev["logical_id"])
1027 19708787 Iustin Pop
    except ValueError:
1028 19708787 Iustin Pop
      l_id = [str(dev["logical_id"])]
1029 19708787 Iustin Pop
    if len(l_id) == 1:
1030 19708787 Iustin Pop
      data.append(("logical_id", l_id[0]))
1031 19708787 Iustin Pop
    else:
1032 19708787 Iustin Pop
      data.extend(l_id)
1033 a8083063 Iustin Pop
  elif dev["physical_id"] is not None:
1034 19708787 Iustin Pop
    data.append("physical_id:")
1035 19708787 Iustin Pop
    data.append([dev["physical_id"]])
1036 57821cac Iustin Pop
  if not static:
1037 19708787 Iustin Pop
    data.append(("on primary", helper(dev["dev_type"], dev["pstatus"])))
1038 57821cac Iustin Pop
  if dev["sstatus"] and not static:
1039 19708787 Iustin Pop
    data.append(("on secondary", helper(dev["dev_type"], dev["sstatus"])))
1040 a8083063 Iustin Pop
1041 a8083063 Iustin Pop
  if dev["children"]:
1042 19708787 Iustin Pop
    data.append("child devices:")
1043 19708787 Iustin Pop
    for c_idx, child in enumerate(dev["children"]):
1044 19708787 Iustin Pop
      data.append(_FormatBlockDevInfo(c_idx, False, child, static))
1045 19708787 Iustin Pop
  d1.append(data)
1046 19708787 Iustin Pop
  return d1
1047 a8083063 Iustin Pop
1048 a8083063 Iustin Pop
1049 19708787 Iustin Pop
def _FormatList(buf, data, indent_level):
1050 19708787 Iustin Pop
  """Formats a list of data at a given indent level.
1051 19708787 Iustin Pop
1052 19708787 Iustin Pop
  If the element of the list is:
1053 19708787 Iustin Pop
    - a string, it is simply formatted as is
1054 19708787 Iustin Pop
    - a tuple, it will be split into key, value and the all the
1055 19708787 Iustin Pop
      values in a list will be aligned all at the same start column
1056 19708787 Iustin Pop
    - a list, will be recursively formatted
1057 19708787 Iustin Pop
1058 19708787 Iustin Pop
  @type buf: StringIO
1059 19708787 Iustin Pop
  @param buf: the buffer into which we write the output
1060 19708787 Iustin Pop
  @param data: the list to format
1061 19708787 Iustin Pop
  @type indent_level: int
1062 19708787 Iustin Pop
  @param indent_level: the indent level to format at
1063 19708787 Iustin Pop
1064 19708787 Iustin Pop
  """
1065 19708787 Iustin Pop
  max_tlen = max([len(elem[0]) for elem in data
1066 19708787 Iustin Pop
                 if isinstance(elem, tuple)] or [0])
1067 19708787 Iustin Pop
  for elem in data:
1068 19708787 Iustin Pop
    if isinstance(elem, basestring):
1069 19708787 Iustin Pop
      buf.write("%*s%s\n" % (2*indent_level, "", elem))
1070 19708787 Iustin Pop
    elif isinstance(elem, tuple):
1071 19708787 Iustin Pop
      key, value = elem
1072 19708787 Iustin Pop
      spacer = "%*s" % (max_tlen - len(key), "")
1073 19708787 Iustin Pop
      buf.write("%*s%s:%s %s\n" % (2*indent_level, "", key, spacer, value))
1074 19708787 Iustin Pop
    elif isinstance(elem, list):
1075 19708787 Iustin Pop
      _FormatList(buf, elem, indent_level+1)
1076 19708787 Iustin Pop
1077 a8083063 Iustin Pop
def ShowInstanceConfig(opts, args):
1078 a8083063 Iustin Pop
  """Compute instance run-time status.
1079 a8083063 Iustin Pop
1080 7232c04c Iustin Pop
  @param opts: the command line options selected by the user
1081 7232c04c Iustin Pop
  @type args: list
1082 7232c04c Iustin Pop
  @param args: either an empty list, and then we query all
1083 7232c04c Iustin Pop
      instances, or should contain a list of instance names
1084 7232c04c Iustin Pop
  @rtype: int
1085 7232c04c Iustin Pop
  @return: the desired exit code
1086 7232c04c Iustin Pop
1087 a8083063 Iustin Pop
  """
1088 a8083063 Iustin Pop
  retcode = 0
1089 57821cac Iustin Pop
  op = opcodes.OpQueryInstanceData(instances=args, static=opts.static)
1090 a8083063 Iustin Pop
  result = SubmitOpCode(op)
1091 a8083063 Iustin Pop
  if not result:
1092 3a24c527 Iustin Pop
    ToStdout("No instances.")
1093 a8083063 Iustin Pop
    return 1
1094 a8083063 Iustin Pop
1095 a8083063 Iustin Pop
  buf = StringIO()
1096 a8083063 Iustin Pop
  retcode = 0
1097 a8083063 Iustin Pop
  for instance_name in result:
1098 a8083063 Iustin Pop
    instance = result[instance_name]
1099 a8083063 Iustin Pop
    buf.write("Instance name: %s\n" % instance["name"])
1100 57821cac Iustin Pop
    buf.write("State: configured to be %s" % instance["config_state"])
1101 57821cac Iustin Pop
    if not opts.static:
1102 57821cac Iustin Pop
      buf.write(", actual state is %s" % instance["run_state"])
1103 57821cac Iustin Pop
    buf.write("\n")
1104 57821cac Iustin Pop
    ##buf.write("Considered for memory checks in cluster verify: %s\n" %
1105 57821cac Iustin Pop
    ##          instance["auto_balance"])
1106 a8083063 Iustin Pop
    buf.write("  Nodes:\n")
1107 a8083063 Iustin Pop
    buf.write("    - primary: %s\n" % instance["pnode"])
1108 a8083063 Iustin Pop
    buf.write("    - secondaries: %s\n" % ", ".join(instance["snodes"]))
1109 a8083063 Iustin Pop
    buf.write("  Operating system: %s\n" % instance["os"])
1110 a8340917 Iustin Pop
    if instance.has_key("network_port"):
1111 a8340917 Iustin Pop
      buf.write("  Allocated network port: %s\n" % instance["network_port"])
1112 24838135 Iustin Pop
    buf.write("  Hypervisor: %s\n" % instance["hypervisor"])
1113 24838135 Iustin Pop
    if instance["hypervisor"] == constants.HT_XEN_PVM:
1114 24838135 Iustin Pop
      hvattrs = ((constants.HV_KERNEL_PATH, "kernel path"),
1115 24838135 Iustin Pop
                 (constants.HV_INITRD_PATH, "initrd path"))
1116 24838135 Iustin Pop
    elif instance["hypervisor"] == constants.HT_XEN_HVM:
1117 24838135 Iustin Pop
      hvattrs = ((constants.HV_BOOT_ORDER, "boot order"),
1118 24838135 Iustin Pop
                 (constants.HV_ACPI, "ACPI"),
1119 24838135 Iustin Pop
                 (constants.HV_PAE, "PAE"),
1120 24838135 Iustin Pop
                 (constants.HV_CDROM_IMAGE_PATH, "virtual CDROM"),
1121 24838135 Iustin Pop
                 (constants.HV_NIC_TYPE, "NIC type"),
1122 24838135 Iustin Pop
                 (constants.HV_DISK_TYPE, "Disk type"),
1123 24838135 Iustin Pop
                 (constants.HV_VNC_BIND_ADDRESS, "VNC bind address"),
1124 24838135 Iustin Pop
                 )
1125 24838135 Iustin Pop
      # custom console information for HVM
1126 24838135 Iustin Pop
      vnc_bind_address = instance["hv_actual"][constants.HV_VNC_BIND_ADDRESS]
1127 24838135 Iustin Pop
      if vnc_bind_address == constants.BIND_ADDRESS_GLOBAL:
1128 24838135 Iustin Pop
        vnc_console_port = "%s:%s" % (instance["pnode"],
1129 24838135 Iustin Pop
                                      instance["network_port"])
1130 24838135 Iustin Pop
      elif vnc_bind_address == constants.LOCALHOST_IP_ADDRESS:
1131 24838135 Iustin Pop
        vnc_console_port = "%s:%s on node %s" % (vnc_bind_address,
1132 24838135 Iustin Pop
                                                 instance["network_port"],
1133 24838135 Iustin Pop
                                                 instance["pnode"])
1134 a8340917 Iustin Pop
      else:
1135 24838135 Iustin Pop
        vnc_console_port = "%s:%s" % (vnc_bind_address,
1136 24838135 Iustin Pop
                                      instance["network_port"])
1137 24838135 Iustin Pop
      buf.write("    - console connection: vnc to %s\n" % vnc_console_port)
1138 24838135 Iustin Pop
1139 24838135 Iustin Pop
    else:
1140 24838135 Iustin Pop
      # auto-handle other hypervisor types
1141 24838135 Iustin Pop
      hvattrs = [(key, key) for key in instance["hv_actual"]]
1142 24838135 Iustin Pop
1143 24838135 Iustin Pop
    for key, desc in hvattrs:
1144 24838135 Iustin Pop
      if key in instance["hv_instance"]:
1145 24838135 Iustin Pop
        val = instance["hv_instance"][key]
1146 a8340917 Iustin Pop
      else:
1147 24838135 Iustin Pop
        val = "default (%s)" % instance["hv_actual"][key]
1148 24838135 Iustin Pop
      buf.write("    - %s: %s\n" % (desc, val))
1149 a8083063 Iustin Pop
    buf.write("  Hardware:\n")
1150 338e51e8 Iustin Pop
    buf.write("    - VCPUs: %d\n" %
1151 338e51e8 Iustin Pop
              instance["be_actual"][constants.BE_VCPUS])
1152 338e51e8 Iustin Pop
    buf.write("    - memory: %dMiB\n" %
1153 338e51e8 Iustin Pop
              instance["be_actual"][constants.BE_MEMORY])
1154 d2acfe27 Iustin Pop
    buf.write("    - NICs:\n")
1155 d2acfe27 Iustin Pop
    for idx, (mac, ip, bridge) in enumerate(instance["nics"]):
1156 d2acfe27 Iustin Pop
      buf.write("      - nic/%d: MAC: %s, IP: %s, bridge: %s\n" %
1157 d2acfe27 Iustin Pop
                (idx, mac, ip, bridge))
1158 19708787 Iustin Pop
    buf.write("  Disks:\n")
1159 a8083063 Iustin Pop
1160 19708787 Iustin Pop
    for idx, device in enumerate(instance["disks"]):
1161 19708787 Iustin Pop
      _FormatList(buf, _FormatBlockDevInfo(idx, True, device, opts.static), 2)
1162 a8083063 Iustin Pop
1163 3a24c527 Iustin Pop
  ToStdout(buf.getvalue().rstrip('\n'))
1164 a8083063 Iustin Pop
  return retcode
1165 a8083063 Iustin Pop
1166 a8083063 Iustin Pop
1167 7767bbf5 Manuel Franceschini
def SetInstanceParams(opts, args):
1168 a8083063 Iustin Pop
  """Modifies an instance.
1169 a8083063 Iustin Pop
1170 a8083063 Iustin Pop
  All parameters take effect only at the next restart of the instance.
1171 a8083063 Iustin Pop
1172 7232c04c Iustin Pop
  @param opts: the command line options selected by the user
1173 7232c04c Iustin Pop
  @type args: list
1174 7232c04c Iustin Pop
  @param args: should contain only one element, the instance name
1175 7232c04c Iustin Pop
  @rtype: int
1176 7232c04c Iustin Pop
  @return: the desired exit code
1177 a8083063 Iustin Pop
1178 a8083063 Iustin Pop
  """
1179 24991749 Iustin Pop
  if not (opts.nics or opts.disks or
1180 61be6ba4 Iustin Pop
          opts.hypervisor or opts.beparams):
1181 3a24c527 Iustin Pop
    ToStderr("Please give at least one of the parameters.")
1182 a8083063 Iustin Pop
    return 1
1183 a8083063 Iustin Pop
1184 467ae11e Guido Trotter
  for param in opts.beparams:
1185 e9d622bc Guido Trotter
    if isinstance(opts.beparams[param], basestring):
1186 e9d622bc Guido Trotter
      if opts.beparams[param].lower() == "default":
1187 e9d622bc Guido Trotter
        opts.beparams[param] = constants.VALUE_DEFAULT
1188 a5728081 Guido Trotter
1189 a5728081 Guido Trotter
  utils.ForceDictType(opts.beparams, constants.BES_PARAMETER_TYPES,
1190 a5728081 Guido Trotter
                      allowed_values=[constants.VALUE_DEFAULT])
1191 467ae11e Guido Trotter
1192 467ae11e Guido Trotter
  for param in opts.hypervisor:
1193 e9d622bc Guido Trotter
    if isinstance(opts.hypervisor[param], basestring):
1194 e9d622bc Guido Trotter
      if opts.hypervisor[param].lower() == "default":
1195 e9d622bc Guido Trotter
        opts.hypervisor[param] = constants.VALUE_DEFAULT
1196 a5728081 Guido Trotter
1197 a5728081 Guido Trotter
  utils.ForceDictType(opts.hypervisor, constants.HVS_PARAMETER_TYPES,
1198 a5728081 Guido Trotter
                      allowed_values=[constants.VALUE_DEFAULT])
1199 61be6ba4 Iustin Pop
1200 24991749 Iustin Pop
  for idx, (nic_op, nic_dict) in enumerate(opts.nics):
1201 24991749 Iustin Pop
    try:
1202 24991749 Iustin Pop
      nic_op = int(nic_op)
1203 24991749 Iustin Pop
      opts.nics[idx] = (nic_op, nic_dict)
1204 24991749 Iustin Pop
    except ValueError:
1205 24991749 Iustin Pop
      pass
1206 24991749 Iustin Pop
1207 24991749 Iustin Pop
  for idx, (disk_op, disk_dict) in enumerate(opts.disks):
1208 24991749 Iustin Pop
    try:
1209 24991749 Iustin Pop
      disk_op = int(disk_op)
1210 24991749 Iustin Pop
      opts.disks[idx] = (disk_op, disk_dict)
1211 24991749 Iustin Pop
    except ValueError:
1212 24991749 Iustin Pop
      pass
1213 24991749 Iustin Pop
    if disk_op == constants.DDM_ADD:
1214 24991749 Iustin Pop
      if 'size' not in disk_dict:
1215 24991749 Iustin Pop
        raise errors.OpPrereqError("Missing required parameter 'size'")
1216 24991749 Iustin Pop
      disk_dict['size'] = utils.ParseUnit(disk_dict['size'])
1217 24991749 Iustin Pop
1218 338e51e8 Iustin Pop
  op = opcodes.OpSetInstanceParams(instance_name=args[0],
1219 24991749 Iustin Pop
                                   nics=opts.nics,
1220 24991749 Iustin Pop
                                   disks=opts.disks,
1221 74409b12 Iustin Pop
                                   hvparams=opts.hypervisor,
1222 338e51e8 Iustin Pop
                                   beparams=opts.beparams,
1223 4300c4b6 Guido Trotter
                                   force=opts.force)
1224 31a853d2 Iustin Pop
1225 6340bb0a Iustin Pop
  # even if here we process the result, we allow submit only
1226 6340bb0a Iustin Pop
  result = SubmitOrSend(op, opts)
1227 a8083063 Iustin Pop
1228 a8083063 Iustin Pop
  if result:
1229 3a24c527 Iustin Pop
    ToStdout("Modified instance %s", args[0])
1230 a8083063 Iustin Pop
    for param, data in result:
1231 3a24c527 Iustin Pop
      ToStdout(" - %-5s -> %s", param, data)
1232 3a24c527 Iustin Pop
    ToStdout("Please don't forget that these parameters take effect"
1233 3a24c527 Iustin Pop
             " only at the next start of the instance.")
1234 a8083063 Iustin Pop
  return 0
1235 a8083063 Iustin Pop
1236 a8083063 Iustin Pop
1237 a8083063 Iustin Pop
# options used in more than one cmd
1238 a8083063 Iustin Pop
node_opt = make_option("-n", "--node", dest="node", help="Target node",
1239 a8083063 Iustin Pop
                       metavar="<node>")
1240 a8083063 Iustin Pop
1241 d0834de3 Michael Hanselmann
os_opt = cli_option("-o", "--os-type", dest="os", help="What OS to run",
1242 739ecd56 Michael Hanselmann
                    metavar="<os>")
1243 d0834de3 Michael Hanselmann
1244 312ac745 Iustin Pop
# multi-instance selection options
1245 804a1e8e Iustin Pop
m_force_multi = make_option("--force-multiple", dest="force_multi",
1246 804a1e8e Iustin Pop
                            help="Do not ask for confirmation when more than"
1247 804a1e8e Iustin Pop
                            " one instance is affected",
1248 804a1e8e Iustin Pop
                            action="store_true", default=False)
1249 804a1e8e Iustin Pop
1250 312ac745 Iustin Pop
m_pri_node_opt = make_option("--primary", dest="multi_mode",
1251 312ac745 Iustin Pop
                             help="Filter by nodes (primary only)",
1252 312ac745 Iustin Pop
                             const=_SHUTDOWN_NODES_PRI, action="store_const")
1253 312ac745 Iustin Pop
1254 312ac745 Iustin Pop
m_sec_node_opt = make_option("--secondary", dest="multi_mode",
1255 312ac745 Iustin Pop
                             help="Filter by nodes (secondary only)",
1256 312ac745 Iustin Pop
                             const=_SHUTDOWN_NODES_SEC, action="store_const")
1257 312ac745 Iustin Pop
1258 312ac745 Iustin Pop
m_node_opt = make_option("--node", dest="multi_mode",
1259 312ac745 Iustin Pop
                         help="Filter by nodes (primary and secondary)",
1260 312ac745 Iustin Pop
                         const=_SHUTDOWN_NODES_BOTH, action="store_const")
1261 312ac745 Iustin Pop
1262 312ac745 Iustin Pop
m_clust_opt = make_option("--all", dest="multi_mode",
1263 312ac745 Iustin Pop
                          help="Select all instances in the cluster",
1264 312ac745 Iustin Pop
                          const=_SHUTDOWN_CLUSTER, action="store_const")
1265 312ac745 Iustin Pop
1266 312ac745 Iustin Pop
m_inst_opt = make_option("--instance", dest="multi_mode",
1267 312ac745 Iustin Pop
                         help="Filter by instance name [default]",
1268 312ac745 Iustin Pop
                         const=_SHUTDOWN_INSTANCES, action="store_const")
1269 312ac745 Iustin Pop
1270 312ac745 Iustin Pop
1271 a8083063 Iustin Pop
# this is defined separately due to readability only
1272 a8083063 Iustin Pop
add_opts = [
1273 a8083063 Iustin Pop
  DEBUG_OPT,
1274 60d49723 Michael Hanselmann
  make_option("-n", "--node", dest="node",
1275 60d49723 Michael Hanselmann
              help="Target node and optional secondary node",
1276 60d49723 Michael Hanselmann
              metavar="<pnode>[:<snode>]"),
1277 d0834de3 Michael Hanselmann
  os_opt,
1278 338e51e8 Iustin Pop
  keyval_option("-B", "--backend", dest="beparams",
1279 338e51e8 Iustin Pop
                type="keyval", default={},
1280 338e51e8 Iustin Pop
                help="Backend parameters"),
1281 a8083063 Iustin Pop
  make_option("-t", "--disk-template", dest="disk_template",
1282 45873083 Manuel Franceschini
              help="Custom disk setup (diskless, file, plain or drbd)",
1283 f9193417 Iustin Pop
              default=None, metavar="TEMPL"),
1284 c0e4a2c3 Iustin Pop
  cli_option("-s", "--os-size", dest="sd_size", help="Disk size for a"
1285 c0e4a2c3 Iustin Pop
             " single-disk configuration, when not using the --disk option,"
1286 c0e4a2c3 Iustin Pop
             " in MiB unless a suffix is used",
1287 c0e4a2c3 Iustin Pop
             default=None, type="unit", metavar="<size>"),
1288 08db7c5c Iustin Pop
  ikv_option("--disk", help="Disk information",
1289 08db7c5c Iustin Pop
             default=[], dest="disks",
1290 08db7c5c Iustin Pop
             action="append",
1291 08db7c5c Iustin Pop
             type="identkeyval"),
1292 08db7c5c Iustin Pop
  ikv_option("--net", help="NIC information",
1293 08db7c5c Iustin Pop
             default=[], dest="nics",
1294 08db7c5c Iustin Pop
             action="append",
1295 08db7c5c Iustin Pop
             type="identkeyval"),
1296 e0e31530 Iustin Pop
  make_option("--no-nics", default=False, action="store_true",
1297 e0e31530 Iustin Pop
              help="Do not create any network cards for the instance"),
1298 a8083063 Iustin Pop
  make_option("--no-wait-for-sync", dest="wait_for_sync", default=True,
1299 a8083063 Iustin Pop
              action="store_false", help="Don't wait for sync (DANGEROUS!)"),
1300 bdd55f71 Iustin Pop
  make_option("--no-start", dest="start", default=True,
1301 bdd55f71 Iustin Pop
              action="store_false", help="Don't start the instance after"
1302 bdd55f71 Iustin Pop
              " creation"),
1303 bdd55f71 Iustin Pop
  make_option("--no-ip-check", dest="ip_check", default=True,
1304 bdd55f71 Iustin Pop
              action="store_false", help="Don't check that the instance's IP"
1305 bdd55f71 Iustin Pop
              " is alive (only valid with --no-start)"),
1306 45873083 Manuel Franceschini
  make_option("--file-storage-dir", dest="file_storage_dir",
1307 45873083 Manuel Franceschini
              help="Relative path under default cluster-wide file storage dir"
1308 45873083 Manuel Franceschini
              " to store file-based disks", default=None,
1309 45873083 Manuel Franceschini
              metavar="<DIR>"),
1310 45873083 Manuel Franceschini
  make_option("--file-driver", dest="file_driver", help="Driver to use"
1311 538475ca Iustin Pop
              " for image files", default="loop", metavar="<DRIVER>"),
1312 1325da74 Iustin Pop
  make_option("-I", "--iallocator", metavar="<NAME>",
1313 538475ca Iustin Pop
              help="Select nodes for the instance automatically using the"
1314 538475ca Iustin Pop
              " <NAME> iallocator plugin", default=None, type="string"),
1315 6785674e Iustin Pop
  ikv_option("-H", "--hypervisor", dest="hypervisor",
1316 6785674e Iustin Pop
              help="Hypervisor and hypervisor options, in the format"
1317 6785674e Iustin Pop
              " hypervisor:option=value,option=value,...", default=None,
1318 6785674e Iustin Pop
              type="identkeyval"),
1319 6340bb0a Iustin Pop
  SUBMIT_OPT,
1320 a8083063 Iustin Pop
  ]
1321 a8083063 Iustin Pop
1322 a8083063 Iustin Pop
commands = {
1323 a8083063 Iustin Pop
  'add': (AddInstance, ARGS_ONE, add_opts,
1324 bdb7d4e8 Michael Hanselmann
          "[...] -t disk-type -n node[:secondary-node] -o os-type <name>",
1325 a8083063 Iustin Pop
          "Creates and adds a new instance to the cluster"),
1326 0d0e9090 René Nussbaumer
  'batch-create': (BatchCreate, ARGS_ONE,
1327 0d0e9090 René Nussbaumer
                   [DEBUG_OPT],
1328 0d0e9090 René Nussbaumer
                   "<instances_file.json>",
1329 0d0e9090 René Nussbaumer
                   "Create a bunch of instances based on specs in the file."),
1330 51c6e7b5 Michael Hanselmann
  'console': (ConnectToInstanceConsole, ARGS_ONE,
1331 51c6e7b5 Michael Hanselmann
              [DEBUG_OPT,
1332 51c6e7b5 Michael Hanselmann
               make_option("--show-cmd", dest="show_command",
1333 51c6e7b5 Michael Hanselmann
                           action="store_true", default=False,
1334 51c6e7b5 Michael Hanselmann
                           help=("Show command instead of executing it"))],
1335 9a033156 Iustin Pop
              "[--show-cmd] <instance>",
1336 a8083063 Iustin Pop
              "Opens a console on the specified instance"),
1337 80de0e3f Iustin Pop
  'failover': (FailoverInstance, ARGS_ONE,
1338 fe7b0351 Michael Hanselmann
               [DEBUG_OPT, FORCE_OPT,
1339 a8083063 Iustin Pop
                make_option("--ignore-consistency", dest="ignore_consistency",
1340 a8083063 Iustin Pop
                            action="store_true", default=False,
1341 a8083063 Iustin Pop
                            help="Ignore the consistency of the disks on"
1342 a8083063 Iustin Pop
                            " the secondary"),
1343 6340bb0a Iustin Pop
                SUBMIT_OPT,
1344 a8083063 Iustin Pop
                ],
1345 9a033156 Iustin Pop
               "[-f] <instance>",
1346 a8083063 Iustin Pop
               "Stops the instance and starts it on the backup node, using"
1347 99e2be3b Guido Trotter
               " the remote mirror (only for instances of type drbd)"),
1348 53c776b5 Iustin Pop
  'migrate': (MigrateInstance, ARGS_ONE,
1349 53c776b5 Iustin Pop
               [DEBUG_OPT, FORCE_OPT,
1350 53c776b5 Iustin Pop
                make_option("--non-live", dest="live",
1351 53c776b5 Iustin Pop
                            default=True, action="store_false",
1352 53c776b5 Iustin Pop
                            help="Do a non-live migration (this usually means"
1353 53c776b5 Iustin Pop
                            " freeze the instance, save the state,"
1354 53c776b5 Iustin Pop
                            " transfer and only then resume running on the"
1355 53c776b5 Iustin Pop
                            " secondary node)"),
1356 53c776b5 Iustin Pop
                make_option("--cleanup", dest="cleanup",
1357 53c776b5 Iustin Pop
                            default=False, action="store_true",
1358 53c776b5 Iustin Pop
                            help="Instead of performing the migration, try to"
1359 53c776b5 Iustin Pop
                            " recover from a failed cleanup. This is safe"
1360 53c776b5 Iustin Pop
                            " to run even if the instance is healthy, but it"
1361 53c776b5 Iustin Pop
                            " will create extra replication traffic and "
1362 53c776b5 Iustin Pop
                            " disrupt briefly the replication (like during the"
1363 53c776b5 Iustin Pop
                            " migration"),
1364 53c776b5 Iustin Pop
                ],
1365 53c776b5 Iustin Pop
               "[-f] <instance>",
1366 53c776b5 Iustin Pop
               "Migrate instance to its secondary node"
1367 53c776b5 Iustin Pop
               " (only for instances of type drbd)"),
1368 57821cac Iustin Pop
  'info': (ShowInstanceConfig, ARGS_ANY,
1369 57821cac Iustin Pop
           [DEBUG_OPT,
1370 57821cac Iustin Pop
            make_option("-s", "--static", dest="static",
1371 57821cac Iustin Pop
                        action="store_true", default=False,
1372 57821cac Iustin Pop
                        help="Only show configuration data, not runtime data"),
1373 57821cac Iustin Pop
            ], "[-s] [<instance>...]",
1374 57821cac Iustin Pop
           "Show information on the specified instance(s)"),
1375 5ffaa51d Iustin Pop
  'list': (ListInstances, ARGS_ANY,
1376 ec79568d Iustin Pop
           [DEBUG_OPT, NOHDR_OPT, SEP_OPT, USEUNITS_OPT, FIELDS_OPT, SYNC_OPT],
1377 5ffaa51d Iustin Pop
           "[<instance>...]",
1378 d8052456 Iustin Pop
           "Lists the instances and their status. The available fields are"
1379 d8052456 Iustin Pop
           " (see the man page for details): status, oper_state, oper_ram,"
1380 d8a4b51d Iustin Pop
           " name, os, pnode, snodes, admin_state, admin_ram, disk_template,"
1381 e69d05fd Iustin Pop
           " ip, mac, bridge, sda_size, sdb_size, vcpus, serial_no,"
1382 e69d05fd Iustin Pop
           " hypervisor."
1383 38d7239a Iustin Pop
           " The default field"
1384 48c4dfa8 Iustin Pop
           " list is (in order): %s." % ", ".join(_LIST_DEF_FIELDS),
1385 48c4dfa8 Iustin Pop
           ),
1386 20e23543 Alexander Schreiber
  'reinstall': (ReinstallInstance, ARGS_ONE,
1387 20e23543 Alexander Schreiber
                [DEBUG_OPT, FORCE_OPT, os_opt,
1388 20e23543 Alexander Schreiber
                 make_option("--select-os", dest="select_os",
1389 20e23543 Alexander Schreiber
                             action="store_true", default=False,
1390 20e23543 Alexander Schreiber
                             help="Interactive OS reinstall, lists available"
1391 6340bb0a Iustin Pop
                             " OS templates for selection"),
1392 6340bb0a Iustin Pop
                 SUBMIT_OPT,
1393 6340bb0a Iustin Pop
                 ],
1394 9a033156 Iustin Pop
                "[-f] <instance>", "Reinstall a stopped instance"),
1395 1d67656e Iustin Pop
  'remove': (RemoveInstance, ARGS_ONE,
1396 1d67656e Iustin Pop
             [DEBUG_OPT, FORCE_OPT,
1397 1d67656e Iustin Pop
              make_option("--ignore-failures", dest="ignore_failures",
1398 1d67656e Iustin Pop
                          action="store_true", default=False,
1399 1d67656e Iustin Pop
                          help=("Remove the instance from the cluster even"
1400 1d67656e Iustin Pop
                                " if there are failures during the removal"
1401 1d67656e Iustin Pop
                                " process (shutdown, disk removal, etc.)")),
1402 6340bb0a Iustin Pop
              SUBMIT_OPT,
1403 1d67656e Iustin Pop
              ],
1404 9a033156 Iustin Pop
             "[-f] <instance>", "Shuts down the instance and removes it"),
1405 decd5f45 Iustin Pop
  'rename': (RenameInstance, ARGS_FIXED(2),
1406 decd5f45 Iustin Pop
             [DEBUG_OPT,
1407 decd5f45 Iustin Pop
              make_option("--no-ip-check", dest="ignore_ip",
1408 decd5f45 Iustin Pop
                          help="Do not check that the IP of the new name"
1409 decd5f45 Iustin Pop
                          " is alive",
1410 decd5f45 Iustin Pop
                          default=False, action="store_true"),
1411 6340bb0a Iustin Pop
              SUBMIT_OPT,
1412 decd5f45 Iustin Pop
              ],
1413 9a033156 Iustin Pop
             "<instance> <new_name>", "Rename the instance"),
1414 a8083063 Iustin Pop
  'replace-disks': (ReplaceDisks, ARGS_ONE,
1415 a8083063 Iustin Pop
                    [DEBUG_OPT,
1416 a8083063 Iustin Pop
                     make_option("-n", "--new-secondary", dest="new_secondary",
1417 a9e0c397 Iustin Pop
                                 help=("New secondary node (for secondary"
1418 7e9366f7 Iustin Pop
                                       " node change)"), metavar="NODE",
1419 7e9366f7 Iustin Pop
                                 default=None),
1420 a9e0c397 Iustin Pop
                     make_option("-p", "--on-primary", dest="on_primary",
1421 a9e0c397 Iustin Pop
                                 default=False, action="store_true",
1422 a9e0c397 Iustin Pop
                                 help=("Replace the disk(s) on the primary"
1423 12c3449a Michael Hanselmann
                                       " node (only for the drbd template)")),
1424 a9e0c397 Iustin Pop
                     make_option("-s", "--on-secondary", dest="on_secondary",
1425 a9e0c397 Iustin Pop
                                 default=False, action="store_true",
1426 a9e0c397 Iustin Pop
                                 help=("Replace the disk(s) on the secondary"
1427 12c3449a Michael Hanselmann
                                       " node (only for the drbd template)")),
1428 a9e0c397 Iustin Pop
                     make_option("--disks", dest="disks", default=None,
1429 a9e0c397 Iustin Pop
                                 help=("Comma-separated list of disks"
1430 a9e0c397 Iustin Pop
                                       " to replace (e.g. sda) (optional,"
1431 a9e0c397 Iustin Pop
                                       " defaults to all disks")),
1432 633b36db Iustin Pop
                     make_option("-I", "--iallocator", metavar="<NAME>",
1433 b6e82a65 Iustin Pop
                                 help="Select new secondary for the instance"
1434 b6e82a65 Iustin Pop
                                 " automatically using the"
1435 b6e82a65 Iustin Pop
                                 " <NAME> iallocator plugin (enables"
1436 b6e82a65 Iustin Pop
                                 " secondary node replacement)",
1437 b6e82a65 Iustin Pop
                                 default=None, type="string"),
1438 6340bb0a Iustin Pop
                     SUBMIT_OPT,
1439 a9e0c397 Iustin Pop
                     ],
1440 633b36db Iustin Pop
                    "[-s|-p|-n NODE|-I NAME] <instance>",
1441 a8083063 Iustin Pop
                    "Replaces all disks for the instance"),
1442 7767bbf5 Manuel Franceschini
  'modify': (SetInstanceParams, ARGS_ONE,
1443 fe7b0351 Michael Hanselmann
             [DEBUG_OPT, FORCE_OPT,
1444 74409b12 Iustin Pop
              keyval_option("-H", "--hypervisor", type="keyval",
1445 74409b12 Iustin Pop
                            default={}, dest="hypervisor",
1446 74409b12 Iustin Pop
                            help="Change hypervisor parameters"),
1447 61be6ba4 Iustin Pop
              keyval_option("-B", "--backend", type="keyval",
1448 61be6ba4 Iustin Pop
                            default={}, dest="beparams",
1449 61be6ba4 Iustin Pop
                            help="Change backend parameters"),
1450 24991749 Iustin Pop
              ikv_option("--disk", help="Disk changes",
1451 24991749 Iustin Pop
                         default=[], dest="disks",
1452 24991749 Iustin Pop
                         action="append",
1453 24991749 Iustin Pop
                         type="identkeyval"),
1454 24991749 Iustin Pop
              ikv_option("--net", help="NIC changes",
1455 24991749 Iustin Pop
                         default=[], dest="nics",
1456 24991749 Iustin Pop
                         action="append",
1457 24991749 Iustin Pop
                         type="identkeyval"),
1458 6340bb0a Iustin Pop
              SUBMIT_OPT,
1459 a8083063 Iustin Pop
              ],
1460 9a033156 Iustin Pop
             "<instance>", "Alters the parameters of an instance"),
1461 312ac745 Iustin Pop
  'shutdown': (ShutdownInstance, ARGS_ANY,
1462 312ac745 Iustin Pop
               [DEBUG_OPT, m_node_opt, m_pri_node_opt, m_sec_node_opt,
1463 6340bb0a Iustin Pop
                m_clust_opt, m_inst_opt, m_force_multi,
1464 6340bb0a Iustin Pop
                SUBMIT_OPT,
1465 6340bb0a Iustin Pop
                ],
1466 9a033156 Iustin Pop
               "<instance>", "Stops an instance"),
1467 312ac745 Iustin Pop
  'startup': (StartupInstance, ARGS_ANY,
1468 804a1e8e Iustin Pop
              [DEBUG_OPT, FORCE_OPT, m_force_multi,
1469 a8083063 Iustin Pop
               make_option("-e", "--extra", dest="extra_args",
1470 a8083063 Iustin Pop
                           help="Extra arguments for the instance's kernel",
1471 a8083063 Iustin Pop
                           default=None, type="string", metavar="<PARAMS>"),
1472 312ac745 Iustin Pop
               m_node_opt, m_pri_node_opt, m_sec_node_opt,
1473 312ac745 Iustin Pop
               m_clust_opt, m_inst_opt,
1474 6340bb0a Iustin Pop
               SUBMIT_OPT,
1475 a8083063 Iustin Pop
               ],
1476 9a033156 Iustin Pop
            "<instance>", "Starts an instance"),
1477 579d4337 Alexander Schreiber
1478 579d4337 Alexander Schreiber
  'reboot': (RebootInstance, ARGS_ANY,
1479 579d4337 Alexander Schreiber
              [DEBUG_OPT, m_force_multi,
1480 579d4337 Alexander Schreiber
               make_option("-e", "--extra", dest="extra_args",
1481 579d4337 Alexander Schreiber
                           help="Extra arguments for the instance's kernel",
1482 579d4337 Alexander Schreiber
                           default=None, type="string", metavar="<PARAMS>"),
1483 579d4337 Alexander Schreiber
               make_option("-t", "--type", dest="reboot_type",
1484 579d4337 Alexander Schreiber
                           help="Type of reboot: soft/hard/full",
1485 bf2fd71e Alexander Schreiber
                           default=constants.INSTANCE_REBOOT_HARD,
1486 579d4337 Alexander Schreiber
                           type="string", metavar="<REBOOT>"),
1487 579d4337 Alexander Schreiber
               make_option("--ignore-secondaries", dest="ignore_secondaries",
1488 579d4337 Alexander Schreiber
                           default=False, action="store_true",
1489 579d4337 Alexander Schreiber
                           help="Ignore errors from secondaries"),
1490 579d4337 Alexander Schreiber
               m_node_opt, m_pri_node_opt, m_sec_node_opt,
1491 579d4337 Alexander Schreiber
               m_clust_opt, m_inst_opt,
1492 6340bb0a Iustin Pop
               SUBMIT_OPT,
1493 579d4337 Alexander Schreiber
               ],
1494 9a033156 Iustin Pop
            "<instance>", "Reboots an instance"),
1495 6340bb0a Iustin Pop
  'activate-disks': (ActivateDisks, ARGS_ONE, [DEBUG_OPT, SUBMIT_OPT],
1496 9a033156 Iustin Pop
                     "<instance>",
1497 a8083063 Iustin Pop
                     "Activate an instance's disks"),
1498 6340bb0a Iustin Pop
  'deactivate-disks': (DeactivateDisks, ARGS_ONE, [DEBUG_OPT, SUBMIT_OPT],
1499 9a033156 Iustin Pop
                       "<instance>",
1500 a8083063 Iustin Pop
                       "Deactivate an instance's disks"),
1501 6605411d Iustin Pop
  'grow-disk': (GrowDisk, ARGS_FIXED(3),
1502 6605411d Iustin Pop
                [DEBUG_OPT, SUBMIT_OPT,
1503 6605411d Iustin Pop
                 make_option("--no-wait-for-sync",
1504 6605411d Iustin Pop
                             dest="wait_for_sync", default=True,
1505 6605411d Iustin Pop
                             action="store_false",
1506 6605411d Iustin Pop
                             help="Don't wait for sync (DANGEROUS!)"),
1507 6605411d Iustin Pop
                 ],
1508 c6e911bc Iustin Pop
                "<instance> <disk> <size>", "Grow an instance's disk"),
1509 846baef9 Iustin Pop
  'list-tags': (ListTags, ARGS_ONE, [DEBUG_OPT],
1510 746ea1da Guido Trotter
                "<instance_name>", "List the tags of the given instance"),
1511 810c50b7 Iustin Pop
  'add-tags': (AddTags, ARGS_ATLEAST(1), [DEBUG_OPT, TAG_SRC_OPT],
1512 746ea1da Guido Trotter
               "<instance_name> tag...", "Add tags to the given instance"),
1513 810c50b7 Iustin Pop
  'remove-tags': (RemoveTags, ARGS_ATLEAST(1), [DEBUG_OPT, TAG_SRC_OPT],
1514 746ea1da Guido Trotter
                  "<instance_name> tag...", "Remove tags from given instance"),
1515 a8083063 Iustin Pop
  }
1516 a8083063 Iustin Pop
1517 7232c04c Iustin Pop
#: dictionary with aliases for commands
1518 dbfd89dd Guido Trotter
aliases = {
1519 dbfd89dd Guido Trotter
  'activate_block_devs': 'activate-disks',
1520 00ce8b29 Guido Trotter
  'replace_disks': 'replace-disks',
1521 536fda25 Guido Trotter
  'start': 'startup',
1522 536fda25 Guido Trotter
  'stop': 'shutdown',
1523 dbfd89dd Guido Trotter
  }
1524 dbfd89dd Guido Trotter
1525 a8083063 Iustin Pop
if __name__ == '__main__':
1526 dbfd89dd Guido Trotter
  sys.exit(GenericMain(commands, aliases=aliases,
1527 846baef9 Iustin Pop
                       override={"tag_type": constants.TAG_INSTANCE}))