Statistics
| Branch: | Tag: | Revision:

root / scripts / gnt-instance @ e00f7a05

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