Statistics
| Branch: | Tag: | Revision:

root / scripts / gnt-instance @ 1c5945b6

History | View | Annotate | Download (48.2 kB)

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