Statistics
| Branch: | Tag: | Revision:

root / scripts / gnt-instance @ 9939547b

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