Statistics
| Branch: | Tag: | Revision:

root / scripts / gnt-instance @ 936f3c59

History | View | Annotate | Download (45.8 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 033d58b0 Iustin Pop
      "ctime": "CTime", "mtime": "MTime", "uuid": "UUID",
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 d77490c5 Iustin Pop
  This is just a wrapper over GenericInstanceCreate.
315 a8083063 Iustin Pop
316 a8083063 Iustin Pop
  """
317 d77490c5 Iustin Pop
  return GenericInstanceCreate(constants.INSTANCE_CREATE, opts, args)
318 a8083063 Iustin Pop
  return 0
319 a8083063 Iustin Pop
320 a8083063 Iustin Pop
321 0d0e9090 René Nussbaumer
def BatchCreate(opts, args):
322 7232c04c Iustin Pop
  """Create instances using a definition file.
323 7232c04c Iustin Pop
324 7232c04c Iustin Pop
  This function reads a json file with instances defined
325 7232c04c Iustin Pop
  in the form::
326 7232c04c Iustin Pop
327 7232c04c Iustin Pop
    {"instance-name":{
328 9939547b Iustin Pop
      "disk_size": [20480],
329 7232c04c Iustin Pop
      "template": "drbd",
330 7232c04c Iustin Pop
      "backend": {
331 7232c04c Iustin Pop
        "memory": 512,
332 7232c04c Iustin Pop
        "vcpus": 1 },
333 9939547b Iustin Pop
      "os": "debootstrap",
334 7232c04c Iustin Pop
      "primary_node": "firstnode",
335 7232c04c Iustin Pop
      "secondary_node": "secondnode",
336 7232c04c Iustin Pop
      "iallocator": "dumb"}
337 7232c04c Iustin Pop
    }
338 7232c04c Iustin Pop
339 7232c04c Iustin Pop
  Note that I{primary_node} and I{secondary_node} have precedence over
340 7232c04c Iustin Pop
  I{iallocator}.
341 7232c04c Iustin Pop
342 7232c04c Iustin Pop
  @param opts: the command line options selected by the user
343 7232c04c Iustin Pop
  @type args: list
344 7232c04c Iustin Pop
  @param args: should contain one element, the json filename
345 7232c04c Iustin Pop
  @rtype: int
346 7232c04c Iustin Pop
  @return: the desired exit code
347 0d0e9090 René Nussbaumer
348 0d0e9090 René Nussbaumer
  """
349 9939547b Iustin Pop
  _DEFAULT_SPECS = {"disk_size": [20 * 1024],
350 0d0e9090 René Nussbaumer
                    "backend": {},
351 0d0e9090 René Nussbaumer
                    "iallocator": None,
352 0d0e9090 René Nussbaumer
                    "primary_node": None,
353 0d0e9090 René Nussbaumer
                    "secondary_node": None,
354 a379d9bd Guido Trotter
                    "nics": None,
355 0d0e9090 René Nussbaumer
                    "start": True,
356 0d0e9090 René Nussbaumer
                    "ip_check": True,
357 0d0e9090 René Nussbaumer
                    "hypervisor": None,
358 4082e6f9 Iustin Pop
                    "hvparams": {},
359 0d0e9090 René Nussbaumer
                    "file_storage_dir": None,
360 0d0e9090 René Nussbaumer
                    "file_driver": 'loop'}
361 0d0e9090 René Nussbaumer
362 0d0e9090 René Nussbaumer
  def _PopulateWithDefaults(spec):
363 0d0e9090 René Nussbaumer
    """Returns a new hash combined with default values."""
364 2f79bd34 Iustin Pop
    mydict = _DEFAULT_SPECS.copy()
365 2f79bd34 Iustin Pop
    mydict.update(spec)
366 2f79bd34 Iustin Pop
    return mydict
367 0d0e9090 René Nussbaumer
368 0d0e9090 René Nussbaumer
  def _Validate(spec):
369 0d0e9090 René Nussbaumer
    """Validate the instance specs."""
370 0d0e9090 René Nussbaumer
    # Validate fields required under any circumstances
371 0d0e9090 René Nussbaumer
    for required_field in ('os', 'template'):
372 0d0e9090 René Nussbaumer
      if required_field not in spec:
373 0d0e9090 René Nussbaumer
        raise errors.OpPrereqError('Required field "%s" is missing.' %
374 0d0e9090 René Nussbaumer
                                   required_field)
375 0d0e9090 René Nussbaumer
    # Validate special fields
376 0d0e9090 René Nussbaumer
    if spec['primary_node'] is not None:
377 0d0e9090 René Nussbaumer
      if (spec['template'] in constants.DTS_NET_MIRROR and
378 0d0e9090 René Nussbaumer
          spec['secondary_node'] is None):
379 0d0e9090 René Nussbaumer
        raise errors.OpPrereqError('Template requires secondary node, but'
380 0d0e9090 René Nussbaumer
                                   ' there was no secondary provided.')
381 0d0e9090 René Nussbaumer
    elif spec['iallocator'] is None:
382 0d0e9090 René Nussbaumer
      raise errors.OpPrereqError('You have to provide at least a primary_node'
383 0d0e9090 René Nussbaumer
                                 ' or an iallocator.')
384 0d0e9090 René Nussbaumer
385 4082e6f9 Iustin Pop
    if (spec['hvparams'] and
386 4082e6f9 Iustin Pop
        not isinstance(spec['hvparams'], dict)):
387 0d0e9090 René Nussbaumer
      raise errors.OpPrereqError('Hypervisor parameters must be a dict.')
388 0d0e9090 René Nussbaumer
389 0d0e9090 René Nussbaumer
  json_filename = args[0]
390 0d0e9090 René Nussbaumer
  try:
391 13998ef2 Michael Hanselmann
    instance_data = simplejson.loads(utils.ReadFile(json_filename))
392 4082e6f9 Iustin Pop
  except Exception, err:
393 4082e6f9 Iustin Pop
    ToStderr("Can't parse the instance definition file: %s" % str(err))
394 4082e6f9 Iustin Pop
    return 1
395 0d0e9090 René Nussbaumer
396 d4dd4b74 Iustin Pop
  jex = JobExecutor()
397 d4dd4b74 Iustin Pop
398 0d0e9090 René Nussbaumer
  # Iterate over the instances and do:
399 0d0e9090 René Nussbaumer
  #  * Populate the specs with default value
400 0d0e9090 René Nussbaumer
  #  * Validate the instance specs
401 7312b33d Iustin Pop
  i_names = utils.NiceSort(instance_data.keys())
402 7312b33d Iustin Pop
  for name in i_names:
403 7312b33d Iustin Pop
    specs = instance_data[name]
404 0d0e9090 René Nussbaumer
    specs = _PopulateWithDefaults(specs)
405 0d0e9090 René Nussbaumer
    _Validate(specs)
406 0d0e9090 René Nussbaumer
407 4082e6f9 Iustin Pop
    hypervisor = specs['hypervisor']
408 4082e6f9 Iustin Pop
    hvparams = specs['hvparams']
409 0d0e9090 René Nussbaumer
410 9939547b Iustin Pop
    disks = []
411 9939547b Iustin Pop
    for elem in specs['disk_size']:
412 9939547b Iustin Pop
      try:
413 9939547b Iustin Pop
        size = utils.ParseUnit(elem)
414 9939547b Iustin Pop
      except ValueError, err:
415 9939547b Iustin Pop
        raise errors.OpPrereqError("Invalid disk size '%s' for"
416 9939547b Iustin Pop
                                   " instance %s: %s" %
417 9939547b Iustin Pop
                                   (elem, name, err))
418 9939547b Iustin Pop
      disks.append({"size": size})
419 9939547b Iustin Pop
420 a5728081 Guido Trotter
    utils.ForceDictType(specs['backend'], constants.BES_PARAMETER_TYPES)
421 a5728081 Guido Trotter
    utils.ForceDictType(hvparams, constants.HVS_PARAMETER_TYPES)
422 a5728081 Guido Trotter
423 a379d9bd Guido Trotter
    tmp_nics = []
424 a379d9bd Guido Trotter
    for field in ('ip', 'mac', 'mode', 'link', 'bridge'):
425 a379d9bd Guido Trotter
      if field in specs:
426 a379d9bd Guido Trotter
        if not tmp_nics:
427 a379d9bd Guido Trotter
          tmp_nics.append({})
428 a379d9bd Guido Trotter
        tmp_nics[0][field] = specs[field]
429 a379d9bd Guido Trotter
430 a379d9bd Guido Trotter
    if specs['nics'] is not None and tmp_nics:
431 a379d9bd Guido Trotter
      raise errors.OpPrereqError("'nics' list incompatible with using"
432 a379d9bd Guido Trotter
                                 " individual nic fields as well")
433 a379d9bd Guido Trotter
    elif specs['nics'] is not None:
434 a379d9bd Guido Trotter
      tmp_nics = specs['nics']
435 a379d9bd Guido Trotter
    elif not tmp_nics:
436 a379d9bd Guido Trotter
      tmp_nics = [{}]
437 a379d9bd Guido Trotter
438 0d0e9090 René Nussbaumer
    op = opcodes.OpCreateInstance(instance_name=name,
439 9939547b Iustin Pop
                                  disks=disks,
440 0d0e9090 René Nussbaumer
                                  disk_template=specs['template'],
441 0d0e9090 René Nussbaumer
                                  mode=constants.INSTANCE_CREATE,
442 0d0e9090 René Nussbaumer
                                  os_type=specs['os'],
443 06073e85 Guido Trotter
                                  force_variant=opts.force_variant,
444 0d0e9090 René Nussbaumer
                                  pnode=specs['primary_node'],
445 0d0e9090 René Nussbaumer
                                  snode=specs['secondary_node'],
446 a379d9bd Guido Trotter
                                  nics=tmp_nics,
447 0d0e9090 René Nussbaumer
                                  start=specs['start'],
448 0d0e9090 René Nussbaumer
                                  ip_check=specs['ip_check'],
449 0d0e9090 René Nussbaumer
                                  wait_for_sync=True,
450 0d0e9090 René Nussbaumer
                                  iallocator=specs['iallocator'],
451 0d0e9090 René Nussbaumer
                                  hypervisor=hypervisor,
452 0d0e9090 René Nussbaumer
                                  hvparams=hvparams,
453 0d0e9090 René Nussbaumer
                                  beparams=specs['backend'],
454 0d0e9090 René Nussbaumer
                                  file_storage_dir=specs['file_storage_dir'],
455 0d0e9090 René Nussbaumer
                                  file_driver=specs['file_driver'])
456 0d0e9090 René Nussbaumer
457 d4dd4b74 Iustin Pop
    jex.QueueJob(name, op)
458 d4dd4b74 Iustin Pop
  # we never want to wait, just show the submitted job IDs
459 d4dd4b74 Iustin Pop
  jex.WaitOrShow(False)
460 0d0e9090 René Nussbaumer
461 0d0e9090 René Nussbaumer
  return 0
462 0d0e9090 René Nussbaumer
463 0d0e9090 René Nussbaumer
464 fe7b0351 Michael Hanselmann
def ReinstallInstance(opts, args):
465 fe7b0351 Michael Hanselmann
  """Reinstall an instance.
466 fe7b0351 Michael Hanselmann
467 7232c04c Iustin Pop
  @param opts: the command line options selected by the user
468 7232c04c Iustin Pop
  @type args: list
469 7232c04c Iustin Pop
  @param args: should contain only one element, the name of the
470 7232c04c Iustin Pop
      instance to be reinstalled
471 7232c04c Iustin Pop
  @rtype: int
472 7232c04c Iustin Pop
  @return: the desired exit code
473 fe7b0351 Michael Hanselmann
474 fe7b0351 Michael Hanselmann
  """
475 55efe6da Iustin Pop
  # first, compute the desired name list
476 55efe6da Iustin Pop
  if opts.multi_mode is None:
477 55efe6da Iustin Pop
    opts.multi_mode = _SHUTDOWN_INSTANCES
478 55efe6da Iustin Pop
479 55efe6da Iustin Pop
  inames = _ExpandMultiNames(opts.multi_mode, args)
480 55efe6da Iustin Pop
  if not inames:
481 55efe6da Iustin Pop
    raise errors.OpPrereqError("Selection filter does not match any instances")
482 fe7b0351 Michael Hanselmann
483 55efe6da Iustin Pop
  # second, if requested, ask for an OS
484 20e23543 Alexander Schreiber
  if opts.select_os is True:
485 e3ac208c Guido Trotter
    op = opcodes.OpDiagnoseOS(output_fields=["name", "valid", "variants"],
486 e3ac208c Guido Trotter
                              names=[])
487 20e23543 Alexander Schreiber
    result = SubmitOpCode(op)
488 20e23543 Alexander Schreiber
489 20e23543 Alexander Schreiber
    if not result:
490 3a24c527 Iustin Pop
      ToStdout("Can't get the OS list")
491 20e23543 Alexander Schreiber
      return 1
492 20e23543 Alexander Schreiber
493 3a24c527 Iustin Pop
    ToStdout("Available OS templates:")
494 20e23543 Alexander Schreiber
    number = 0
495 20e23543 Alexander Schreiber
    choices = []
496 e3ac208c Guido Trotter
    for (name, valid, variants) in result:
497 e3ac208c Guido Trotter
      if valid:
498 e3ac208c Guido Trotter
        for entry in CalculateOSNames(name, variants):
499 e3ac208c Guido Trotter
          ToStdout("%3s: %s", number, entry)
500 e3ac208c Guido Trotter
          choices.append(("%s" % number, entry, entry))
501 e3ac208c Guido Trotter
          number += 1
502 20e23543 Alexander Schreiber
503 20e23543 Alexander Schreiber
    choices.append(('x', 'exit', 'Exit gnt-instance reinstall'))
504 949bdabe Iustin Pop
    selected = AskUser("Enter OS template number (or x to abort):",
505 20e23543 Alexander Schreiber
                       choices)
506 20e23543 Alexander Schreiber
507 20e23543 Alexander Schreiber
    if selected == 'exit':
508 55efe6da Iustin Pop
      ToStderr("User aborted reinstall, exiting")
509 20e23543 Alexander Schreiber
      return 1
510 20e23543 Alexander Schreiber
511 2f79bd34 Iustin Pop
    os_name = selected
512 20e23543 Alexander Schreiber
  else:
513 2f79bd34 Iustin Pop
    os_name = opts.os
514 20e23543 Alexander Schreiber
515 55efe6da Iustin Pop
  # third, get confirmation: multi-reinstall requires --force-multi
516 55efe6da Iustin Pop
  # *and* --force, single-reinstall just --force
517 55efe6da Iustin Pop
  multi_on = opts.multi_mode != _SHUTDOWN_INSTANCES or len(inames) > 1
518 55efe6da Iustin Pop
  if multi_on:
519 55efe6da Iustin Pop
    warn_msg = "Note: this will remove *all* data for the below instances!\n"
520 55efe6da Iustin Pop
    if not ((opts.force_multi and opts.force) or
521 55efe6da Iustin Pop
            _ConfirmOperation(inames, "reinstall", extra=warn_msg)):
522 fe7b0351 Michael Hanselmann
      return 1
523 55efe6da Iustin Pop
  else:
524 55efe6da Iustin Pop
    if not opts.force:
525 55efe6da Iustin Pop
      usertext = ("This will reinstall the instance %s and remove"
526 b6e243ab Iustin Pop
                  " all data. Continue?") % inames[0]
527 55efe6da Iustin Pop
      if not AskUser(usertext):
528 55efe6da Iustin Pop
        return 1
529 55efe6da Iustin Pop
530 55efe6da Iustin Pop
  jex = JobExecutor(verbose=multi_on)
531 55efe6da Iustin Pop
  for instance_name in inames:
532 55efe6da Iustin Pop
    op = opcodes.OpReinstallInstance(instance_name=instance_name,
533 06073e85 Guido Trotter
                                     os_type=os_name,
534 06073e85 Guido Trotter
                                     force_variant=opts.force_variant)
535 55efe6da Iustin Pop
    jex.QueueJob(instance_name, op)
536 fe7b0351 Michael Hanselmann
537 55efe6da Iustin Pop
  jex.WaitOrShow(not opts.submit_only)
538 fe7b0351 Michael Hanselmann
  return 0
539 fe7b0351 Michael Hanselmann
540 fe7b0351 Michael Hanselmann
541 a8083063 Iustin Pop
def RemoveInstance(opts, args):
542 a8083063 Iustin Pop
  """Remove an instance.
543 a8083063 Iustin Pop
544 7232c04c Iustin Pop
  @param opts: the command line options selected by the user
545 7232c04c Iustin Pop
  @type args: list
546 7232c04c Iustin Pop
  @param args: should contain only one element, the name of
547 7232c04c Iustin Pop
      the instance to be removed
548 7232c04c Iustin Pop
  @rtype: int
549 7232c04c Iustin Pop
  @return: the desired exit code
550 a8083063 Iustin Pop
551 a8083063 Iustin Pop
  """
552 a8083063 Iustin Pop
  instance_name = args[0]
553 a8083063 Iustin Pop
  force = opts.force
554 a76f0c4a Iustin Pop
  cl = GetClient()
555 a8083063 Iustin Pop
556 a8083063 Iustin Pop
  if not force:
557 a76f0c4a Iustin Pop
    _EnsureInstancesExist(cl, [instance_name])
558 a76f0c4a Iustin Pop
559 a8083063 Iustin Pop
    usertext = ("This will remove the volumes of the instance %s"
560 a8083063 Iustin Pop
                " (including mirrors), thus removing all the data"
561 a8083063 Iustin Pop
                " of the instance. Continue?") % instance_name
562 47988778 Iustin Pop
    if not AskUser(usertext):
563 a8083063 Iustin Pop
      return 1
564 a8083063 Iustin Pop
565 1d67656e Iustin Pop
  op = opcodes.OpRemoveInstance(instance_name=instance_name,
566 17c3f802 Guido Trotter
                                ignore_failures=opts.ignore_failures,
567 4d98c565 Guido Trotter
                                shutdown_timeout=opts.shutdown_timeout)
568 a76f0c4a Iustin Pop
  SubmitOrSend(op, opts, cl=cl)
569 a8083063 Iustin Pop
  return 0
570 a8083063 Iustin Pop
571 a8083063 Iustin Pop
572 decd5f45 Iustin Pop
def RenameInstance(opts, args):
573 4ab0b9e3 Guido Trotter
  """Rename an instance.
574 decd5f45 Iustin Pop
575 7232c04c Iustin Pop
  @param opts: the command line options selected by the user
576 7232c04c Iustin Pop
  @type args: list
577 7232c04c Iustin Pop
  @param args: should contain two elements, the old and the
578 7232c04c Iustin Pop
      new instance names
579 7232c04c Iustin Pop
  @rtype: int
580 7232c04c Iustin Pop
  @return: the desired exit code
581 decd5f45 Iustin Pop
582 decd5f45 Iustin Pop
  """
583 decd5f45 Iustin Pop
  op = opcodes.OpRenameInstance(instance_name=args[0],
584 decd5f45 Iustin Pop
                                new_name=args[1],
585 decd5f45 Iustin Pop
                                ignore_ip=opts.ignore_ip)
586 6340bb0a Iustin Pop
  SubmitOrSend(op, opts)
587 decd5f45 Iustin Pop
  return 0
588 decd5f45 Iustin Pop
589 decd5f45 Iustin Pop
590 a8083063 Iustin Pop
def ActivateDisks(opts, args):
591 a8083063 Iustin Pop
  """Activate an instance's disks.
592 a8083063 Iustin Pop
593 a8083063 Iustin Pop
  This serves two purposes:
594 7232c04c Iustin Pop
    - it allows (as long as the instance is not running)
595 7232c04c Iustin Pop
      mounting the disks and modifying them from the node
596 a8083063 Iustin Pop
    - it repairs inactive secondary drbds
597 a8083063 Iustin Pop
598 7232c04c Iustin Pop
  @param opts: the command line options selected by the user
599 7232c04c Iustin Pop
  @type args: list
600 7232c04c Iustin Pop
  @param args: should contain only one element, the instance name
601 7232c04c Iustin Pop
  @rtype: int
602 7232c04c Iustin Pop
  @return: the desired exit code
603 7232c04c Iustin Pop
604 a8083063 Iustin Pop
  """
605 a8083063 Iustin Pop
  instance_name = args[0]
606 b4ec07f8 Iustin Pop
  op = opcodes.OpActivateInstanceDisks(instance_name=instance_name,
607 b4ec07f8 Iustin Pop
                                       ignore_size=opts.ignore_size)
608 6340bb0a Iustin Pop
  disks_info = SubmitOrSend(op, opts)
609 a8083063 Iustin Pop
  for host, iname, nname in disks_info:
610 3a24c527 Iustin Pop
    ToStdout("%s:%s:%s", host, iname, nname)
611 a8083063 Iustin Pop
  return 0
612 a8083063 Iustin Pop
613 a8083063 Iustin Pop
614 a8083063 Iustin Pop
def DeactivateDisks(opts, args):
615 bd315bfa Iustin Pop
  """Deactivate an instance's disks.
616 a8083063 Iustin Pop
617 a8083063 Iustin Pop
  This function takes the instance name, looks for its primary node
618 a8083063 Iustin Pop
  and the tries to shutdown its block devices on that node.
619 a8083063 Iustin Pop
620 7232c04c Iustin Pop
  @param opts: the command line options selected by the user
621 7232c04c Iustin Pop
  @type args: list
622 7232c04c Iustin Pop
  @param args: should contain only one element, the instance name
623 7232c04c Iustin Pop
  @rtype: int
624 7232c04c Iustin Pop
  @return: the desired exit code
625 7232c04c Iustin Pop
626 a8083063 Iustin Pop
  """
627 a8083063 Iustin Pop
  instance_name = args[0]
628 a8083063 Iustin Pop
  op = opcodes.OpDeactivateInstanceDisks(instance_name=instance_name)
629 6340bb0a Iustin Pop
  SubmitOrSend(op, opts)
630 a8083063 Iustin Pop
  return 0
631 a8083063 Iustin Pop
632 a8083063 Iustin Pop
633 bd315bfa Iustin Pop
def RecreateDisks(opts, args):
634 bd315bfa Iustin Pop
  """Recreate an instance's disks.
635 bd315bfa Iustin Pop
636 bd315bfa Iustin Pop
  @param opts: the command line options selected by the user
637 bd315bfa Iustin Pop
  @type args: list
638 bd315bfa Iustin Pop
  @param args: should contain only one element, the instance name
639 bd315bfa Iustin Pop
  @rtype: int
640 bd315bfa Iustin Pop
  @return: the desired exit code
641 bd315bfa Iustin Pop
642 bd315bfa Iustin Pop
  """
643 bd315bfa Iustin Pop
  instance_name = args[0]
644 bd315bfa Iustin Pop
  if opts.disks:
645 bd315bfa Iustin Pop
    try:
646 bd315bfa Iustin Pop
      opts.disks = [int(v) for v in opts.disks.split(",")]
647 bd315bfa Iustin Pop
    except (ValueError, TypeError), err:
648 bd315bfa Iustin Pop
      ToStderr("Invalid disks value: %s" % str(err))
649 bd315bfa Iustin Pop
      return 1
650 bd315bfa Iustin Pop
  else:
651 bd315bfa Iustin Pop
    opts.disks = []
652 bd315bfa Iustin Pop
653 bd315bfa Iustin Pop
  op = opcodes.OpRecreateInstanceDisks(instance_name=instance_name,
654 bd315bfa Iustin Pop
                                       disks=opts.disks)
655 bd315bfa Iustin Pop
  SubmitOrSend(op, opts)
656 bd315bfa Iustin Pop
  return 0
657 bd315bfa Iustin Pop
658 bd315bfa Iustin Pop
659 c6e911bc Iustin Pop
def GrowDisk(opts, args):
660 7232c04c Iustin Pop
  """Grow an instance's disks.
661 c6e911bc Iustin Pop
662 7232c04c Iustin Pop
  @param opts: the command line options selected by the user
663 7232c04c Iustin Pop
  @type args: list
664 7232c04c Iustin Pop
  @param args: should contain two elements, the instance name
665 7232c04c Iustin Pop
      whose disks we grow and the disk name, e.g. I{sda}
666 7232c04c Iustin Pop
  @rtype: int
667 7232c04c Iustin Pop
  @return: the desired exit code
668 c6e911bc Iustin Pop
669 c6e911bc Iustin Pop
  """
670 c6e911bc Iustin Pop
  instance = args[0]
671 c6e911bc Iustin Pop
  disk = args[1]
672 ad24e046 Iustin Pop
  try:
673 ad24e046 Iustin Pop
    disk = int(disk)
674 ad24e046 Iustin Pop
  except ValueError, err:
675 ad24e046 Iustin Pop
    raise errors.OpPrereqError("Invalid disk index: %s" % str(err))
676 c6e911bc Iustin Pop
  amount = utils.ParseUnit(args[2])
677 6605411d Iustin Pop
  op = opcodes.OpGrowDisk(instance_name=instance, disk=disk, amount=amount,
678 6605411d Iustin Pop
                          wait_for_sync=opts.wait_for_sync)
679 6340bb0a Iustin Pop
  SubmitOrSend(op, opts)
680 c6e911bc Iustin Pop
  return 0
681 c6e911bc Iustin Pop
682 c6e911bc Iustin Pop
683 1c5945b6 Iustin Pop
def _StartupInstance(name, opts):
684 7232c04c Iustin Pop
  """Startup instances.
685 a8083063 Iustin Pop
686 1c5945b6 Iustin Pop
  This returns the opcode to start an instance, and its decorator will
687 1c5945b6 Iustin Pop
  wrap this into a loop starting all desired instances.
688 7232c04c Iustin Pop
689 1c5945b6 Iustin Pop
  @param name: the name of the instance to act on
690 7232c04c Iustin Pop
  @param opts: the command line options selected by the user
691 1c5945b6 Iustin Pop
  @return: the opcode needed for the operation
692 a8083063 Iustin Pop
693 a8083063 Iustin Pop
  """
694 1c5945b6 Iustin Pop
  op = opcodes.OpStartupInstance(instance_name=name,
695 1c5945b6 Iustin Pop
                                 force=opts.force)
696 1c5945b6 Iustin Pop
  # do not add these parameters to the opcode unless they're defined
697 1c5945b6 Iustin Pop
  if opts.hvparams:
698 1c5945b6 Iustin Pop
    op.hvparams = opts.hvparams
699 1c5945b6 Iustin Pop
  if opts.beparams:
700 1c5945b6 Iustin Pop
    op.beparams = opts.beparams
701 1c5945b6 Iustin Pop
  return op
702 a8083063 Iustin Pop
703 7c0d6283 Michael Hanselmann
704 1c5945b6 Iustin Pop
def _RebootInstance(name, opts):
705 7232c04c Iustin Pop
  """Reboot instance(s).
706 7232c04c Iustin Pop
707 1c5945b6 Iustin Pop
  This returns the opcode to reboot an instance, and its decorator
708 1c5945b6 Iustin Pop
  will wrap this into a loop rebooting all desired instances.
709 579d4337 Alexander Schreiber
710 1c5945b6 Iustin Pop
  @param name: the name of the instance to act on
711 7232c04c Iustin Pop
  @param opts: the command line options selected by the user
712 1c5945b6 Iustin Pop
  @return: the opcode needed for the operation
713 579d4337 Alexander Schreiber
714 579d4337 Alexander Schreiber
  """
715 1c5945b6 Iustin Pop
  return opcodes.OpRebootInstance(instance_name=name,
716 579d4337 Alexander Schreiber
                                  reboot_type=opts.reboot_type,
717 17c3f802 Guido Trotter
                                  ignore_secondaries=opts.ignore_secondaries,
718 4d98c565 Guido Trotter
                                  shutdown_timeout=opts.shutdown_timeout)
719 a8083063 Iustin Pop
720 7c0d6283 Michael Hanselmann
721 1c5945b6 Iustin Pop
def _ShutdownInstance(name, opts):
722 a8083063 Iustin Pop
  """Shutdown an instance.
723 a8083063 Iustin Pop
724 1c5945b6 Iustin Pop
  This returns the opcode to shutdown an instance, and its decorator
725 1c5945b6 Iustin Pop
  will wrap this into a loop shutting down all desired instances.
726 1c5945b6 Iustin Pop
727 1c5945b6 Iustin Pop
  @param name: the name of the instance to act on
728 7232c04c Iustin Pop
  @param opts: the command line options selected by the user
729 1c5945b6 Iustin Pop
  @return: the opcode needed for the operation
730 a8083063 Iustin Pop
731 a8083063 Iustin Pop
  """
732 6263189c Guido Trotter
  return opcodes.OpShutdownInstance(instance_name=name,
733 6263189c Guido Trotter
                                    timeout=opts.timeout)
734 a8083063 Iustin Pop
735 a8083063 Iustin Pop
736 a8083063 Iustin Pop
def ReplaceDisks(opts, args):
737 a8083063 Iustin Pop
  """Replace the disks of an instance
738 a8083063 Iustin Pop
739 7232c04c Iustin Pop
  @param opts: the command line options selected by the user
740 7232c04c Iustin Pop
  @type args: list
741 7232c04c Iustin Pop
  @param args: should contain only one element, the instance name
742 7232c04c Iustin Pop
  @rtype: int
743 7232c04c Iustin Pop
  @return: the desired exit code
744 a8083063 Iustin Pop
745 a8083063 Iustin Pop
  """
746 a8083063 Iustin Pop
  instance_name = args[0]
747 a14db5ff Iustin Pop
  new_2ndary = opts.dst_node
748 b6e82a65 Iustin Pop
  iallocator = opts.iallocator
749 a9e0c397 Iustin Pop
  if opts.disks is None:
750 54155f52 Iustin Pop
    disks = []
751 a9e0c397 Iustin Pop
  else:
752 54155f52 Iustin Pop
    try:
753 54155f52 Iustin Pop
      disks = [int(i) for i in opts.disks.split(",")]
754 54155f52 Iustin Pop
    except ValueError, err:
755 54155f52 Iustin Pop
      raise errors.OpPrereqError("Invalid disk index passed: %s" % str(err))
756 05d47e33 Michael Hanselmann
  cnt = [opts.on_primary, opts.on_secondary, opts.auto,
757 7e9366f7 Iustin Pop
         new_2ndary is not None, iallocator is not None].count(True)
758 7e9366f7 Iustin Pop
  if cnt != 1:
759 05d47e33 Michael Hanselmann
    raise errors.OpPrereqError("One and only one of the -p, -s, -a, -n and -i"
760 7e9366f7 Iustin Pop
                               " options must be passed")
761 7e9366f7 Iustin Pop
  elif opts.on_primary:
762 a9e0c397 Iustin Pop
    mode = constants.REPLACE_DISK_PRI
763 7e9366f7 Iustin Pop
  elif opts.on_secondary:
764 a9e0c397 Iustin Pop
    mode = constants.REPLACE_DISK_SEC
765 05d47e33 Michael Hanselmann
  elif opts.auto:
766 05d47e33 Michael Hanselmann
    mode = constants.REPLACE_DISK_AUTO
767 05d47e33 Michael Hanselmann
    if disks:
768 05d47e33 Michael Hanselmann
      raise errors.OpPrereqError("Cannot specify disks when using automatic"
769 05d47e33 Michael Hanselmann
                                 " mode")
770 7e9366f7 Iustin Pop
  elif new_2ndary is not None or iallocator is not None:
771 7e9366f7 Iustin Pop
    # replace secondary
772 7e9366f7 Iustin Pop
    mode = constants.REPLACE_DISK_CHG
773 a9e0c397 Iustin Pop
774 a9e0c397 Iustin Pop
  op = opcodes.OpReplaceDisks(instance_name=args[0], disks=disks,
775 b6e82a65 Iustin Pop
                              remote_node=new_2ndary, mode=mode,
776 b6e82a65 Iustin Pop
                              iallocator=iallocator)
777 6340bb0a Iustin Pop
  SubmitOrSend(op, opts)
778 a8083063 Iustin Pop
  return 0
779 a8083063 Iustin Pop
780 a8083063 Iustin Pop
781 a8083063 Iustin Pop
def FailoverInstance(opts, args):
782 a8083063 Iustin Pop
  """Failover an instance.
783 a8083063 Iustin Pop
784 a8083063 Iustin Pop
  The failover is done by shutting it down on its present node and
785 a8083063 Iustin Pop
  starting it on the secondary.
786 a8083063 Iustin Pop
787 7232c04c Iustin Pop
  @param opts: the command line options selected by the user
788 7232c04c Iustin Pop
  @type args: list
789 7232c04c Iustin Pop
  @param args: should contain only one element, the instance name
790 7232c04c Iustin Pop
  @rtype: int
791 7232c04c Iustin Pop
  @return: the desired exit code
792 a8083063 Iustin Pop
793 a8083063 Iustin Pop
  """
794 a76f0c4a Iustin Pop
  cl = GetClient()
795 80de0e3f Iustin Pop
  instance_name = args[0]
796 80de0e3f Iustin Pop
  force = opts.force
797 a8083063 Iustin Pop
798 80de0e3f Iustin Pop
  if not force:
799 a76f0c4a Iustin Pop
    _EnsureInstancesExist(cl, [instance_name])
800 a76f0c4a Iustin Pop
801 80de0e3f Iustin Pop
    usertext = ("Failover will happen to image %s."
802 80de0e3f Iustin Pop
                " This requires a shutdown of the instance. Continue?" %
803 80de0e3f Iustin Pop
                (instance_name,))
804 80de0e3f Iustin Pop
    if not AskUser(usertext):
805 80de0e3f Iustin Pop
      return 1
806 a8083063 Iustin Pop
807 80de0e3f Iustin Pop
  op = opcodes.OpFailoverInstance(instance_name=instance_name,
808 17c3f802 Guido Trotter
                                  ignore_consistency=opts.ignore_consistency,
809 4d98c565 Guido Trotter
                                  shutdown_timeout=opts.shutdown_timeout)
810 a76f0c4a Iustin Pop
  SubmitOrSend(op, opts, cl=cl)
811 80de0e3f Iustin Pop
  return 0
812 a8083063 Iustin Pop
813 a8083063 Iustin Pop
814 53c776b5 Iustin Pop
def MigrateInstance(opts, args):
815 53c776b5 Iustin Pop
  """Migrate an instance.
816 53c776b5 Iustin Pop
817 53c776b5 Iustin Pop
  The migrate is done without shutdown.
818 53c776b5 Iustin Pop
819 2f907a8c Iustin Pop
  @param opts: the command line options selected by the user
820 2f907a8c Iustin Pop
  @type args: list
821 2f907a8c Iustin Pop
  @param args: should contain only one element, the instance name
822 2f907a8c Iustin Pop
  @rtype: int
823 2f907a8c Iustin Pop
  @return: the desired exit code
824 53c776b5 Iustin Pop
825 53c776b5 Iustin Pop
  """
826 a76f0c4a Iustin Pop
  cl = GetClient()
827 53c776b5 Iustin Pop
  instance_name = args[0]
828 53c776b5 Iustin Pop
  force = opts.force
829 53c776b5 Iustin Pop
830 53c776b5 Iustin Pop
  if not force:
831 a76f0c4a Iustin Pop
    _EnsureInstancesExist(cl, [instance_name])
832 a76f0c4a Iustin Pop
833 53c776b5 Iustin Pop
    if opts.cleanup:
834 53c776b5 Iustin Pop
      usertext = ("Instance %s will be recovered from a failed migration."
835 53c776b5 Iustin Pop
                  " Note that the migration procedure (including cleanup)" %
836 53c776b5 Iustin Pop
                  (instance_name,))
837 53c776b5 Iustin Pop
    else:
838 53c776b5 Iustin Pop
      usertext = ("Instance %s will be migrated. Note that migration" %
839 53c776b5 Iustin Pop
                  (instance_name,))
840 53c776b5 Iustin Pop
    usertext += (" is **experimental** in this version."
841 53c776b5 Iustin Pop
                " This might impact the instance if anything goes wrong."
842 53c776b5 Iustin Pop
                " Continue?")
843 53c776b5 Iustin Pop
    if not AskUser(usertext):
844 53c776b5 Iustin Pop
      return 1
845 53c776b5 Iustin Pop
846 53c776b5 Iustin Pop
  op = opcodes.OpMigrateInstance(instance_name=instance_name, live=opts.live,
847 53c776b5 Iustin Pop
                                 cleanup=opts.cleanup)
848 a76f0c4a Iustin Pop
  SubmitOpCode(op, cl=cl)
849 53c776b5 Iustin Pop
  return 0
850 53c776b5 Iustin Pop
851 53c776b5 Iustin Pop
852 fbf5a861 Iustin Pop
def MoveInstance(opts, args):
853 fbf5a861 Iustin Pop
  """Move an instance.
854 fbf5a861 Iustin Pop
855 fbf5a861 Iustin Pop
  @param opts: the command line options selected by the user
856 fbf5a861 Iustin Pop
  @type args: list
857 fbf5a861 Iustin Pop
  @param args: should contain only one element, the instance name
858 fbf5a861 Iustin Pop
  @rtype: int
859 fbf5a861 Iustin Pop
  @return: the desired exit code
860 fbf5a861 Iustin Pop
861 fbf5a861 Iustin Pop
  """
862 fbf5a861 Iustin Pop
  cl = GetClient()
863 fbf5a861 Iustin Pop
  instance_name = args[0]
864 fbf5a861 Iustin Pop
  force = opts.force
865 fbf5a861 Iustin Pop
866 fbf5a861 Iustin Pop
  if not force:
867 fbf5a861 Iustin Pop
    usertext = ("Instance %s will be moved."
868 fbf5a861 Iustin Pop
                " This requires a shutdown of the instance. Continue?" %
869 fbf5a861 Iustin Pop
                (instance_name,))
870 fbf5a861 Iustin Pop
    if not AskUser(usertext):
871 fbf5a861 Iustin Pop
      return 1
872 fbf5a861 Iustin Pop
873 fbf5a861 Iustin Pop
  op = opcodes.OpMoveInstance(instance_name=instance_name,
874 17c3f802 Guido Trotter
                              target_node=opts.node,
875 4d98c565 Guido Trotter
                              shutdown_timeout=opts.shutdown_timeout)
876 fbf5a861 Iustin Pop
  SubmitOrSend(op, opts, cl=cl)
877 fbf5a861 Iustin Pop
  return 0
878 fbf5a861 Iustin Pop
879 fbf5a861 Iustin Pop
880 a8083063 Iustin Pop
def ConnectToInstanceConsole(opts, args):
881 a8083063 Iustin Pop
  """Connect to the console of an instance.
882 a8083063 Iustin Pop
883 7232c04c Iustin Pop
  @param opts: the command line options selected by the user
884 7232c04c Iustin Pop
  @type args: list
885 7232c04c Iustin Pop
  @param args: should contain only one element, the instance name
886 7232c04c Iustin Pop
  @rtype: int
887 7232c04c Iustin Pop
  @return: the desired exit code
888 a8083063 Iustin Pop
889 a8083063 Iustin Pop
  """
890 a8083063 Iustin Pop
  instance_name = args[0]
891 a8083063 Iustin Pop
892 a8083063 Iustin Pop
  op = opcodes.OpConnectConsole(instance_name=instance_name)
893 0a80a26f Michael Hanselmann
  cmd = SubmitOpCode(op)
894 51c6e7b5 Michael Hanselmann
895 51c6e7b5 Michael Hanselmann
  if opts.show_command:
896 3a24c527 Iustin Pop
    ToStdout("%s", utils.ShellQuoteArgs(cmd))
897 51c6e7b5 Michael Hanselmann
  else:
898 51c6e7b5 Michael Hanselmann
    try:
899 51c6e7b5 Michael Hanselmann
      os.execvp(cmd[0], cmd)
900 51c6e7b5 Michael Hanselmann
    finally:
901 3a24c527 Iustin Pop
      ToStderr("Can't run console command %s with arguments:\n'%s'",
902 2f79bd34 Iustin Pop
               cmd[0], " ".join(cmd))
903 51c6e7b5 Michael Hanselmann
      os._exit(1)
904 a8083063 Iustin Pop
905 a8083063 Iustin Pop
906 19708787 Iustin Pop
def _FormatLogicalID(dev_type, logical_id):
907 19708787 Iustin Pop
  """Formats the logical_id of a disk.
908 19708787 Iustin Pop
909 19708787 Iustin Pop
  """
910 19708787 Iustin Pop
  if dev_type == constants.LD_DRBD8:
911 19708787 Iustin Pop
    node_a, node_b, port, minor_a, minor_b, key = logical_id
912 19708787 Iustin Pop
    data = [
913 19708787 Iustin Pop
      ("nodeA", "%s, minor=%s" % (node_a, minor_a)),
914 19708787 Iustin Pop
      ("nodeB", "%s, minor=%s" % (node_b, minor_b)),
915 19708787 Iustin Pop
      ("port", port),
916 19708787 Iustin Pop
      ("auth key", key),
917 19708787 Iustin Pop
      ]
918 19708787 Iustin Pop
  elif dev_type == constants.LD_LV:
919 19708787 Iustin Pop
    vg_name, lv_name = logical_id
920 19708787 Iustin Pop
    data = ["%s/%s" % (vg_name, lv_name)]
921 19708787 Iustin Pop
  else:
922 19708787 Iustin Pop
    data = [str(logical_id)]
923 19708787 Iustin Pop
924 19708787 Iustin Pop
  return data
925 19708787 Iustin Pop
926 19708787 Iustin Pop
927 19708787 Iustin Pop
def _FormatBlockDevInfo(idx, top_level, dev, static):
928 a8083063 Iustin Pop
  """Show block device information.
929 a8083063 Iustin Pop
930 7232c04c Iustin Pop
  This is only used by L{ShowInstanceConfig}, but it's too big to be
931 a8083063 Iustin Pop
  left for an inline definition.
932 a8083063 Iustin Pop
933 19708787 Iustin Pop
  @type idx: int
934 19708787 Iustin Pop
  @param idx: the index of the current disk
935 19708787 Iustin Pop
  @type top_level: boolean
936 19708787 Iustin Pop
  @param top_level: if this a top-level disk?
937 7232c04c Iustin Pop
  @type dev: dict
938 7232c04c Iustin Pop
  @param dev: dictionary with disk information
939 7232c04c Iustin Pop
  @type static: boolean
940 7232c04c Iustin Pop
  @param static: wheter the device information doesn't contain
941 7232c04c Iustin Pop
      runtime information but only static data
942 19708787 Iustin Pop
  @return: a list of either strings, tuples or lists
943 19708787 Iustin Pop
      (which should be formatted at a higher indent level)
944 7232c04c Iustin Pop
945 a8083063 Iustin Pop
  """
946 19708787 Iustin Pop
  def helper(dtype, status):
947 7232c04c Iustin Pop
    """Format one line for physical device status.
948 7232c04c Iustin Pop
949 7232c04c Iustin Pop
    @type dtype: str
950 7232c04c Iustin Pop
    @param dtype: a constant from the L{constants.LDS_BLOCK} set
951 7232c04c Iustin Pop
    @type status: tuple
952 7232c04c Iustin Pop
    @param status: a tuple as returned from L{backend.FindBlockDevice}
953 19708787 Iustin Pop
    @return: the string representing the status
954 7232c04c Iustin Pop
955 7232c04c Iustin Pop
    """
956 a8083063 Iustin Pop
    if not status:
957 19708787 Iustin Pop
      return "not active"
958 19708787 Iustin Pop
    txt = ""
959 f208978a Michael Hanselmann
    (path, major, minor, syncp, estt, degr, ldisk_status) = status
960 19708787 Iustin Pop
    if major is None:
961 19708787 Iustin Pop
      major_string = "N/A"
962 a8083063 Iustin Pop
    else:
963 19708787 Iustin Pop
      major_string = str(major)
964 fd38ef95 Manuel Franceschini
965 19708787 Iustin Pop
    if minor is None:
966 19708787 Iustin Pop
      minor_string = "N/A"
967 19708787 Iustin Pop
    else:
968 19708787 Iustin Pop
      minor_string = str(minor)
969 19708787 Iustin Pop
970 19708787 Iustin Pop
    txt += ("%s (%s:%s)" % (path, major_string, minor_string))
971 19708787 Iustin Pop
    if dtype in (constants.LD_DRBD8, ):
972 19708787 Iustin Pop
      if syncp is not None:
973 19708787 Iustin Pop
        sync_text = "*RECOVERING* %5.2f%%," % syncp
974 19708787 Iustin Pop
        if estt:
975 19708787 Iustin Pop
          sync_text += " ETA %ds" % estt
976 9db6dbce Iustin Pop
        else:
977 19708787 Iustin Pop
          sync_text += " ETA unknown"
978 19708787 Iustin Pop
      else:
979 19708787 Iustin Pop
        sync_text = "in sync"
980 19708787 Iustin Pop
      if degr:
981 19708787 Iustin Pop
        degr_text = "*DEGRADED*"
982 19708787 Iustin Pop
      else:
983 19708787 Iustin Pop
        degr_text = "ok"
984 f208978a Michael Hanselmann
      if ldisk_status == constants.LDS_FAULTY:
985 19708787 Iustin Pop
        ldisk_text = " *MISSING DISK*"
986 f208978a Michael Hanselmann
      elif ldisk_status == constants.LDS_UNKNOWN:
987 f208978a Michael Hanselmann
        ldisk_text = " *UNCERTAIN STATE*"
988 19708787 Iustin Pop
      else:
989 19708787 Iustin Pop
        ldisk_text = ""
990 19708787 Iustin Pop
      txt += (" %s, status %s%s" % (sync_text, degr_text, ldisk_text))
991 19708787 Iustin Pop
    elif dtype == constants.LD_LV:
992 f208978a Michael Hanselmann
      if ldisk_status == constants.LDS_FAULTY:
993 19708787 Iustin Pop
        ldisk_text = " *FAILED* (failed drive?)"
994 19708787 Iustin Pop
      else:
995 19708787 Iustin Pop
        ldisk_text = ""
996 19708787 Iustin Pop
      txt += ldisk_text
997 19708787 Iustin Pop
    return txt
998 19708787 Iustin Pop
999 19708787 Iustin Pop
  # the header
1000 19708787 Iustin Pop
  if top_level:
1001 19708787 Iustin Pop
    if dev["iv_name"] is not None:
1002 19708787 Iustin Pop
      txt = dev["iv_name"]
1003 19708787 Iustin Pop
    else:
1004 19708787 Iustin Pop
      txt = "disk %d" % idx
1005 a8083063 Iustin Pop
  else:
1006 19708787 Iustin Pop
    txt = "child %d" % idx
1007 c98162a7 Iustin Pop
  if isinstance(dev["size"], int):
1008 c98162a7 Iustin Pop
    nice_size = utils.FormatUnit(dev["size"], "h")
1009 c98162a7 Iustin Pop
  else:
1010 c98162a7 Iustin Pop
    nice_size = dev["size"]
1011 c98162a7 Iustin Pop
  d1 = ["- %s: %s, size %s" % (txt, dev["dev_type"], nice_size)]
1012 19708787 Iustin Pop
  data = []
1013 19708787 Iustin Pop
  if top_level:
1014 19708787 Iustin Pop
    data.append(("access mode", dev["mode"]))
1015 a8083063 Iustin Pop
  if dev["logical_id"] is not None:
1016 19708787 Iustin Pop
    try:
1017 19708787 Iustin Pop
      l_id = _FormatLogicalID(dev["dev_type"], dev["logical_id"])
1018 19708787 Iustin Pop
    except ValueError:
1019 19708787 Iustin Pop
      l_id = [str(dev["logical_id"])]
1020 19708787 Iustin Pop
    if len(l_id) == 1:
1021 19708787 Iustin Pop
      data.append(("logical_id", l_id[0]))
1022 19708787 Iustin Pop
    else:
1023 19708787 Iustin Pop
      data.extend(l_id)
1024 a8083063 Iustin Pop
  elif dev["physical_id"] is not None:
1025 19708787 Iustin Pop
    data.append("physical_id:")
1026 19708787 Iustin Pop
    data.append([dev["physical_id"]])
1027 57821cac Iustin Pop
  if not static:
1028 19708787 Iustin Pop
    data.append(("on primary", helper(dev["dev_type"], dev["pstatus"])))
1029 57821cac Iustin Pop
  if dev["sstatus"] and not static:
1030 19708787 Iustin Pop
    data.append(("on secondary", helper(dev["dev_type"], dev["sstatus"])))
1031 a8083063 Iustin Pop
1032 a8083063 Iustin Pop
  if dev["children"]:
1033 19708787 Iustin Pop
    data.append("child devices:")
1034 19708787 Iustin Pop
    for c_idx, child in enumerate(dev["children"]):
1035 19708787 Iustin Pop
      data.append(_FormatBlockDevInfo(c_idx, False, child, static))
1036 19708787 Iustin Pop
  d1.append(data)
1037 19708787 Iustin Pop
  return d1
1038 a8083063 Iustin Pop
1039 a8083063 Iustin Pop
1040 19708787 Iustin Pop
def _FormatList(buf, data, indent_level):
1041 19708787 Iustin Pop
  """Formats a list of data at a given indent level.
1042 19708787 Iustin Pop
1043 19708787 Iustin Pop
  If the element of the list is:
1044 19708787 Iustin Pop
    - a string, it is simply formatted as is
1045 19708787 Iustin Pop
    - a tuple, it will be split into key, value and the all the
1046 19708787 Iustin Pop
      values in a list will be aligned all at the same start column
1047 19708787 Iustin Pop
    - a list, will be recursively formatted
1048 19708787 Iustin Pop
1049 19708787 Iustin Pop
  @type buf: StringIO
1050 19708787 Iustin Pop
  @param buf: the buffer into which we write the output
1051 19708787 Iustin Pop
  @param data: the list to format
1052 19708787 Iustin Pop
  @type indent_level: int
1053 19708787 Iustin Pop
  @param indent_level: the indent level to format at
1054 19708787 Iustin Pop
1055 19708787 Iustin Pop
  """
1056 19708787 Iustin Pop
  max_tlen = max([len(elem[0]) for elem in data
1057 19708787 Iustin Pop
                 if isinstance(elem, tuple)] or [0])
1058 19708787 Iustin Pop
  for elem in data:
1059 19708787 Iustin Pop
    if isinstance(elem, basestring):
1060 19708787 Iustin Pop
      buf.write("%*s%s\n" % (2*indent_level, "", elem))
1061 19708787 Iustin Pop
    elif isinstance(elem, tuple):
1062 19708787 Iustin Pop
      key, value = elem
1063 19708787 Iustin Pop
      spacer = "%*s" % (max_tlen - len(key), "")
1064 19708787 Iustin Pop
      buf.write("%*s%s:%s %s\n" % (2*indent_level, "", key, spacer, value))
1065 19708787 Iustin Pop
    elif isinstance(elem, list):
1066 19708787 Iustin Pop
      _FormatList(buf, elem, indent_level+1)
1067 19708787 Iustin Pop
1068 98825740 Michael Hanselmann
1069 a8083063 Iustin Pop
def ShowInstanceConfig(opts, args):
1070 a8083063 Iustin Pop
  """Compute instance run-time status.
1071 a8083063 Iustin Pop
1072 7232c04c Iustin Pop
  @param opts: the command line options selected by the user
1073 7232c04c Iustin Pop
  @type args: list
1074 7232c04c Iustin Pop
  @param args: either an empty list, and then we query all
1075 7232c04c Iustin Pop
      instances, or should contain a list of instance names
1076 7232c04c Iustin Pop
  @rtype: int
1077 7232c04c Iustin Pop
  @return: the desired exit code
1078 7232c04c Iustin Pop
1079 a8083063 Iustin Pop
  """
1080 220cde0b Guido Trotter
  if not args and not opts.show_all:
1081 220cde0b Guido Trotter
    ToStderr("No instance selected."
1082 220cde0b Guido Trotter
             " Please pass in --all if you want to query all instances.\n"
1083 220cde0b Guido Trotter
             "Note that this can take a long time on a big cluster.")
1084 220cde0b Guido Trotter
    return 1
1085 220cde0b Guido Trotter
  elif args and opts.show_all:
1086 220cde0b Guido Trotter
    ToStderr("Cannot use --all if you specify instance names.")
1087 220cde0b Guido Trotter
    return 1
1088 220cde0b Guido Trotter
1089 a8083063 Iustin Pop
  retcode = 0
1090 57821cac Iustin Pop
  op = opcodes.OpQueryInstanceData(instances=args, static=opts.static)
1091 a8083063 Iustin Pop
  result = SubmitOpCode(op)
1092 a8083063 Iustin Pop
  if not result:
1093 3a24c527 Iustin Pop
    ToStdout("No instances.")
1094 a8083063 Iustin Pop
    return 1
1095 a8083063 Iustin Pop
1096 a8083063 Iustin Pop
  buf = StringIO()
1097 a8083063 Iustin Pop
  retcode = 0
1098 a8083063 Iustin Pop
  for instance_name in result:
1099 a8083063 Iustin Pop
    instance = result[instance_name]
1100 a8083063 Iustin Pop
    buf.write("Instance name: %s\n" % instance["name"])
1101 033d58b0 Iustin Pop
    buf.write("UUID: %s\n" % instance["uuid"])
1102 90f72445 Iustin Pop
    buf.write("Serial number: %s\n" % instance["serial_no"])
1103 90f72445 Iustin Pop
    buf.write("Creation time: %s\n" % utils.FormatTime(instance["ctime"]))
1104 90f72445 Iustin Pop
    buf.write("Modification time: %s\n" % utils.FormatTime(instance["mtime"]))
1105 57821cac Iustin Pop
    buf.write("State: configured to be %s" % instance["config_state"])
1106 57821cac Iustin Pop
    if not opts.static:
1107 57821cac Iustin Pop
      buf.write(", actual state is %s" % instance["run_state"])
1108 57821cac Iustin Pop
    buf.write("\n")
1109 57821cac Iustin Pop
    ##buf.write("Considered for memory checks in cluster verify: %s\n" %
1110 57821cac Iustin Pop
    ##          instance["auto_balance"])
1111 a8083063 Iustin Pop
    buf.write("  Nodes:\n")
1112 a8083063 Iustin Pop
    buf.write("    - primary: %s\n" % instance["pnode"])
1113 a8083063 Iustin Pop
    buf.write("    - secondaries: %s\n" % ", ".join(instance["snodes"]))
1114 a8083063 Iustin Pop
    buf.write("  Operating system: %s\n" % instance["os"])
1115 a8340917 Iustin Pop
    if instance.has_key("network_port"):
1116 a8340917 Iustin Pop
      buf.write("  Allocated network port: %s\n" % instance["network_port"])
1117 24838135 Iustin Pop
    buf.write("  Hypervisor: %s\n" % instance["hypervisor"])
1118 dfff41f8 Guido Trotter
1119 dfff41f8 Guido Trotter
    # custom VNC console information
1120 dfff41f8 Guido Trotter
    vnc_bind_address = instance["hv_actual"].get(constants.HV_VNC_BIND_ADDRESS,
1121 dfff41f8 Guido Trotter
                                                 None)
1122 dfff41f8 Guido Trotter
    if vnc_bind_address:
1123 dfff41f8 Guido Trotter
      port = instance["network_port"]
1124 dfff41f8 Guido Trotter
      display = int(port) - constants.VNC_BASE_PORT
1125 dfff41f8 Guido Trotter
      if display > 0 and vnc_bind_address == constants.BIND_ADDRESS_GLOBAL:
1126 dfff41f8 Guido Trotter
        vnc_console_port = "%s:%s (display %s)" % (instance["pnode"],
1127 dfff41f8 Guido Trotter
                                                   port,
1128 dfff41f8 Guido Trotter
                                                   display)
1129 dfff41f8 Guido Trotter
      elif display > 0 and utils.IsValidIP(vnc_bind_address):
1130 dfff41f8 Guido Trotter
        vnc_console_port = ("%s:%s (node %s) (display %s)" %
1131 dfff41f8 Guido Trotter
                             (vnc_bind_address, port,
1132 dfff41f8 Guido Trotter
                              instance["pnode"], display))
1133 a8340917 Iustin Pop
      else:
1134 dfff41f8 Guido Trotter
        # vnc bind address is a file
1135 dfff41f8 Guido Trotter
        vnc_console_port = "%s:%s" % (instance["pnode"],
1136 dfff41f8 Guido Trotter
                                      vnc_bind_address)
1137 24838135 Iustin Pop
      buf.write("    - console connection: vnc to %s\n" % vnc_console_port)
1138 24838135 Iustin Pop
1139 dfff41f8 Guido Trotter
    for key in instance["hv_actual"]:
1140 24838135 Iustin Pop
      if key in instance["hv_instance"]:
1141 24838135 Iustin Pop
        val = instance["hv_instance"][key]
1142 a8340917 Iustin Pop
      else:
1143 24838135 Iustin Pop
        val = "default (%s)" % instance["hv_actual"][key]
1144 dfff41f8 Guido Trotter
      buf.write("    - %s: %s\n" % (key, val))
1145 a8083063 Iustin Pop
    buf.write("  Hardware:\n")
1146 338e51e8 Iustin Pop
    buf.write("    - VCPUs: %d\n" %
1147 338e51e8 Iustin Pop
              instance["be_actual"][constants.BE_VCPUS])
1148 338e51e8 Iustin Pop
    buf.write("    - memory: %dMiB\n" %
1149 338e51e8 Iustin Pop
              instance["be_actual"][constants.BE_MEMORY])
1150 d2acfe27 Iustin Pop
    buf.write("    - NICs:\n")
1151 14ea9302 Guido Trotter
    for idx, (ip, mac, mode, link) in enumerate(instance["nics"]):
1152 0b13832c Guido Trotter
      buf.write("      - nic/%d: MAC: %s, IP: %s, mode: %s, link: %s\n" %
1153 0b13832c Guido Trotter
                (idx, mac, ip, mode, link))
1154 19708787 Iustin Pop
    buf.write("  Disks:\n")
1155 a8083063 Iustin Pop
1156 19708787 Iustin Pop
    for idx, device in enumerate(instance["disks"]):
1157 19708787 Iustin Pop
      _FormatList(buf, _FormatBlockDevInfo(idx, True, device, opts.static), 2)
1158 a8083063 Iustin Pop
1159 3a24c527 Iustin Pop
  ToStdout(buf.getvalue().rstrip('\n'))
1160 a8083063 Iustin Pop
  return retcode
1161 a8083063 Iustin Pop
1162 a8083063 Iustin Pop
1163 7767bbf5 Manuel Franceschini
def SetInstanceParams(opts, args):
1164 a8083063 Iustin Pop
  """Modifies an instance.
1165 a8083063 Iustin Pop
1166 a8083063 Iustin Pop
  All parameters take effect only at the next restart of the instance.
1167 a8083063 Iustin Pop
1168 7232c04c Iustin Pop
  @param opts: the command line options selected by the user
1169 7232c04c Iustin Pop
  @type args: list
1170 7232c04c Iustin Pop
  @param args: should contain only one element, the instance name
1171 7232c04c Iustin Pop
  @rtype: int
1172 7232c04c Iustin Pop
  @return: the desired exit code
1173 a8083063 Iustin Pop
1174 a8083063 Iustin Pop
  """
1175 24991749 Iustin Pop
  if not (opts.nics or opts.disks or
1176 48f212d7 Iustin Pop
          opts.hvparams or opts.beparams):
1177 3a24c527 Iustin Pop
    ToStderr("Please give at least one of the parameters.")
1178 a8083063 Iustin Pop
    return 1
1179 a8083063 Iustin Pop
1180 467ae11e Guido Trotter
  for param in opts.beparams:
1181 e9d622bc Guido Trotter
    if isinstance(opts.beparams[param], basestring):
1182 e9d622bc Guido Trotter
      if opts.beparams[param].lower() == "default":
1183 e9d622bc Guido Trotter
        opts.beparams[param] = constants.VALUE_DEFAULT
1184 a5728081 Guido Trotter
1185 a5728081 Guido Trotter
  utils.ForceDictType(opts.beparams, constants.BES_PARAMETER_TYPES,
1186 a5728081 Guido Trotter
                      allowed_values=[constants.VALUE_DEFAULT])
1187 467ae11e Guido Trotter
1188 48f212d7 Iustin Pop
  for param in opts.hvparams:
1189 48f212d7 Iustin Pop
    if isinstance(opts.hvparams[param], basestring):
1190 48f212d7 Iustin Pop
      if opts.hvparams[param].lower() == "default":
1191 48f212d7 Iustin Pop
        opts.hvparams[param] = constants.VALUE_DEFAULT
1192 a5728081 Guido Trotter
1193 48f212d7 Iustin Pop
  utils.ForceDictType(opts.hvparams, constants.HVS_PARAMETER_TYPES,
1194 a5728081 Guido Trotter
                      allowed_values=[constants.VALUE_DEFAULT])
1195 61be6ba4 Iustin Pop
1196 24991749 Iustin Pop
  for idx, (nic_op, nic_dict) in enumerate(opts.nics):
1197 24991749 Iustin Pop
    try:
1198 24991749 Iustin Pop
      nic_op = int(nic_op)
1199 24991749 Iustin Pop
      opts.nics[idx] = (nic_op, nic_dict)
1200 24991749 Iustin Pop
    except ValueError:
1201 24991749 Iustin Pop
      pass
1202 24991749 Iustin Pop
1203 24991749 Iustin Pop
  for idx, (disk_op, disk_dict) in enumerate(opts.disks):
1204 24991749 Iustin Pop
    try:
1205 24991749 Iustin Pop
      disk_op = int(disk_op)
1206 24991749 Iustin Pop
      opts.disks[idx] = (disk_op, disk_dict)
1207 24991749 Iustin Pop
    except ValueError:
1208 24991749 Iustin Pop
      pass
1209 24991749 Iustin Pop
    if disk_op == constants.DDM_ADD:
1210 24991749 Iustin Pop
      if 'size' not in disk_dict:
1211 24991749 Iustin Pop
        raise errors.OpPrereqError("Missing required parameter 'size'")
1212 24991749 Iustin Pop
      disk_dict['size'] = utils.ParseUnit(disk_dict['size'])
1213 24991749 Iustin Pop
1214 338e51e8 Iustin Pop
  op = opcodes.OpSetInstanceParams(instance_name=args[0],
1215 24991749 Iustin Pop
                                   nics=opts.nics,
1216 24991749 Iustin Pop
                                   disks=opts.disks,
1217 48f212d7 Iustin Pop
                                   hvparams=opts.hvparams,
1218 338e51e8 Iustin Pop
                                   beparams=opts.beparams,
1219 4300c4b6 Guido Trotter
                                   force=opts.force)
1220 31a853d2 Iustin Pop
1221 6340bb0a Iustin Pop
  # even if here we process the result, we allow submit only
1222 6340bb0a Iustin Pop
  result = SubmitOrSend(op, opts)
1223 a8083063 Iustin Pop
1224 a8083063 Iustin Pop
  if result:
1225 3a24c527 Iustin Pop
    ToStdout("Modified instance %s", args[0])
1226 a8083063 Iustin Pop
    for param, data in result:
1227 3a24c527 Iustin Pop
      ToStdout(" - %-5s -> %s", param, data)
1228 3a24c527 Iustin Pop
    ToStdout("Please don't forget that these parameters take effect"
1229 3a24c527 Iustin Pop
             " only at the next start of the instance.")
1230 a8083063 Iustin Pop
  return 0
1231 a8083063 Iustin Pop
1232 a8083063 Iustin Pop
1233 312ac745 Iustin Pop
# multi-instance selection options
1234 c38c44ad Michael Hanselmann
m_force_multi = cli_option("--force-multiple", dest="force_multi",
1235 c38c44ad Michael Hanselmann
                           help="Do not ask for confirmation when more than"
1236 c38c44ad Michael Hanselmann
                           " one instance is affected",
1237 c38c44ad Michael Hanselmann
                           action="store_true", default=False)
1238 804a1e8e Iustin Pop
1239 c38c44ad Michael Hanselmann
m_pri_node_opt = cli_option("--primary", dest="multi_mode",
1240 c38c44ad Michael Hanselmann
                            help="Filter by nodes (primary only)",
1241 c38c44ad Michael Hanselmann
                            const=_SHUTDOWN_NODES_PRI, action="store_const")
1242 312ac745 Iustin Pop
1243 c38c44ad Michael Hanselmann
m_sec_node_opt = cli_option("--secondary", dest="multi_mode",
1244 c38c44ad Michael Hanselmann
                            help="Filter by nodes (secondary only)",
1245 c38c44ad Michael Hanselmann
                            const=_SHUTDOWN_NODES_SEC, action="store_const")
1246 312ac745 Iustin Pop
1247 c38c44ad Michael Hanselmann
m_node_opt = cli_option("--node", dest="multi_mode",
1248 c38c44ad Michael Hanselmann
                        help="Filter by nodes (primary and secondary)",
1249 c38c44ad Michael Hanselmann
                        const=_SHUTDOWN_NODES_BOTH, action="store_const")
1250 312ac745 Iustin Pop
1251 c38c44ad Michael Hanselmann
m_clust_opt = cli_option("--all", dest="multi_mode",
1252 c38c44ad Michael Hanselmann
                         help="Select all instances in the cluster",
1253 c38c44ad Michael Hanselmann
                         const=_SHUTDOWN_CLUSTER, action="store_const")
1254 312ac745 Iustin Pop
1255 c38c44ad Michael Hanselmann
m_inst_opt = cli_option("--instance", dest="multi_mode",
1256 c38c44ad Michael Hanselmann
                        help="Filter by instance name [default]",
1257 c38c44ad Michael Hanselmann
                        const=_SHUTDOWN_INSTANCES, action="store_const")
1258 312ac745 Iustin Pop
1259 312ac745 Iustin Pop
1260 a8083063 Iustin Pop
# this is defined separately due to readability only
1261 a8083063 Iustin Pop
add_opts = [
1262 087ed2ed Iustin Pop
  BACKEND_OPT,
1263 e3876ccb Iustin Pop
  DISK_OPT,
1264 064c21f8 Iustin Pop
  DISK_TEMPLATE_OPT,
1265 4a25828c Iustin Pop
  FILESTORE_DIR_OPT,
1266 0f87c43e Iustin Pop
  FILESTORE_DRIVER_OPT,
1267 236fd9c4 Iustin Pop
  HYPERVISOR_OPT,
1268 064c21f8 Iustin Pop
  IALLOCATOR_OPT,
1269 064c21f8 Iustin Pop
  NET_OPT,
1270 064c21f8 Iustin Pop
  NODE_PLACEMENT_OPT,
1271 064c21f8 Iustin Pop
  NOIPCHECK_OPT,
1272 064c21f8 Iustin Pop
  NONICS_OPT,
1273 064c21f8 Iustin Pop
  NOSTART_OPT,
1274 064c21f8 Iustin Pop
  NWSYNC_OPT,
1275 064c21f8 Iustin Pop
  OS_OPT,
1276 06073e85 Guido Trotter
  FORCE_VARIANT_OPT,
1277 064c21f8 Iustin Pop
  OS_SIZE_OPT,
1278 6340bb0a Iustin Pop
  SUBMIT_OPT,
1279 a8083063 Iustin Pop
  ]
1280 a8083063 Iustin Pop
1281 a8083063 Iustin Pop
commands = {
1282 6ea815cf Iustin Pop
  'add': (
1283 6ea815cf Iustin Pop
    AddInstance, [ArgHost(min=1, max=1)], add_opts,
1284 6ea815cf Iustin Pop
    "[...] -t disk-type -n node[:secondary-node] -o os-type <name>",
1285 6ea815cf Iustin Pop
    "Creates and adds a new instance to the cluster"),
1286 6ea815cf Iustin Pop
  'batch-create': (
1287 064c21f8 Iustin Pop
    BatchCreate, [ArgFile(min=1, max=1)], [],
1288 6ea815cf Iustin Pop
    "<instances.json>",
1289 6ea815cf Iustin Pop
    "Create a bunch of instances based on specs in the file."),
1290 6ea815cf Iustin Pop
  'console': (
1291 6ea815cf Iustin Pop
    ConnectToInstanceConsole, ARGS_ONE_INSTANCE,
1292 064c21f8 Iustin Pop
    [SHOWCMD_OPT],
1293 6ea815cf Iustin Pop
    "[--show-cmd] <instance>", "Opens a console on the specified instance"),
1294 6ea815cf Iustin Pop
  'failover': (
1295 6ea815cf Iustin Pop
    FailoverInstance, ARGS_ONE_INSTANCE,
1296 17c3f802 Guido Trotter
    [FORCE_OPT, IGNORE_CONSIST_OPT, SUBMIT_OPT, SHUTDOWN_TIMEOUT_OPT],
1297 6ea815cf Iustin Pop
    "[-f] <instance>", "Stops the instance and starts it on the backup node,"
1298 6ea815cf Iustin Pop
    " using the remote mirror (only for instances of type drbd)"),
1299 6ea815cf Iustin Pop
  'migrate': (
1300 6ea815cf Iustin Pop
    MigrateInstance, ARGS_ONE_INSTANCE,
1301 064c21f8 Iustin Pop
    [FORCE_OPT, NONLIVE_OPT, CLEANUP_OPT],
1302 6ea815cf Iustin Pop
    "[-f] <instance>", "Migrate instance to its secondary node"
1303 6ea815cf Iustin Pop
    " (only for instances of type drbd)"),
1304 6ea815cf Iustin Pop
  'move': (
1305 6ea815cf Iustin Pop
    MoveInstance, ARGS_ONE_INSTANCE,
1306 17c3f802 Guido Trotter
    [FORCE_OPT, SUBMIT_OPT, SINGLE_NODE_OPT, SHUTDOWN_TIMEOUT_OPT],
1307 6ea815cf Iustin Pop
    "[-f] <instance>", "Move instance to an arbitrary node"
1308 6ea815cf Iustin Pop
    " (only for instances of type file and lv)"),
1309 6ea815cf Iustin Pop
  'info': (
1310 6ea815cf Iustin Pop
    ShowInstanceConfig, ARGS_MANY_INSTANCES,
1311 064c21f8 Iustin Pop
    [STATIC_OPT, ALL_OPT],
1312 6ea815cf Iustin Pop
    "[-s] {--all | <instance>...}",
1313 6ea815cf Iustin Pop
    "Show information on the specified instance(s)"),
1314 6ea815cf Iustin Pop
  'list': (
1315 6ea815cf Iustin Pop
    ListInstances, ARGS_MANY_INSTANCES,
1316 064c21f8 Iustin Pop
    [NOHDR_OPT, SEP_OPT, USEUNITS_OPT, FIELDS_OPT, SYNC_OPT],
1317 6ea815cf Iustin Pop
    "[<instance>...]",
1318 6ea815cf Iustin Pop
    "Lists the instances and their status. The available fields are"
1319 6ea815cf Iustin Pop
    " (see the man page for details): status, oper_state, oper_ram,"
1320 6ea815cf Iustin Pop
    " name, os, pnode, snodes, admin_state, admin_ram, disk_template,"
1321 6ea815cf Iustin Pop
    " ip, mac, mode, link, sda_size, sdb_size, vcpus, serial_no,"
1322 6ea815cf Iustin Pop
    " hypervisor."
1323 6ea815cf Iustin Pop
    " The default field"
1324 6ea815cf Iustin Pop
    " list is (in order): %s." % ", ".join(_LIST_DEF_FIELDS),
1325 6ea815cf Iustin Pop
    ),
1326 6ea815cf Iustin Pop
  'reinstall': (
1327 3e54ace7 Iustin Pop
    ReinstallInstance, [ArgInstance()],
1328 06073e85 Guido Trotter
    [FORCE_OPT, OS_OPT, FORCE_VARIANT_OPT, m_force_multi, m_node_opt,
1329 06073e85 Guido Trotter
     m_pri_node_opt, m_sec_node_opt, m_clust_opt, m_inst_opt, SELECT_OS_OPT,
1330 06073e85 Guido Trotter
     SUBMIT_OPT],
1331 6ea815cf Iustin Pop
    "[-f] <instance>", "Reinstall a stopped instance"),
1332 6ea815cf Iustin Pop
  'remove': (
1333 6ea815cf Iustin Pop
    RemoveInstance, ARGS_ONE_INSTANCE,
1334 17c3f802 Guido Trotter
    [FORCE_OPT, SHUTDOWN_TIMEOUT_OPT, IGNORE_FAILURES_OPT, SUBMIT_OPT],
1335 6ea815cf Iustin Pop
    "[-f] <instance>", "Shuts down the instance and removes it"),
1336 6ea815cf Iustin Pop
  'rename': (
1337 6ea815cf Iustin Pop
    RenameInstance,
1338 6ea815cf Iustin Pop
    [ArgInstance(min=1, max=1), ArgHost(min=1, max=1)],
1339 064c21f8 Iustin Pop
    [NOIPCHECK_OPT, SUBMIT_OPT],
1340 6ea815cf Iustin Pop
    "<instance> <new_name>", "Rename the instance"),
1341 6ea815cf Iustin Pop
  'replace-disks': (
1342 6ea815cf Iustin Pop
    ReplaceDisks, ARGS_ONE_INSTANCE,
1343 064c21f8 Iustin Pop
    [AUTO_REPLACE_OPT, DISKIDX_OPT, IALLOCATOR_OPT,
1344 6ea815cf Iustin Pop
     NEW_SECONDARY_OPT, ON_PRIMARY_OPT, ON_SECONDARY_OPT, SUBMIT_OPT],
1345 6ea815cf Iustin Pop
    "[-s|-p|-n NODE|-I NAME] <instance>",
1346 6ea815cf Iustin Pop
    "Replaces all disks for the instance"),
1347 6ea815cf Iustin Pop
  'modify': (
1348 6ea815cf Iustin Pop
    SetInstanceParams, ARGS_ONE_INSTANCE,
1349 064c21f8 Iustin Pop
    [BACKEND_OPT, DISK_OPT, FORCE_OPT, HVOPTS_OPT, NET_OPT, SUBMIT_OPT],
1350 6ea815cf Iustin Pop
    "<instance>", "Alters the parameters of an instance"),
1351 6ea815cf Iustin Pop
  'shutdown': (
1352 1c5945b6 Iustin Pop
    GenericManyOps("shutdown", _ShutdownInstance), [ArgInstance()],
1353 064c21f8 Iustin Pop
    [m_node_opt, m_pri_node_opt, m_sec_node_opt, m_clust_opt,
1354 6263189c Guido Trotter
     m_inst_opt, m_force_multi, TIMEOUT_OPT, SUBMIT_OPT],
1355 6ea815cf Iustin Pop
    "<instance>", "Stops an instance"),
1356 6ea815cf Iustin Pop
  'startup': (
1357 1c5945b6 Iustin Pop
    GenericManyOps("startup", _StartupInstance), [ArgInstance()],
1358 064c21f8 Iustin Pop
    [FORCE_OPT, m_force_multi, m_node_opt, m_pri_node_opt,
1359 6ea815cf Iustin Pop
     m_sec_node_opt, m_clust_opt, m_inst_opt, SUBMIT_OPT, HVOPTS_OPT,
1360 6ea815cf Iustin Pop
     BACKEND_OPT],
1361 6ea815cf Iustin Pop
    "<instance>", "Starts an instance"),
1362 6ea815cf Iustin Pop
  'reboot': (
1363 1c5945b6 Iustin Pop
    GenericManyOps("reboot", _RebootInstance), [ArgInstance()],
1364 064c21f8 Iustin Pop
    [m_force_multi, REBOOT_TYPE_OPT, IGNORE_SECONDARIES_OPT, m_node_opt,
1365 17c3f802 Guido Trotter
     m_pri_node_opt, m_sec_node_opt, m_clust_opt, m_inst_opt, SUBMIT_OPT,
1366 17c3f802 Guido Trotter
     SHUTDOWN_TIMEOUT_OPT],
1367 6ea815cf Iustin Pop
    "<instance>", "Reboots an instance"),
1368 6ea815cf Iustin Pop
  'activate-disks': (
1369 064c21f8 Iustin Pop
    ActivateDisks, ARGS_ONE_INSTANCE, [SUBMIT_OPT, IGNORE_SIZE_OPT],
1370 6ea815cf Iustin Pop
    "<instance>", "Activate an instance's disks"),
1371 6ea815cf Iustin Pop
  'deactivate-disks': (
1372 064c21f8 Iustin Pop
    DeactivateDisks, ARGS_ONE_INSTANCE, [SUBMIT_OPT],
1373 6ea815cf Iustin Pop
    "<instance>", "Deactivate an instance's disks"),
1374 6ea815cf Iustin Pop
  'recreate-disks': (
1375 064c21f8 Iustin Pop
    RecreateDisks, ARGS_ONE_INSTANCE, [SUBMIT_OPT, DISKIDX_OPT],
1376 6ea815cf Iustin Pop
    "<instance>", "Recreate an instance's disks"),
1377 6ea815cf Iustin Pop
  'grow-disk': (
1378 6ea815cf Iustin Pop
    GrowDisk,
1379 6ea815cf Iustin Pop
    [ArgInstance(min=1, max=1), ArgUnknown(min=1, max=1),
1380 6ea815cf Iustin Pop
     ArgUnknown(min=1, max=1)],
1381 064c21f8 Iustin Pop
    [SUBMIT_OPT, NWSYNC_OPT],
1382 6ea815cf Iustin Pop
    "<instance> <disk> <size>", "Grow an instance's disk"),
1383 6ea815cf Iustin Pop
  'list-tags': (
1384 064c21f8 Iustin Pop
    ListTags, ARGS_ONE_INSTANCE, [],
1385 6ea815cf Iustin Pop
    "<instance_name>", "List the tags of the given instance"),
1386 6ea815cf Iustin Pop
  'add-tags': (
1387 6ea815cf Iustin Pop
    AddTags, [ArgInstance(min=1, max=1), ArgUnknown()],
1388 064c21f8 Iustin Pop
    [TAG_SRC_OPT],
1389 6ea815cf Iustin Pop
    "<instance_name> tag...", "Add tags to the given instance"),
1390 6ea815cf Iustin Pop
  'remove-tags': (
1391 6ea815cf Iustin Pop
    RemoveTags, [ArgInstance(min=1, max=1), ArgUnknown()],
1392 064c21f8 Iustin Pop
    [TAG_SRC_OPT],
1393 6ea815cf Iustin Pop
    "<instance_name> tag...", "Remove tags from given instance"),
1394 a8083063 Iustin Pop
  }
1395 a8083063 Iustin Pop
1396 7232c04c Iustin Pop
#: dictionary with aliases for commands
1397 dbfd89dd Guido Trotter
aliases = {
1398 dbfd89dd Guido Trotter
  'activate_block_devs': 'activate-disks',
1399 00ce8b29 Guido Trotter
  'replace_disks': 'replace-disks',
1400 536fda25 Guido Trotter
  'start': 'startup',
1401 536fda25 Guido Trotter
  'stop': 'shutdown',
1402 dbfd89dd Guido Trotter
  }
1403 dbfd89dd Guido Trotter
1404 a8005e17 Michael Hanselmann
1405 a8083063 Iustin Pop
if __name__ == '__main__':
1406 dbfd89dd Guido Trotter
  sys.exit(GenericMain(commands, aliases=aliases,
1407 846baef9 Iustin Pop
                       override={"tag_type": constants.TAG_INSTANCE}))