Statistics
| Branch: | Tag: | Revision:

root / scripts / gnt-instance @ c118d1f4

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