Statistics
| Branch: | Tag: | Revision:

root / scripts / gnt-instance @ 1094acda

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