Statistics
| Branch: | Tag: | Revision:

root / scripts / gnt-instance @ a379d9bd

History | View | Annotate | Download (54.9 kB)

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