Statistics
| Branch: | Tag: | Revision:

root / scripts / gnt-instance @ 05d47e33

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