Statistics
| Branch: | Tag: | Revision:

root / scripts / gnt-instance @ 24991749

History | View | Annotate | Download (47.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 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 08db7c5c Iustin Pop
  else:
306 08db7c5c Iustin Pop
    # default of one nic, all auto
307 08db7c5c Iustin Pop
    nics = [{}]
308 08db7c5c Iustin Pop
309 08db7c5c Iustin Pop
  if not opts.disks and opts.disk_template != constants.DT_DISKLESS:
310 08db7c5c Iustin Pop
    raise errors.OpPrereqError("No disk information specified")
311 08db7c5c Iustin Pop
  elif opts.disks and opts.disk_template == constants.DT_DISKLESS:
312 08db7c5c Iustin Pop
    raise errors.OpPrereqError("Diskless instance but disk information passeD")
313 08db7c5c Iustin Pop
  else:
314 08db7c5c Iustin Pop
    try:
315 08db7c5c Iustin Pop
      disk_max = max(int(didx[0])+1 for didx in opts.disks)
316 08db7c5c Iustin Pop
    except ValueError, err:
317 08db7c5c Iustin Pop
      raise errors.OpPrereqError("Invalid disk index passed: %s" % str(err))
318 08db7c5c Iustin Pop
    disks = [{}] * disk_max
319 08db7c5c Iustin Pop
    for didx, ddict in opts.disks:
320 08db7c5c Iustin Pop
      didx = int(didx)
321 08db7c5c Iustin Pop
      if "size" not in ddict:
322 08db7c5c Iustin Pop
        raise errors.OpPrereqError("Missing size for disk %d" % didx)
323 08db7c5c Iustin Pop
      try:
324 08db7c5c Iustin Pop
        ddict["size"] = utils.ParseUnit(ddict["size"])
325 08db7c5c Iustin Pop
      except ValueError, err:
326 08db7c5c Iustin Pop
        raise errors.OpPrereqError("Invalid disk size for disk %d: %s" %
327 08db7c5c Iustin Pop
                                   (didx, err))
328 08db7c5c Iustin Pop
      disks[didx] = ddict
329 08db7c5c Iustin Pop
330 7399cd55 Guido Trotter
  ValidateBeParams(opts.beparams)
331 338e51e8 Iustin Pop
332 6785674e Iustin Pop
##  kernel_path = _TransformPath(opts.kernel_path)
333 6785674e Iustin Pop
##  initrd_path = _TransformPath(opts.initrd_path)
334 31a853d2 Iustin Pop
335 6785674e Iustin Pop
##  hvm_acpi = opts.hvm_acpi == _VALUE_TRUE
336 6785674e Iustin Pop
##  hvm_pae = opts.hvm_pae == _VALUE_TRUE
337 6785674e Iustin Pop
338 6785674e Iustin Pop
##  if ((opts.hvm_cdrom_image_path is not None) and
339 6785674e Iustin Pop
##      (opts.hvm_cdrom_image_path.lower() == constants.VALUE_NONE)):
340 6785674e Iustin Pop
##    hvm_cdrom_image_path = None
341 6785674e Iustin Pop
##  else:
342 6785674e Iustin Pop
##    hvm_cdrom_image_path = opts.hvm_cdrom_image_path
343 31a853d2 Iustin Pop
344 338e51e8 Iustin Pop
  op = opcodes.OpCreateInstance(instance_name=instance,
345 08db7c5c Iustin Pop
                                disks=disks,
346 a8083063 Iustin Pop
                                disk_template=opts.disk_template,
347 08db7c5c Iustin Pop
                                nics=nics,
348 a8083063 Iustin Pop
                                mode=constants.INSTANCE_CREATE,
349 60d49723 Michael Hanselmann
                                os_type=opts.os, pnode=pnode,
350 338e51e8 Iustin Pop
                                snode=snode,
351 bdd55f71 Iustin Pop
                                start=opts.start, ip_check=opts.ip_check,
352 3b6d8c9b Iustin Pop
                                wait_for_sync=opts.wait_for_sync,
353 6785674e Iustin Pop
                                hypervisor=hypervisor,
354 6785674e Iustin Pop
                                hvparams=hvparams,
355 338e51e8 Iustin Pop
                                beparams=opts.beparams,
356 31a853d2 Iustin Pop
                                iallocator=opts.iallocator,
357 35a0d128 Iustin Pop
                                file_storage_dir=opts.file_storage_dir,
358 35a0d128 Iustin Pop
                                file_driver=opts.file_driver,
359 6785674e Iustin Pop
                                )
360 31a853d2 Iustin Pop
361 6340bb0a Iustin Pop
  SubmitOrSend(op, opts)
362 a8083063 Iustin Pop
  return 0
363 a8083063 Iustin Pop
364 a8083063 Iustin Pop
365 0d0e9090 René Nussbaumer
def BatchCreate(opts, args):
366 7232c04c Iustin Pop
  """Create instances using a definition file.
367 7232c04c Iustin Pop
368 7232c04c Iustin Pop
  This function reads a json file with instances defined
369 7232c04c Iustin Pop
  in the form::
370 7232c04c Iustin Pop
371 7232c04c Iustin Pop
    {"instance-name":{
372 7232c04c Iustin Pop
      "disk_size": 25,
373 7232c04c Iustin Pop
      "swap_size": 1024,
374 7232c04c Iustin Pop
      "template": "drbd",
375 7232c04c Iustin Pop
      "backend": {
376 7232c04c Iustin Pop
        "memory": 512,
377 7232c04c Iustin Pop
        "vcpus": 1 },
378 7232c04c Iustin Pop
      "os": "etch-image",
379 7232c04c Iustin Pop
      "primary_node": "firstnode",
380 7232c04c Iustin Pop
      "secondary_node": "secondnode",
381 7232c04c Iustin Pop
      "iallocator": "dumb"}
382 7232c04c Iustin Pop
    }
383 7232c04c Iustin Pop
384 7232c04c Iustin Pop
  Note that I{primary_node} and I{secondary_node} have precedence over
385 7232c04c Iustin Pop
  I{iallocator}.
386 7232c04c Iustin Pop
387 7232c04c Iustin Pop
  @param opts: the command line options selected by the user
388 7232c04c Iustin Pop
  @type args: list
389 7232c04c Iustin Pop
  @param args: should contain one element, the json filename
390 7232c04c Iustin Pop
  @rtype: int
391 7232c04c Iustin Pop
  @return: the desired exit code
392 0d0e9090 René Nussbaumer
393 0d0e9090 René Nussbaumer
  """
394 0d0e9090 René Nussbaumer
  _DEFAULT_SPECS = {"disk_size": 20 * 1024,
395 0d0e9090 René Nussbaumer
                    "swap_size": 4 * 1024,
396 0d0e9090 René Nussbaumer
                    "backend": {},
397 0d0e9090 René Nussbaumer
                    "iallocator": None,
398 0d0e9090 René Nussbaumer
                    "primary_node": None,
399 0d0e9090 René Nussbaumer
                    "secondary_node": None,
400 0d0e9090 René Nussbaumer
                    "ip": 'none',
401 0d0e9090 René Nussbaumer
                    "mac": 'auto',
402 0d0e9090 René Nussbaumer
                    "bridge": None,
403 0d0e9090 René Nussbaumer
                    "start": True,
404 0d0e9090 René Nussbaumer
                    "ip_check": True,
405 0d0e9090 René Nussbaumer
                    "hypervisor": None,
406 0d0e9090 René Nussbaumer
                    "file_storage_dir": None,
407 0d0e9090 René Nussbaumer
                    "file_driver": 'loop'}
408 0d0e9090 René Nussbaumer
409 0d0e9090 René Nussbaumer
  def _PopulateWithDefaults(spec):
410 0d0e9090 René Nussbaumer
    """Returns a new hash combined with default values."""
411 2f79bd34 Iustin Pop
    mydict = _DEFAULT_SPECS.copy()
412 2f79bd34 Iustin Pop
    mydict.update(spec)
413 2f79bd34 Iustin Pop
    return mydict
414 0d0e9090 René Nussbaumer
415 0d0e9090 René Nussbaumer
  def _Validate(spec):
416 0d0e9090 René Nussbaumer
    """Validate the instance specs."""
417 0d0e9090 René Nussbaumer
    # Validate fields required under any circumstances
418 0d0e9090 René Nussbaumer
    for required_field in ('os', 'template'):
419 0d0e9090 René Nussbaumer
      if required_field not in spec:
420 0d0e9090 René Nussbaumer
        raise errors.OpPrereqError('Required field "%s" is missing.' %
421 0d0e9090 René Nussbaumer
                                   required_field)
422 0d0e9090 René Nussbaumer
    # Validate special fields
423 0d0e9090 René Nussbaumer
    if spec['primary_node'] is not None:
424 0d0e9090 René Nussbaumer
      if (spec['template'] in constants.DTS_NET_MIRROR and
425 0d0e9090 René Nussbaumer
          spec['secondary_node'] is None):
426 0d0e9090 René Nussbaumer
        raise errors.OpPrereqError('Template requires secondary node, but'
427 0d0e9090 René Nussbaumer
                                   ' there was no secondary provided.')
428 0d0e9090 René Nussbaumer
    elif spec['iallocator'] is None:
429 0d0e9090 René Nussbaumer
      raise errors.OpPrereqError('You have to provide at least a primary_node'
430 0d0e9090 René Nussbaumer
                                 ' or an iallocator.')
431 0d0e9090 René Nussbaumer
432 0d0e9090 René Nussbaumer
    if (spec['hypervisor'] and
433 0d0e9090 René Nussbaumer
        not isinstance(spec['hypervisor'], dict)):
434 0d0e9090 René Nussbaumer
      raise errors.OpPrereqError('Hypervisor parameters must be a dict.')
435 0d0e9090 René Nussbaumer
436 0d0e9090 René Nussbaumer
  json_filename = args[0]
437 0d0e9090 René Nussbaumer
  fd = open(json_filename, 'r')
438 0d0e9090 René Nussbaumer
  try:
439 0d0e9090 René Nussbaumer
    instance_data = simplejson.load(fd)
440 0d0e9090 René Nussbaumer
  finally:
441 0d0e9090 René Nussbaumer
    fd.close()
442 0d0e9090 René Nussbaumer
443 0d0e9090 René Nussbaumer
  # Iterate over the instances and do:
444 0d0e9090 René Nussbaumer
  #  * Populate the specs with default value
445 0d0e9090 René Nussbaumer
  #  * Validate the instance specs
446 0d0e9090 René Nussbaumer
  for (name, specs) in instance_data.iteritems():
447 0d0e9090 René Nussbaumer
    specs = _PopulateWithDefaults(specs)
448 0d0e9090 René Nussbaumer
    _Validate(specs)
449 0d0e9090 René Nussbaumer
450 0d0e9090 René Nussbaumer
    hypervisor = None
451 0d0e9090 René Nussbaumer
    hvparams = {}
452 0d0e9090 René Nussbaumer
    if specs['hypervisor']:
453 0d0e9090 René Nussbaumer
      hypervisor, hvparams = specs['hypervisor'].iteritems()
454 0d0e9090 René Nussbaumer
455 0d0e9090 René Nussbaumer
    op = opcodes.OpCreateInstance(instance_name=name,
456 0d0e9090 René Nussbaumer
                                  disk_size=specs['disk_size'],
457 0d0e9090 René Nussbaumer
                                  swap_size=specs['swap_size'],
458 0d0e9090 René Nussbaumer
                                  disk_template=specs['template'],
459 0d0e9090 René Nussbaumer
                                  mode=constants.INSTANCE_CREATE,
460 0d0e9090 René Nussbaumer
                                  os_type=specs['os'],
461 0d0e9090 René Nussbaumer
                                  pnode=specs['primary_node'],
462 0d0e9090 René Nussbaumer
                                  snode=specs['secondary_node'],
463 0d0e9090 René Nussbaumer
                                  ip=specs['ip'], bridge=specs['bridge'],
464 0d0e9090 René Nussbaumer
                                  start=specs['start'],
465 0d0e9090 René Nussbaumer
                                  ip_check=specs['ip_check'],
466 0d0e9090 René Nussbaumer
                                  wait_for_sync=True,
467 0d0e9090 René Nussbaumer
                                  mac=specs['mac'],
468 0d0e9090 René Nussbaumer
                                  iallocator=specs['iallocator'],
469 0d0e9090 René Nussbaumer
                                  hypervisor=hypervisor,
470 0d0e9090 René Nussbaumer
                                  hvparams=hvparams,
471 0d0e9090 René Nussbaumer
                                  beparams=specs['backend'],
472 0d0e9090 René Nussbaumer
                                  file_storage_dir=specs['file_storage_dir'],
473 0d0e9090 René Nussbaumer
                                  file_driver=specs['file_driver'])
474 0d0e9090 René Nussbaumer
475 3a24c527 Iustin Pop
    ToStdout("%s: %s", name, cli.SendJob([op]))
476 0d0e9090 René Nussbaumer
477 0d0e9090 René Nussbaumer
  return 0
478 0d0e9090 René Nussbaumer
479 0d0e9090 René Nussbaumer
480 fe7b0351 Michael Hanselmann
def ReinstallInstance(opts, args):
481 fe7b0351 Michael Hanselmann
  """Reinstall an instance.
482 fe7b0351 Michael Hanselmann
483 7232c04c Iustin Pop
  @param opts: the command line options selected by the user
484 7232c04c Iustin Pop
  @type args: list
485 7232c04c Iustin Pop
  @param args: should contain only one element, the name of the
486 7232c04c Iustin Pop
      instance to be reinstalled
487 7232c04c Iustin Pop
  @rtype: int
488 7232c04c Iustin Pop
  @return: the desired exit code
489 fe7b0351 Michael Hanselmann
490 fe7b0351 Michael Hanselmann
  """
491 fe7b0351 Michael Hanselmann
  instance_name = args[0]
492 fe7b0351 Michael Hanselmann
493 20e23543 Alexander Schreiber
  if opts.select_os is True:
494 20e23543 Alexander Schreiber
    op = opcodes.OpDiagnoseOS(output_fields=["name", "valid"], names=[])
495 20e23543 Alexander Schreiber
    result = SubmitOpCode(op)
496 20e23543 Alexander Schreiber
497 20e23543 Alexander Schreiber
    if not result:
498 3a24c527 Iustin Pop
      ToStdout("Can't get the OS list")
499 20e23543 Alexander Schreiber
      return 1
500 20e23543 Alexander Schreiber
501 3a24c527 Iustin Pop
    ToStdout("Available OS templates:")
502 20e23543 Alexander Schreiber
    number = 0
503 20e23543 Alexander Schreiber
    choices = []
504 20e23543 Alexander Schreiber
    for entry in result:
505 3a24c527 Iustin Pop
      ToStdout("%3s: %s", number, entry[0])
506 20e23543 Alexander Schreiber
      choices.append(("%s" % number, entry[0], entry[0]))
507 20e23543 Alexander Schreiber
      number = number + 1
508 20e23543 Alexander Schreiber
509 20e23543 Alexander Schreiber
    choices.append(('x', 'exit', 'Exit gnt-instance reinstall'))
510 20e23543 Alexander Schreiber
    selected = AskUser("Enter OS template name or number (or x to abort):",
511 20e23543 Alexander Schreiber
                       choices)
512 20e23543 Alexander Schreiber
513 20e23543 Alexander Schreiber
    if selected == 'exit':
514 3a24c527 Iustin Pop
      ToStdout("User aborted reinstall, exiting")
515 20e23543 Alexander Schreiber
      return 1
516 20e23543 Alexander Schreiber
517 2f79bd34 Iustin Pop
    os_name = selected
518 20e23543 Alexander Schreiber
  else:
519 2f79bd34 Iustin Pop
    os_name = opts.os
520 20e23543 Alexander Schreiber
521 fe7b0351 Michael Hanselmann
  if not opts.force:
522 f4bc1f2c Michael Hanselmann
    usertext = ("This will reinstall the instance %s and remove"
523 f4bc1f2c Michael Hanselmann
                " all data. Continue?") % instance_name
524 47988778 Iustin Pop
    if not AskUser(usertext):
525 fe7b0351 Michael Hanselmann
      return 1
526 fe7b0351 Michael Hanselmann
527 d0834de3 Michael Hanselmann
  op = opcodes.OpReinstallInstance(instance_name=instance_name,
528 2f79bd34 Iustin Pop
                                   os_type=os_name)
529 6340bb0a Iustin Pop
  SubmitOrSend(op, opts)
530 fe7b0351 Michael Hanselmann
531 fe7b0351 Michael Hanselmann
  return 0
532 fe7b0351 Michael Hanselmann
533 fe7b0351 Michael Hanselmann
534 a8083063 Iustin Pop
def RemoveInstance(opts, args):
535 a8083063 Iustin Pop
  """Remove an instance.
536 a8083063 Iustin Pop
537 7232c04c Iustin Pop
  @param opts: the command line options selected by the user
538 7232c04c Iustin Pop
  @type args: list
539 7232c04c Iustin Pop
  @param args: should contain only one element, the name of
540 7232c04c Iustin Pop
      the instance to be removed
541 7232c04c Iustin Pop
  @rtype: int
542 7232c04c Iustin Pop
  @return: the desired exit code
543 a8083063 Iustin Pop
544 a8083063 Iustin Pop
  """
545 a8083063 Iustin Pop
  instance_name = args[0]
546 a8083063 Iustin Pop
  force = opts.force
547 a8083063 Iustin Pop
548 a8083063 Iustin Pop
  if not force:
549 a8083063 Iustin Pop
    usertext = ("This will remove the volumes of the instance %s"
550 a8083063 Iustin Pop
                " (including mirrors), thus removing all the data"
551 a8083063 Iustin Pop
                " of the instance. Continue?") % instance_name
552 47988778 Iustin Pop
    if not AskUser(usertext):
553 a8083063 Iustin Pop
      return 1
554 a8083063 Iustin Pop
555 1d67656e Iustin Pop
  op = opcodes.OpRemoveInstance(instance_name=instance_name,
556 1d67656e Iustin Pop
                                ignore_failures=opts.ignore_failures)
557 6340bb0a Iustin Pop
  SubmitOrSend(op, opts)
558 a8083063 Iustin Pop
  return 0
559 a8083063 Iustin Pop
560 a8083063 Iustin Pop
561 decd5f45 Iustin Pop
def RenameInstance(opts, args):
562 4ab0b9e3 Guido Trotter
  """Rename an instance.
563 decd5f45 Iustin Pop
564 7232c04c Iustin Pop
  @param opts: the command line options selected by the user
565 7232c04c Iustin Pop
  @type args: list
566 7232c04c Iustin Pop
  @param args: should contain two elements, the old and the
567 7232c04c Iustin Pop
      new instance names
568 7232c04c Iustin Pop
  @rtype: int
569 7232c04c Iustin Pop
  @return: the desired exit code
570 decd5f45 Iustin Pop
571 decd5f45 Iustin Pop
  """
572 decd5f45 Iustin Pop
  op = opcodes.OpRenameInstance(instance_name=args[0],
573 decd5f45 Iustin Pop
                                new_name=args[1],
574 decd5f45 Iustin Pop
                                ignore_ip=opts.ignore_ip)
575 6340bb0a Iustin Pop
  SubmitOrSend(op, opts)
576 decd5f45 Iustin Pop
  return 0
577 decd5f45 Iustin Pop
578 decd5f45 Iustin Pop
579 a8083063 Iustin Pop
def ActivateDisks(opts, args):
580 a8083063 Iustin Pop
  """Activate an instance's disks.
581 a8083063 Iustin Pop
582 a8083063 Iustin Pop
  This serves two purposes:
583 7232c04c Iustin Pop
    - it allows (as long as the instance is not running)
584 7232c04c Iustin Pop
      mounting the disks and modifying them from the node
585 a8083063 Iustin Pop
    - it repairs inactive secondary drbds
586 a8083063 Iustin Pop
587 7232c04c Iustin Pop
  @param opts: the command line options selected by the user
588 7232c04c Iustin Pop
  @type args: list
589 7232c04c Iustin Pop
  @param args: should contain only one element, the instance name
590 7232c04c Iustin Pop
  @rtype: int
591 7232c04c Iustin Pop
  @return: the desired exit code
592 7232c04c Iustin Pop
593 a8083063 Iustin Pop
  """
594 a8083063 Iustin Pop
  instance_name = args[0]
595 a8083063 Iustin Pop
  op = opcodes.OpActivateInstanceDisks(instance_name=instance_name)
596 6340bb0a Iustin Pop
  disks_info = SubmitOrSend(op, opts)
597 a8083063 Iustin Pop
  for host, iname, nname in disks_info:
598 3a24c527 Iustin Pop
    ToStdout("%s:%s:%s", host, iname, nname)
599 a8083063 Iustin Pop
  return 0
600 a8083063 Iustin Pop
601 a8083063 Iustin Pop
602 a8083063 Iustin Pop
def DeactivateDisks(opts, args):
603 7232c04c Iustin Pop
  """Deactivate an instance's disks..
604 a8083063 Iustin Pop
605 a8083063 Iustin Pop
  This function takes the instance name, looks for its primary node
606 a8083063 Iustin Pop
  and the tries to shutdown its block devices on that node.
607 a8083063 Iustin Pop
608 7232c04c Iustin Pop
  @param opts: the command line options selected by the user
609 7232c04c Iustin Pop
  @type args: list
610 7232c04c Iustin Pop
  @param args: should contain only one element, the instance name
611 7232c04c Iustin Pop
  @rtype: int
612 7232c04c Iustin Pop
  @return: the desired exit code
613 7232c04c Iustin Pop
614 a8083063 Iustin Pop
  """
615 a8083063 Iustin Pop
  instance_name = args[0]
616 a8083063 Iustin Pop
  op = opcodes.OpDeactivateInstanceDisks(instance_name=instance_name)
617 6340bb0a Iustin Pop
  SubmitOrSend(op, opts)
618 a8083063 Iustin Pop
  return 0
619 a8083063 Iustin Pop
620 a8083063 Iustin Pop
621 c6e911bc Iustin Pop
def GrowDisk(opts, args):
622 7232c04c Iustin Pop
  """Grow an instance's disks.
623 c6e911bc Iustin Pop
624 7232c04c Iustin Pop
  @param opts: the command line options selected by the user
625 7232c04c Iustin Pop
  @type args: list
626 7232c04c Iustin Pop
  @param args: should contain two elements, the instance name
627 7232c04c Iustin Pop
      whose disks we grow and the disk name, e.g. I{sda}
628 7232c04c Iustin Pop
  @rtype: int
629 7232c04c Iustin Pop
  @return: the desired exit code
630 c6e911bc Iustin Pop
631 c6e911bc Iustin Pop
  """
632 c6e911bc Iustin Pop
  instance = args[0]
633 c6e911bc Iustin Pop
  disk = args[1]
634 ad24e046 Iustin Pop
  try:
635 ad24e046 Iustin Pop
    disk = int(disk)
636 ad24e046 Iustin Pop
  except ValueError, err:
637 ad24e046 Iustin Pop
    raise errors.OpPrereqError("Invalid disk index: %s" % str(err))
638 c6e911bc Iustin Pop
  amount = utils.ParseUnit(args[2])
639 6605411d Iustin Pop
  op = opcodes.OpGrowDisk(instance_name=instance, disk=disk, amount=amount,
640 6605411d Iustin Pop
                          wait_for_sync=opts.wait_for_sync)
641 6340bb0a Iustin Pop
  SubmitOrSend(op, opts)
642 c6e911bc Iustin Pop
  return 0
643 c6e911bc Iustin Pop
644 c6e911bc Iustin Pop
645 a8083063 Iustin Pop
def StartupInstance(opts, args):
646 7232c04c Iustin Pop
  """Startup instances.
647 a8083063 Iustin Pop
648 7232c04c Iustin Pop
  Depending on the options given, this will start one or more
649 7232c04c Iustin Pop
  instances.
650 7232c04c Iustin Pop
651 7232c04c Iustin Pop
  @param opts: the command line options selected by the user
652 7232c04c Iustin Pop
  @type args: list
653 7232c04c Iustin Pop
  @param args: the instance or node names based on which we
654 7232c04c Iustin Pop
      create the final selection (in conjunction with the
655 7232c04c Iustin Pop
      opts argument)
656 7232c04c Iustin Pop
  @rtype: int
657 7232c04c Iustin Pop
  @return: the desired exit code
658 a8083063 Iustin Pop
659 a8083063 Iustin Pop
  """
660 312ac745 Iustin Pop
  if opts.multi_mode is None:
661 312ac745 Iustin Pop
    opts.multi_mode = _SHUTDOWN_INSTANCES
662 312ac745 Iustin Pop
  inames = _ExpandMultiNames(opts.multi_mode, args)
663 bcee9cb4 Iustin Pop
  if not inames:
664 bcee9cb4 Iustin Pop
    raise errors.OpPrereqError("Selection filter does not match any instances")
665 804a1e8e Iustin Pop
  multi_on = opts.multi_mode != _SHUTDOWN_INSTANCES or len(inames) > 1
666 804a1e8e Iustin Pop
  if not (opts.force_multi or not multi_on
667 804a1e8e Iustin Pop
          or _ConfirmOperation(inames, "startup")):
668 804a1e8e Iustin Pop
    return 1
669 312ac745 Iustin Pop
  for name in inames:
670 312ac745 Iustin Pop
    op = opcodes.OpStartupInstance(instance_name=name,
671 312ac745 Iustin Pop
                                   force=opts.force,
672 312ac745 Iustin Pop
                                   extra_args=opts.extra_args)
673 312ac745 Iustin Pop
    if multi_on:
674 3a24c527 Iustin Pop
      ToStdout("Starting up %s", name)
675 aefef4f4 Iustin Pop
    try:
676 aefef4f4 Iustin Pop
      SubmitOrSend(op, opts)
677 aefef4f4 Iustin Pop
    except JobSubmittedException, err:
678 aefef4f4 Iustin Pop
      _, txt = FormatError(err)
679 3a24c527 Iustin Pop
      ToStdout("%s", txt)
680 a8083063 Iustin Pop
  return 0
681 a8083063 Iustin Pop
682 7c0d6283 Michael Hanselmann
683 579d4337 Alexander Schreiber
def RebootInstance(opts, args):
684 7232c04c Iustin Pop
  """Reboot instance(s).
685 7232c04c Iustin Pop
686 7232c04c Iustin Pop
  Depending on the parameters given, this will reboot one or more
687 7232c04c Iustin Pop
  instances.
688 579d4337 Alexander Schreiber
689 7232c04c Iustin Pop
  @param opts: the command line options selected by the user
690 7232c04c Iustin Pop
  @type args: list
691 7232c04c Iustin Pop
  @param args: the instance or node names based on which we
692 7232c04c Iustin Pop
      create the final selection (in conjunction with the
693 7232c04c Iustin Pop
      opts argument)
694 7232c04c Iustin Pop
  @rtype: int
695 7232c04c Iustin Pop
  @return: the desired exit code
696 579d4337 Alexander Schreiber
697 579d4337 Alexander Schreiber
  """
698 579d4337 Alexander Schreiber
  if opts.multi_mode is None:
699 579d4337 Alexander Schreiber
    opts.multi_mode = _SHUTDOWN_INSTANCES
700 579d4337 Alexander Schreiber
  inames = _ExpandMultiNames(opts.multi_mode, args)
701 bcee9cb4 Iustin Pop
  if not inames:
702 bcee9cb4 Iustin Pop
    raise errors.OpPrereqError("Selection filter does not match any instances")
703 579d4337 Alexander Schreiber
  multi_on = opts.multi_mode != _SHUTDOWN_INSTANCES or len(inames) > 1
704 579d4337 Alexander Schreiber
  if not (opts.force_multi or not multi_on
705 579d4337 Alexander Schreiber
          or _ConfirmOperation(inames, "reboot")):
706 579d4337 Alexander Schreiber
    return 1
707 579d4337 Alexander Schreiber
  for name in inames:
708 579d4337 Alexander Schreiber
    op = opcodes.OpRebootInstance(instance_name=name,
709 579d4337 Alexander Schreiber
                                  reboot_type=opts.reboot_type,
710 579d4337 Alexander Schreiber
                                  ignore_secondaries=opts.ignore_secondaries)
711 579d4337 Alexander Schreiber
712 6340bb0a Iustin Pop
    SubmitOrSend(op, opts)
713 579d4337 Alexander Schreiber
  return 0
714 a8083063 Iustin Pop
715 7c0d6283 Michael Hanselmann
716 a8083063 Iustin Pop
def ShutdownInstance(opts, args):
717 a8083063 Iustin Pop
  """Shutdown an instance.
718 a8083063 Iustin Pop
719 7232c04c Iustin Pop
  @param opts: the command line options selected by the user
720 7232c04c Iustin Pop
  @type args: list
721 7232c04c Iustin Pop
  @param args: the instance or node names based on which we
722 7232c04c Iustin Pop
      create the final selection (in conjunction with the
723 7232c04c Iustin Pop
      opts argument)
724 7232c04c Iustin Pop
  @rtype: int
725 7232c04c Iustin Pop
  @return: the desired exit code
726 a8083063 Iustin Pop
727 a8083063 Iustin Pop
  """
728 312ac745 Iustin Pop
  if opts.multi_mode is None:
729 312ac745 Iustin Pop
    opts.multi_mode = _SHUTDOWN_INSTANCES
730 312ac745 Iustin Pop
  inames = _ExpandMultiNames(opts.multi_mode, args)
731 bcee9cb4 Iustin Pop
  if not inames:
732 bcee9cb4 Iustin Pop
    raise errors.OpPrereqError("Selection filter does not match any instances")
733 804a1e8e Iustin Pop
  multi_on = opts.multi_mode != _SHUTDOWN_INSTANCES or len(inames) > 1
734 804a1e8e Iustin Pop
  if not (opts.force_multi or not multi_on
735 804a1e8e Iustin Pop
          or _ConfirmOperation(inames, "shutdown")):
736 804a1e8e Iustin Pop
    return 1
737 312ac745 Iustin Pop
  for name in inames:
738 312ac745 Iustin Pop
    op = opcodes.OpShutdownInstance(instance_name=name)
739 312ac745 Iustin Pop
    if multi_on:
740 3a24c527 Iustin Pop
      ToStdout("Shutting down %s", name)
741 aefef4f4 Iustin Pop
    try:
742 aefef4f4 Iustin Pop
      SubmitOrSend(op, opts)
743 aefef4f4 Iustin Pop
    except JobSubmittedException, err:
744 aefef4f4 Iustin Pop
      _, txt = FormatError(err)
745 3a24c527 Iustin Pop
      ToStdout("%s", txt)
746 a8083063 Iustin Pop
  return 0
747 a8083063 Iustin Pop
748 a8083063 Iustin Pop
749 a8083063 Iustin Pop
def ReplaceDisks(opts, args):
750 a8083063 Iustin Pop
  """Replace the disks of an instance
751 a8083063 Iustin Pop
752 7232c04c Iustin Pop
  @param opts: the command line options selected by the user
753 7232c04c Iustin Pop
  @type args: list
754 7232c04c Iustin Pop
  @param args: should contain only one element, the instance name
755 7232c04c Iustin Pop
  @rtype: int
756 7232c04c Iustin Pop
  @return: the desired exit code
757 a8083063 Iustin Pop
758 a8083063 Iustin Pop
  """
759 a8083063 Iustin Pop
  instance_name = args[0]
760 a9e0c397 Iustin Pop
  new_2ndary = opts.new_secondary
761 b6e82a65 Iustin Pop
  iallocator = opts.iallocator
762 a9e0c397 Iustin Pop
  if opts.disks is None:
763 54155f52 Iustin Pop
    disks = []
764 a9e0c397 Iustin Pop
  else:
765 54155f52 Iustin Pop
    try:
766 54155f52 Iustin Pop
      disks = [int(i) for i in opts.disks.split(",")]
767 54155f52 Iustin Pop
    except ValueError, err:
768 54155f52 Iustin Pop
      raise errors.OpPrereqError("Invalid disk index passed: %s" % str(err))
769 a9e0c397 Iustin Pop
  if opts.on_primary == opts.on_secondary: # no -p or -s passed, or both passed
770 a9e0c397 Iustin Pop
    mode = constants.REPLACE_DISK_ALL
771 a9e0c397 Iustin Pop
  elif opts.on_primary: # only on primary:
772 a9e0c397 Iustin Pop
    mode = constants.REPLACE_DISK_PRI
773 b6e82a65 Iustin Pop
    if new_2ndary is not None or iallocator is not None:
774 a9e0c397 Iustin Pop
      raise errors.OpPrereqError("Can't change secondary node on primary disk"
775 a9e0c397 Iustin Pop
                                 " replacement")
776 b6e82a65 Iustin Pop
  elif opts.on_secondary is not None or iallocator is not None:
777 b6e82a65 Iustin Pop
    # only on secondary
778 a9e0c397 Iustin Pop
    mode = constants.REPLACE_DISK_SEC
779 a9e0c397 Iustin Pop
780 a9e0c397 Iustin Pop
  op = opcodes.OpReplaceDisks(instance_name=args[0], disks=disks,
781 b6e82a65 Iustin Pop
                              remote_node=new_2ndary, mode=mode,
782 b6e82a65 Iustin Pop
                              iallocator=iallocator)
783 6340bb0a Iustin Pop
  SubmitOrSend(op, opts)
784 a8083063 Iustin Pop
  return 0
785 a8083063 Iustin Pop
786 a8083063 Iustin Pop
787 a8083063 Iustin Pop
def FailoverInstance(opts, args):
788 a8083063 Iustin Pop
  """Failover an instance.
789 a8083063 Iustin Pop
790 a8083063 Iustin Pop
  The failover is done by shutting it down on its present node and
791 a8083063 Iustin Pop
  starting it on the secondary.
792 a8083063 Iustin Pop
793 7232c04c Iustin Pop
  @param opts: the command line options selected by the user
794 7232c04c Iustin Pop
  @type args: list
795 7232c04c Iustin Pop
  @param args: should contain only one element, the instance name
796 7232c04c Iustin Pop
  @rtype: int
797 7232c04c Iustin Pop
  @return: the desired exit code
798 a8083063 Iustin Pop
799 a8083063 Iustin Pop
  """
800 80de0e3f Iustin Pop
  instance_name = args[0]
801 80de0e3f Iustin Pop
  force = opts.force
802 a8083063 Iustin Pop
803 80de0e3f Iustin Pop
  if not force:
804 80de0e3f Iustin Pop
    usertext = ("Failover will happen to image %s."
805 80de0e3f Iustin Pop
                " This requires a shutdown of the instance. Continue?" %
806 80de0e3f Iustin Pop
                (instance_name,))
807 80de0e3f Iustin Pop
    if not AskUser(usertext):
808 80de0e3f Iustin Pop
      return 1
809 a8083063 Iustin Pop
810 80de0e3f Iustin Pop
  op = opcodes.OpFailoverInstance(instance_name=instance_name,
811 80de0e3f Iustin Pop
                                  ignore_consistency=opts.ignore_consistency)
812 6340bb0a Iustin Pop
  SubmitOrSend(op, opts)
813 80de0e3f Iustin Pop
  return 0
814 a8083063 Iustin Pop
815 a8083063 Iustin Pop
816 a8083063 Iustin Pop
def ConnectToInstanceConsole(opts, args):
817 a8083063 Iustin Pop
  """Connect to the console of an instance.
818 a8083063 Iustin Pop
819 7232c04c Iustin Pop
  @param opts: the command line options selected by the user
820 7232c04c Iustin Pop
  @type args: list
821 7232c04c Iustin Pop
  @param args: should contain only one element, the instance name
822 7232c04c Iustin Pop
  @rtype: int
823 7232c04c Iustin Pop
  @return: the desired exit code
824 a8083063 Iustin Pop
825 a8083063 Iustin Pop
  """
826 a8083063 Iustin Pop
  instance_name = args[0]
827 a8083063 Iustin Pop
828 a8083063 Iustin Pop
  op = opcodes.OpConnectConsole(instance_name=instance_name)
829 0a80a26f Michael Hanselmann
  cmd = SubmitOpCode(op)
830 51c6e7b5 Michael Hanselmann
831 51c6e7b5 Michael Hanselmann
  if opts.show_command:
832 3a24c527 Iustin Pop
    ToStdout("%s", utils.ShellQuoteArgs(cmd))
833 51c6e7b5 Michael Hanselmann
  else:
834 51c6e7b5 Michael Hanselmann
    try:
835 51c6e7b5 Michael Hanselmann
      os.execvp(cmd[0], cmd)
836 51c6e7b5 Michael Hanselmann
    finally:
837 3a24c527 Iustin Pop
      ToStderr("Can't run console command %s with arguments:\n'%s'",
838 2f79bd34 Iustin Pop
               cmd[0], " ".join(cmd))
839 51c6e7b5 Michael Hanselmann
      os._exit(1)
840 a8083063 Iustin Pop
841 a8083063 Iustin Pop
842 57821cac Iustin Pop
def _FormatBlockDevInfo(buf, dev, indent_level, static):
843 a8083063 Iustin Pop
  """Show block device information.
844 a8083063 Iustin Pop
845 7232c04c Iustin Pop
  This is only used by L{ShowInstanceConfig}, but it's too big to be
846 a8083063 Iustin Pop
  left for an inline definition.
847 a8083063 Iustin Pop
848 7232c04c Iustin Pop
  @type buf: StringIO
849 7232c04c Iustin Pop
  @param buf: buffer that will accumulate the output
850 7232c04c Iustin Pop
  @type dev: dict
851 7232c04c Iustin Pop
  @param dev: dictionary with disk information
852 7232c04c Iustin Pop
  @type indent_level: int
853 7232c04c Iustin Pop
  @param indent_level: the indendation level we are at, used for
854 7232c04c Iustin Pop
      the layout of the device tree
855 7232c04c Iustin Pop
  @type static: boolean
856 7232c04c Iustin Pop
  @param static: wheter the device information doesn't contain
857 7232c04c Iustin Pop
      runtime information but only static data
858 7232c04c Iustin Pop
859 a8083063 Iustin Pop
  """
860 a8083063 Iustin Pop
  def helper(buf, dtype, status):
861 7232c04c Iustin Pop
    """Format one line for physical device status.
862 7232c04c Iustin Pop
863 7232c04c Iustin Pop
    @type buf: StringIO
864 7232c04c Iustin Pop
    @param buf: buffer that will accumulate the output
865 7232c04c Iustin Pop
    @type dtype: str
866 7232c04c Iustin Pop
    @param dtype: a constant from the L{constants.LDS_BLOCK} set
867 7232c04c Iustin Pop
    @type status: tuple
868 7232c04c Iustin Pop
    @param status: a tuple as returned from L{backend.FindBlockDevice}
869 7232c04c Iustin Pop
870 7232c04c Iustin Pop
    """
871 a8083063 Iustin Pop
    if not status:
872 a8083063 Iustin Pop
      buf.write("not active\n")
873 a8083063 Iustin Pop
    else:
874 0834c866 Iustin Pop
      (path, major, minor, syncp, estt, degr, ldisk) = status
875 fd38ef95 Manuel Franceschini
      if major is None:
876 fd38ef95 Manuel Franceschini
        major_string = "N/A"
877 fd38ef95 Manuel Franceschini
      else:
878 fd38ef95 Manuel Franceschini
        major_string = str(major)
879 fd38ef95 Manuel Franceschini
880 fd38ef95 Manuel Franceschini
      if minor is None:
881 fd38ef95 Manuel Franceschini
        minor_string = "N/A"
882 fd38ef95 Manuel Franceschini
      else:
883 fd38ef95 Manuel Franceschini
        minor_string = str(minor)
884 fd38ef95 Manuel Franceschini
885 fd38ef95 Manuel Franceschini
      buf.write("%s (%s:%s)" % (path, major_string, minor_string))
886 00fb8246 Michael Hanselmann
      if dtype in (constants.LD_DRBD8, ):
887 a8083063 Iustin Pop
        if syncp is not None:
888 a8083063 Iustin Pop
          sync_text = "*RECOVERING* %5.2f%%," % syncp
889 a8083063 Iustin Pop
          if estt:
890 a8083063 Iustin Pop
            sync_text += " ETA %ds" % estt
891 a8083063 Iustin Pop
          else:
892 a8083063 Iustin Pop
            sync_text += " ETA unknown"
893 a8083063 Iustin Pop
        else:
894 a8083063 Iustin Pop
          sync_text = "in sync"
895 a8083063 Iustin Pop
        if degr:
896 a8083063 Iustin Pop
          degr_text = "*DEGRADED*"
897 a8083063 Iustin Pop
        else:
898 a8083063 Iustin Pop
          degr_text = "ok"
899 0834c866 Iustin Pop
        if ldisk:
900 0834c866 Iustin Pop
          ldisk_text = " *MISSING DISK*"
901 0834c866 Iustin Pop
        else:
902 0834c866 Iustin Pop
          ldisk_text = ""
903 0834c866 Iustin Pop
        buf.write(" %s, status %s%s" % (sync_text, degr_text, ldisk_text))
904 9db6dbce Iustin Pop
      elif dtype == constants.LD_LV:
905 0834c866 Iustin Pop
        if ldisk:
906 0834c866 Iustin Pop
          ldisk_text = " *FAILED* (failed drive?)"
907 9db6dbce Iustin Pop
        else:
908 0834c866 Iustin Pop
          ldisk_text = ""
909 0834c866 Iustin Pop
        buf.write(ldisk_text)
910 a8083063 Iustin Pop
      buf.write("\n")
911 a8083063 Iustin Pop
912 a8083063 Iustin Pop
  if dev["iv_name"] is not None:
913 a8083063 Iustin Pop
    data = "  - %s, " % dev["iv_name"]
914 a8083063 Iustin Pop
  else:
915 a8083063 Iustin Pop
    data = "  - "
916 b6fdf8b8 Iustin Pop
  data += "access mode: %s, " % dev["mode"]
917 a8083063 Iustin Pop
  data += "type: %s" % dev["dev_type"]
918 a8083063 Iustin Pop
  if dev["logical_id"] is not None:
919 a8083063 Iustin Pop
    data += ", logical_id: %s" % (dev["logical_id"],)
920 a8083063 Iustin Pop
  elif dev["physical_id"] is not None:
921 a8083063 Iustin Pop
    data += ", physical_id: %s" % (dev["physical_id"],)
922 a8083063 Iustin Pop
  buf.write("%*s%s\n" % (2*indent_level, "", data))
923 57821cac Iustin Pop
  if not static:
924 57821cac Iustin Pop
    buf.write("%*s    primary:   " % (2*indent_level, ""))
925 57821cac Iustin Pop
    helper(buf, dev["dev_type"], dev["pstatus"])
926 a8083063 Iustin Pop
927 57821cac Iustin Pop
  if dev["sstatus"] and not static:
928 a8083063 Iustin Pop
    buf.write("%*s    secondary: " % (2*indent_level, ""))
929 a8083063 Iustin Pop
    helper(buf, dev["dev_type"], dev["sstatus"])
930 a8083063 Iustin Pop
931 a8083063 Iustin Pop
  if dev["children"]:
932 a8083063 Iustin Pop
    for child in dev["children"]:
933 57821cac Iustin Pop
      _FormatBlockDevInfo(buf, child, indent_level+1, static)
934 a8083063 Iustin Pop
935 a8083063 Iustin Pop
936 a8083063 Iustin Pop
def ShowInstanceConfig(opts, args):
937 a8083063 Iustin Pop
  """Compute instance run-time status.
938 a8083063 Iustin Pop
939 7232c04c Iustin Pop
  @param opts: the command line options selected by the user
940 7232c04c Iustin Pop
  @type args: list
941 7232c04c Iustin Pop
  @param args: either an empty list, and then we query all
942 7232c04c Iustin Pop
      instances, or should contain a list of instance names
943 7232c04c Iustin Pop
  @rtype: int
944 7232c04c Iustin Pop
  @return: the desired exit code
945 7232c04c Iustin Pop
946 a8083063 Iustin Pop
  """
947 a8083063 Iustin Pop
  retcode = 0
948 57821cac Iustin Pop
  op = opcodes.OpQueryInstanceData(instances=args, static=opts.static)
949 a8083063 Iustin Pop
  result = SubmitOpCode(op)
950 a8083063 Iustin Pop
  if not result:
951 3a24c527 Iustin Pop
    ToStdout("No instances.")
952 a8083063 Iustin Pop
    return 1
953 a8083063 Iustin Pop
954 a8083063 Iustin Pop
  buf = StringIO()
955 a8083063 Iustin Pop
  retcode = 0
956 a8083063 Iustin Pop
  for instance_name in result:
957 a8083063 Iustin Pop
    instance = result[instance_name]
958 a8083063 Iustin Pop
    buf.write("Instance name: %s\n" % instance["name"])
959 57821cac Iustin Pop
    buf.write("State: configured to be %s" % instance["config_state"])
960 57821cac Iustin Pop
    if not opts.static:
961 57821cac Iustin Pop
      buf.write(", actual state is %s" % instance["run_state"])
962 57821cac Iustin Pop
    buf.write("\n")
963 57821cac Iustin Pop
    ##buf.write("Considered for memory checks in cluster verify: %s\n" %
964 57821cac Iustin Pop
    ##          instance["auto_balance"])
965 a8083063 Iustin Pop
    buf.write("  Nodes:\n")
966 a8083063 Iustin Pop
    buf.write("    - primary: %s\n" % instance["pnode"])
967 a8083063 Iustin Pop
    buf.write("    - secondaries: %s\n" % ", ".join(instance["snodes"]))
968 a8083063 Iustin Pop
    buf.write("  Operating system: %s\n" % instance["os"])
969 a8340917 Iustin Pop
    if instance.has_key("network_port"):
970 a8340917 Iustin Pop
      buf.write("  Allocated network port: %s\n" % instance["network_port"])
971 24838135 Iustin Pop
    buf.write("  Hypervisor: %s\n" % instance["hypervisor"])
972 24838135 Iustin Pop
    if instance["hypervisor"] == constants.HT_XEN_PVM:
973 24838135 Iustin Pop
      hvattrs = ((constants.HV_KERNEL_PATH, "kernel path"),
974 24838135 Iustin Pop
                 (constants.HV_INITRD_PATH, "initrd path"))
975 24838135 Iustin Pop
    elif instance["hypervisor"] == constants.HT_XEN_HVM:
976 24838135 Iustin Pop
      hvattrs = ((constants.HV_BOOT_ORDER, "boot order"),
977 24838135 Iustin Pop
                 (constants.HV_ACPI, "ACPI"),
978 24838135 Iustin Pop
                 (constants.HV_PAE, "PAE"),
979 24838135 Iustin Pop
                 (constants.HV_CDROM_IMAGE_PATH, "virtual CDROM"),
980 24838135 Iustin Pop
                 (constants.HV_NIC_TYPE, "NIC type"),
981 24838135 Iustin Pop
                 (constants.HV_DISK_TYPE, "Disk type"),
982 24838135 Iustin Pop
                 (constants.HV_VNC_BIND_ADDRESS, "VNC bind address"),
983 24838135 Iustin Pop
                 )
984 24838135 Iustin Pop
      # custom console information for HVM
985 24838135 Iustin Pop
      vnc_bind_address = instance["hv_actual"][constants.HV_VNC_BIND_ADDRESS]
986 24838135 Iustin Pop
      if vnc_bind_address == constants.BIND_ADDRESS_GLOBAL:
987 24838135 Iustin Pop
        vnc_console_port = "%s:%s" % (instance["pnode"],
988 24838135 Iustin Pop
                                      instance["network_port"])
989 24838135 Iustin Pop
      elif vnc_bind_address == constants.LOCALHOST_IP_ADDRESS:
990 24838135 Iustin Pop
        vnc_console_port = "%s:%s on node %s" % (vnc_bind_address,
991 24838135 Iustin Pop
                                                 instance["network_port"],
992 24838135 Iustin Pop
                                                 instance["pnode"])
993 a8340917 Iustin Pop
      else:
994 24838135 Iustin Pop
        vnc_console_port = "%s:%s" % (vnc_bind_address,
995 24838135 Iustin Pop
                                      instance["network_port"])
996 24838135 Iustin Pop
      buf.write("    - console connection: vnc to %s\n" % vnc_console_port)
997 24838135 Iustin Pop
998 24838135 Iustin Pop
    else:
999 24838135 Iustin Pop
      # auto-handle other hypervisor types
1000 24838135 Iustin Pop
      hvattrs = [(key, key) for key in instance["hv_actual"]]
1001 24838135 Iustin Pop
1002 24838135 Iustin Pop
    for key, desc in hvattrs:
1003 24838135 Iustin Pop
      if key in instance["hv_instance"]:
1004 24838135 Iustin Pop
        val = instance["hv_instance"][key]
1005 a8340917 Iustin Pop
      else:
1006 24838135 Iustin Pop
        val = "default (%s)" % instance["hv_actual"][key]
1007 24838135 Iustin Pop
      buf.write("    - %s: %s\n" % (desc, val))
1008 a8083063 Iustin Pop
    buf.write("  Hardware:\n")
1009 338e51e8 Iustin Pop
    buf.write("    - VCPUs: %d\n" %
1010 338e51e8 Iustin Pop
              instance["be_actual"][constants.BE_VCPUS])
1011 338e51e8 Iustin Pop
    buf.write("    - memory: %dMiB\n" %
1012 338e51e8 Iustin Pop
              instance["be_actual"][constants.BE_MEMORY])
1013 d2acfe27 Iustin Pop
    buf.write("    - NICs:\n")
1014 d2acfe27 Iustin Pop
    for idx, (mac, ip, bridge) in enumerate(instance["nics"]):
1015 d2acfe27 Iustin Pop
      buf.write("      - nic/%d: MAC: %s, IP: %s, bridge: %s\n" %
1016 d2acfe27 Iustin Pop
                (idx, mac, ip, bridge))
1017 a8083063 Iustin Pop
    buf.write("  Block devices:\n")
1018 a8083063 Iustin Pop
1019 a8083063 Iustin Pop
    for device in instance["disks"]:
1020 57821cac Iustin Pop
      _FormatBlockDevInfo(buf, device, 1, opts.static)
1021 a8083063 Iustin Pop
1022 3a24c527 Iustin Pop
  ToStdout(buf.getvalue().rstrip('\n'))
1023 a8083063 Iustin Pop
  return retcode
1024 a8083063 Iustin Pop
1025 a8083063 Iustin Pop
1026 7767bbf5 Manuel Franceschini
def SetInstanceParams(opts, args):
1027 a8083063 Iustin Pop
  """Modifies an instance.
1028 a8083063 Iustin Pop
1029 a8083063 Iustin Pop
  All parameters take effect only at the next restart of the instance.
1030 a8083063 Iustin Pop
1031 7232c04c Iustin Pop
  @param opts: the command line options selected by the user
1032 7232c04c Iustin Pop
  @type args: list
1033 7232c04c Iustin Pop
  @param args: should contain only one element, the instance name
1034 7232c04c Iustin Pop
  @rtype: int
1035 7232c04c Iustin Pop
  @return: the desired exit code
1036 a8083063 Iustin Pop
1037 a8083063 Iustin Pop
  """
1038 24991749 Iustin Pop
  if not (opts.nics or opts.disks or
1039 61be6ba4 Iustin Pop
          opts.hypervisor or opts.beparams):
1040 3a24c527 Iustin Pop
    ToStderr("Please give at least one of the parameters.")
1041 a8083063 Iustin Pop
    return 1
1042 a8083063 Iustin Pop
1043 61be6ba4 Iustin Pop
  if constants.BE_MEMORY in opts.beparams:
1044 61be6ba4 Iustin Pop
    opts.beparams[constants.BE_MEMORY] = utils.ParseUnit(
1045 61be6ba4 Iustin Pop
      opts.beparams[constants.BE_MEMORY])
1046 61be6ba4 Iustin Pop
1047 24991749 Iustin Pop
  for idx, (nic_op, nic_dict) in enumerate(opts.nics):
1048 24991749 Iustin Pop
    try:
1049 24991749 Iustin Pop
      nic_op = int(nic_op)
1050 24991749 Iustin Pop
      opts.nics[idx] = (nic_op, nic_dict)
1051 24991749 Iustin Pop
    except ValueError:
1052 24991749 Iustin Pop
      pass
1053 24991749 Iustin Pop
1054 24991749 Iustin Pop
  for idx, (disk_op, disk_dict) in enumerate(opts.disks):
1055 24991749 Iustin Pop
    try:
1056 24991749 Iustin Pop
      disk_op = int(disk_op)
1057 24991749 Iustin Pop
      opts.disks[idx] = (disk_op, disk_dict)
1058 24991749 Iustin Pop
    except ValueError:
1059 24991749 Iustin Pop
      pass
1060 24991749 Iustin Pop
    if disk_op == constants.DDM_ADD:
1061 24991749 Iustin Pop
      if 'size' not in disk_dict:
1062 24991749 Iustin Pop
        raise errors.OpPrereqError("Missing required parameter 'size'")
1063 24991749 Iustin Pop
      disk_dict['size'] = utils.ParseUnit(disk_dict['size'])
1064 24991749 Iustin Pop
1065 338e51e8 Iustin Pop
  op = opcodes.OpSetInstanceParams(instance_name=args[0],
1066 24991749 Iustin Pop
                                   nics=opts.nics,
1067 24991749 Iustin Pop
                                   disks=opts.disks,
1068 74409b12 Iustin Pop
                                   hvparams=opts.hypervisor,
1069 338e51e8 Iustin Pop
                                   beparams=opts.beparams,
1070 4300c4b6 Guido Trotter
                                   force=opts.force)
1071 31a853d2 Iustin Pop
1072 6340bb0a Iustin Pop
  # even if here we process the result, we allow submit only
1073 6340bb0a Iustin Pop
  result = SubmitOrSend(op, opts)
1074 a8083063 Iustin Pop
1075 a8083063 Iustin Pop
  if result:
1076 3a24c527 Iustin Pop
    ToStdout("Modified instance %s", args[0])
1077 a8083063 Iustin Pop
    for param, data in result:
1078 3a24c527 Iustin Pop
      ToStdout(" - %-5s -> %s", param, data)
1079 3a24c527 Iustin Pop
    ToStdout("Please don't forget that these parameters take effect"
1080 3a24c527 Iustin Pop
             " only at the next start of the instance.")
1081 a8083063 Iustin Pop
  return 0
1082 a8083063 Iustin Pop
1083 a8083063 Iustin Pop
1084 a8083063 Iustin Pop
# options used in more than one cmd
1085 a8083063 Iustin Pop
node_opt = make_option("-n", "--node", dest="node", help="Target node",
1086 a8083063 Iustin Pop
                       metavar="<node>")
1087 a8083063 Iustin Pop
1088 d0834de3 Michael Hanselmann
os_opt = cli_option("-o", "--os-type", dest="os", help="What OS to run",
1089 739ecd56 Michael Hanselmann
                    metavar="<os>")
1090 d0834de3 Michael Hanselmann
1091 312ac745 Iustin Pop
# multi-instance selection options
1092 804a1e8e Iustin Pop
m_force_multi = make_option("--force-multiple", dest="force_multi",
1093 804a1e8e Iustin Pop
                            help="Do not ask for confirmation when more than"
1094 804a1e8e Iustin Pop
                            " one instance is affected",
1095 804a1e8e Iustin Pop
                            action="store_true", default=False)
1096 804a1e8e Iustin Pop
1097 312ac745 Iustin Pop
m_pri_node_opt = make_option("--primary", dest="multi_mode",
1098 312ac745 Iustin Pop
                             help="Filter by nodes (primary only)",
1099 312ac745 Iustin Pop
                             const=_SHUTDOWN_NODES_PRI, action="store_const")
1100 312ac745 Iustin Pop
1101 312ac745 Iustin Pop
m_sec_node_opt = make_option("--secondary", dest="multi_mode",
1102 312ac745 Iustin Pop
                             help="Filter by nodes (secondary only)",
1103 312ac745 Iustin Pop
                             const=_SHUTDOWN_NODES_SEC, action="store_const")
1104 312ac745 Iustin Pop
1105 312ac745 Iustin Pop
m_node_opt = make_option("--node", dest="multi_mode",
1106 312ac745 Iustin Pop
                         help="Filter by nodes (primary and secondary)",
1107 312ac745 Iustin Pop
                         const=_SHUTDOWN_NODES_BOTH, action="store_const")
1108 312ac745 Iustin Pop
1109 312ac745 Iustin Pop
m_clust_opt = make_option("--all", dest="multi_mode",
1110 312ac745 Iustin Pop
                          help="Select all instances in the cluster",
1111 312ac745 Iustin Pop
                          const=_SHUTDOWN_CLUSTER, action="store_const")
1112 312ac745 Iustin Pop
1113 312ac745 Iustin Pop
m_inst_opt = make_option("--instance", dest="multi_mode",
1114 312ac745 Iustin Pop
                         help="Filter by instance name [default]",
1115 312ac745 Iustin Pop
                         const=_SHUTDOWN_INSTANCES, action="store_const")
1116 312ac745 Iustin Pop
1117 312ac745 Iustin Pop
1118 a8083063 Iustin Pop
# this is defined separately due to readability only
1119 a8083063 Iustin Pop
add_opts = [
1120 a8083063 Iustin Pop
  DEBUG_OPT,
1121 60d49723 Michael Hanselmann
  make_option("-n", "--node", dest="node",
1122 60d49723 Michael Hanselmann
              help="Target node and optional secondary node",
1123 60d49723 Michael Hanselmann
              metavar="<pnode>[:<snode>]"),
1124 b9ac33e9 Iustin Pop
  cli_option("-s", "--os-size", dest="size", help="Disk size, in MiB unless"
1125 b9ac33e9 Iustin Pop
             " a suffix is used",
1126 a8083063 Iustin Pop
             default=20 * 1024, type="unit", metavar="<size>"),
1127 b9ac33e9 Iustin Pop
  cli_option("--swap-size", dest="swap", help="Swap size, in MiB unless a"
1128 b9ac33e9 Iustin Pop
             " suffix is used",
1129 a8083063 Iustin Pop
             default=4 * 1024, type="unit", metavar="<size>"),
1130 d0834de3 Michael Hanselmann
  os_opt,
1131 338e51e8 Iustin Pop
  keyval_option("-B", "--backend", dest="beparams",
1132 338e51e8 Iustin Pop
                type="keyval", default={},
1133 338e51e8 Iustin Pop
                help="Backend parameters"),
1134 a8083063 Iustin Pop
  make_option("-t", "--disk-template", dest="disk_template",
1135 45873083 Manuel Franceschini
              help="Custom disk setup (diskless, file, plain or drbd)",
1136 f9193417 Iustin Pop
              default=None, metavar="TEMPL"),
1137 08db7c5c Iustin Pop
  ikv_option("--disk", help="Disk information",
1138 08db7c5c Iustin Pop
             default=[], dest="disks",
1139 08db7c5c Iustin Pop
             action="append",
1140 08db7c5c Iustin Pop
             type="identkeyval"),
1141 08db7c5c Iustin Pop
  ikv_option("--net", help="NIC information",
1142 08db7c5c Iustin Pop
             default=[], dest="nics",
1143 08db7c5c Iustin Pop
             action="append",
1144 08db7c5c Iustin Pop
             type="identkeyval"),
1145 a8083063 Iustin Pop
  make_option("--no-wait-for-sync", dest="wait_for_sync", default=True,
1146 a8083063 Iustin Pop
              action="store_false", help="Don't wait for sync (DANGEROUS!)"),
1147 bdd55f71 Iustin Pop
  make_option("--no-start", dest="start", default=True,
1148 bdd55f71 Iustin Pop
              action="store_false", help="Don't start the instance after"
1149 bdd55f71 Iustin Pop
              " creation"),
1150 bdd55f71 Iustin Pop
  make_option("--no-ip-check", dest="ip_check", default=True,
1151 bdd55f71 Iustin Pop
              action="store_false", help="Don't check that the instance's IP"
1152 bdd55f71 Iustin Pop
              " is alive (only valid with --no-start)"),
1153 45873083 Manuel Franceschini
  make_option("--file-storage-dir", dest="file_storage_dir",
1154 45873083 Manuel Franceschini
              help="Relative path under default cluster-wide file storage dir"
1155 45873083 Manuel Franceschini
              " to store file-based disks", default=None,
1156 45873083 Manuel Franceschini
              metavar="<DIR>"),
1157 45873083 Manuel Franceschini
  make_option("--file-driver", dest="file_driver", help="Driver to use"
1158 538475ca Iustin Pop
              " for image files", default="loop", metavar="<DRIVER>"),
1159 538475ca Iustin Pop
  make_option("--iallocator", metavar="<NAME>",
1160 538475ca Iustin Pop
              help="Select nodes for the instance automatically using the"
1161 538475ca Iustin Pop
              " <NAME> iallocator plugin", default=None, type="string"),
1162 6785674e Iustin Pop
  ikv_option("-H", "--hypervisor", dest="hypervisor",
1163 6785674e Iustin Pop
              help="Hypervisor and hypervisor options, in the format"
1164 6785674e Iustin Pop
              " hypervisor:option=value,option=value,...", default=None,
1165 6785674e Iustin Pop
              type="identkeyval"),
1166 6340bb0a Iustin Pop
  SUBMIT_OPT,
1167 a8083063 Iustin Pop
  ]
1168 a8083063 Iustin Pop
1169 a8083063 Iustin Pop
commands = {
1170 a8083063 Iustin Pop
  'add': (AddInstance, ARGS_ONE, add_opts,
1171 bdb7d4e8 Michael Hanselmann
          "[...] -t disk-type -n node[:secondary-node] -o os-type <name>",
1172 a8083063 Iustin Pop
          "Creates and adds a new instance to the cluster"),
1173 0d0e9090 René Nussbaumer
  'batch-create': (BatchCreate, ARGS_ONE,
1174 0d0e9090 René Nussbaumer
                   [DEBUG_OPT],
1175 0d0e9090 René Nussbaumer
                   "<instances_file.json>",
1176 0d0e9090 René Nussbaumer
                   "Create a bunch of instances based on specs in the file."),
1177 51c6e7b5 Michael Hanselmann
  'console': (ConnectToInstanceConsole, ARGS_ONE,
1178 51c6e7b5 Michael Hanselmann
              [DEBUG_OPT,
1179 51c6e7b5 Michael Hanselmann
               make_option("--show-cmd", dest="show_command",
1180 51c6e7b5 Michael Hanselmann
                           action="store_true", default=False,
1181 51c6e7b5 Michael Hanselmann
                           help=("Show command instead of executing it"))],
1182 9a033156 Iustin Pop
              "[--show-cmd] <instance>",
1183 a8083063 Iustin Pop
              "Opens a console on the specified instance"),
1184 80de0e3f Iustin Pop
  'failover': (FailoverInstance, ARGS_ONE,
1185 fe7b0351 Michael Hanselmann
               [DEBUG_OPT, FORCE_OPT,
1186 a8083063 Iustin Pop
                make_option("--ignore-consistency", dest="ignore_consistency",
1187 a8083063 Iustin Pop
                            action="store_true", default=False,
1188 a8083063 Iustin Pop
                            help="Ignore the consistency of the disks on"
1189 a8083063 Iustin Pop
                            " the secondary"),
1190 6340bb0a Iustin Pop
                SUBMIT_OPT,
1191 a8083063 Iustin Pop
                ],
1192 9a033156 Iustin Pop
               "[-f] <instance>",
1193 a8083063 Iustin Pop
               "Stops the instance and starts it on the backup node, using"
1194 99e2be3b Guido Trotter
               " the remote mirror (only for instances of type drbd)"),
1195 57821cac Iustin Pop
  'info': (ShowInstanceConfig, ARGS_ANY,
1196 57821cac Iustin Pop
           [DEBUG_OPT,
1197 57821cac Iustin Pop
            make_option("-s", "--static", dest="static",
1198 57821cac Iustin Pop
                        action="store_true", default=False,
1199 57821cac Iustin Pop
                        help="Only show configuration data, not runtime data"),
1200 57821cac Iustin Pop
            ], "[-s] [<instance>...]",
1201 57821cac Iustin Pop
           "Show information on the specified instance(s)"),
1202 a8083063 Iustin Pop
  'list': (ListInstances, ARGS_NONE,
1203 9a033156 Iustin Pop
           [DEBUG_OPT, NOHDR_OPT, SEP_OPT, USEUNITS_OPT, FIELDS_OPT], "",
1204 d8052456 Iustin Pop
           "Lists the instances and their status. The available fields are"
1205 d8052456 Iustin Pop
           " (see the man page for details): status, oper_state, oper_ram,"
1206 d8a4b51d Iustin Pop
           " name, os, pnode, snodes, admin_state, admin_ram, disk_template,"
1207 e69d05fd Iustin Pop
           " ip, mac, bridge, sda_size, sdb_size, vcpus, serial_no,"
1208 e69d05fd Iustin Pop
           " hypervisor."
1209 38d7239a Iustin Pop
           " The default field"
1210 48c4dfa8 Iustin Pop
           " list is (in order): %s." % ", ".join(_LIST_DEF_FIELDS),
1211 48c4dfa8 Iustin Pop
           ),
1212 20e23543 Alexander Schreiber
  'reinstall': (ReinstallInstance, ARGS_ONE,
1213 20e23543 Alexander Schreiber
                [DEBUG_OPT, FORCE_OPT, os_opt,
1214 20e23543 Alexander Schreiber
                 make_option("--select-os", dest="select_os",
1215 20e23543 Alexander Schreiber
                             action="store_true", default=False,
1216 20e23543 Alexander Schreiber
                             help="Interactive OS reinstall, lists available"
1217 6340bb0a Iustin Pop
                             " OS templates for selection"),
1218 6340bb0a Iustin Pop
                 SUBMIT_OPT,
1219 6340bb0a Iustin Pop
                 ],
1220 9a033156 Iustin Pop
                "[-f] <instance>", "Reinstall a stopped instance"),
1221 1d67656e Iustin Pop
  'remove': (RemoveInstance, ARGS_ONE,
1222 1d67656e Iustin Pop
             [DEBUG_OPT, FORCE_OPT,
1223 1d67656e Iustin Pop
              make_option("--ignore-failures", dest="ignore_failures",
1224 1d67656e Iustin Pop
                          action="store_true", default=False,
1225 1d67656e Iustin Pop
                          help=("Remove the instance from the cluster even"
1226 1d67656e Iustin Pop
                                " if there are failures during the removal"
1227 1d67656e Iustin Pop
                                " process (shutdown, disk removal, etc.)")),
1228 6340bb0a Iustin Pop
              SUBMIT_OPT,
1229 1d67656e Iustin Pop
              ],
1230 9a033156 Iustin Pop
             "[-f] <instance>", "Shuts down the instance and removes it"),
1231 decd5f45 Iustin Pop
  'rename': (RenameInstance, ARGS_FIXED(2),
1232 decd5f45 Iustin Pop
             [DEBUG_OPT,
1233 decd5f45 Iustin Pop
              make_option("--no-ip-check", dest="ignore_ip",
1234 decd5f45 Iustin Pop
                          help="Do not check that the IP of the new name"
1235 decd5f45 Iustin Pop
                          " is alive",
1236 decd5f45 Iustin Pop
                          default=False, action="store_true"),
1237 6340bb0a Iustin Pop
              SUBMIT_OPT,
1238 decd5f45 Iustin Pop
              ],
1239 9a033156 Iustin Pop
             "<instance> <new_name>", "Rename the instance"),
1240 a8083063 Iustin Pop
  'replace-disks': (ReplaceDisks, ARGS_ONE,
1241 a8083063 Iustin Pop
                    [DEBUG_OPT,
1242 a8083063 Iustin Pop
                     make_option("-n", "--new-secondary", dest="new_secondary",
1243 a9e0c397 Iustin Pop
                                 help=("New secondary node (for secondary"
1244 a9e0c397 Iustin Pop
                                       " node change)"), metavar="NODE"),
1245 a9e0c397 Iustin Pop
                     make_option("-p", "--on-primary", dest="on_primary",
1246 a9e0c397 Iustin Pop
                                 default=False, action="store_true",
1247 a9e0c397 Iustin Pop
                                 help=("Replace the disk(s) on the primary"
1248 12c3449a Michael Hanselmann
                                       " node (only for the drbd template)")),
1249 a9e0c397 Iustin Pop
                     make_option("-s", "--on-secondary", dest="on_secondary",
1250 a9e0c397 Iustin Pop
                                 default=False, action="store_true",
1251 a9e0c397 Iustin Pop
                                 help=("Replace the disk(s) on the secondary"
1252 12c3449a Michael Hanselmann
                                       " node (only for the drbd template)")),
1253 a9e0c397 Iustin Pop
                     make_option("--disks", dest="disks", default=None,
1254 a9e0c397 Iustin Pop
                                 help=("Comma-separated list of disks"
1255 a9e0c397 Iustin Pop
                                       " to replace (e.g. sda) (optional,"
1256 a9e0c397 Iustin Pop
                                       " defaults to all disks")),
1257 b6e82a65 Iustin Pop
                     make_option("--iallocator", metavar="<NAME>",
1258 b6e82a65 Iustin Pop
                                 help="Select new secondary for the instance"
1259 b6e82a65 Iustin Pop
                                 " automatically using the"
1260 b6e82a65 Iustin Pop
                                 " <NAME> iallocator plugin (enables"
1261 b6e82a65 Iustin Pop
                                 " secondary node replacement)",
1262 b6e82a65 Iustin Pop
                                 default=None, type="string"),
1263 6340bb0a Iustin Pop
                     SUBMIT_OPT,
1264 a9e0c397 Iustin Pop
                     ],
1265 9a033156 Iustin Pop
                    "[-s|-p|-n NODE] <instance>",
1266 a8083063 Iustin Pop
                    "Replaces all disks for the instance"),
1267 7767bbf5 Manuel Franceschini
  'modify': (SetInstanceParams, ARGS_ONE,
1268 fe7b0351 Michael Hanselmann
             [DEBUG_OPT, FORCE_OPT,
1269 74409b12 Iustin Pop
              keyval_option("-H", "--hypervisor", type="keyval",
1270 74409b12 Iustin Pop
                            default={}, dest="hypervisor",
1271 74409b12 Iustin Pop
                            help="Change hypervisor parameters"),
1272 61be6ba4 Iustin Pop
              keyval_option("-B", "--backend", type="keyval",
1273 61be6ba4 Iustin Pop
                            default={}, dest="beparams",
1274 61be6ba4 Iustin Pop
                            help="Change backend parameters"),
1275 24991749 Iustin Pop
              ikv_option("--disk", help="Disk changes",
1276 24991749 Iustin Pop
                         default=[], dest="disks",
1277 24991749 Iustin Pop
                         action="append",
1278 24991749 Iustin Pop
                         type="identkeyval"),
1279 24991749 Iustin Pop
              ikv_option("--net", help="NIC changes",
1280 24991749 Iustin Pop
                         default=[], dest="nics",
1281 24991749 Iustin Pop
                         action="append",
1282 24991749 Iustin Pop
                         type="identkeyval"),
1283 6340bb0a Iustin Pop
              SUBMIT_OPT,
1284 a8083063 Iustin Pop
              ],
1285 9a033156 Iustin Pop
             "<instance>", "Alters the parameters of an instance"),
1286 312ac745 Iustin Pop
  'shutdown': (ShutdownInstance, ARGS_ANY,
1287 312ac745 Iustin Pop
               [DEBUG_OPT, m_node_opt, m_pri_node_opt, m_sec_node_opt,
1288 6340bb0a Iustin Pop
                m_clust_opt, m_inst_opt, m_force_multi,
1289 6340bb0a Iustin Pop
                SUBMIT_OPT,
1290 6340bb0a Iustin Pop
                ],
1291 9a033156 Iustin Pop
               "<instance>", "Stops an instance"),
1292 312ac745 Iustin Pop
  'startup': (StartupInstance, ARGS_ANY,
1293 804a1e8e Iustin Pop
              [DEBUG_OPT, FORCE_OPT, m_force_multi,
1294 a8083063 Iustin Pop
               make_option("-e", "--extra", dest="extra_args",
1295 a8083063 Iustin Pop
                           help="Extra arguments for the instance's kernel",
1296 a8083063 Iustin Pop
                           default=None, type="string", metavar="<PARAMS>"),
1297 312ac745 Iustin Pop
               m_node_opt, m_pri_node_opt, m_sec_node_opt,
1298 312ac745 Iustin Pop
               m_clust_opt, m_inst_opt,
1299 6340bb0a Iustin Pop
               SUBMIT_OPT,
1300 a8083063 Iustin Pop
               ],
1301 9a033156 Iustin Pop
            "<instance>", "Starts an instance"),
1302 579d4337 Alexander Schreiber
1303 579d4337 Alexander Schreiber
  'reboot': (RebootInstance, ARGS_ANY,
1304 579d4337 Alexander Schreiber
              [DEBUG_OPT, m_force_multi,
1305 579d4337 Alexander Schreiber
               make_option("-e", "--extra", dest="extra_args",
1306 579d4337 Alexander Schreiber
                           help="Extra arguments for the instance's kernel",
1307 579d4337 Alexander Schreiber
                           default=None, type="string", metavar="<PARAMS>"),
1308 579d4337 Alexander Schreiber
               make_option("-t", "--type", dest="reboot_type",
1309 579d4337 Alexander Schreiber
                           help="Type of reboot: soft/hard/full",
1310 bf2fd71e Alexander Schreiber
                           default=constants.INSTANCE_REBOOT_HARD,
1311 579d4337 Alexander Schreiber
                           type="string", metavar="<REBOOT>"),
1312 579d4337 Alexander Schreiber
               make_option("--ignore-secondaries", dest="ignore_secondaries",
1313 579d4337 Alexander Schreiber
                           default=False, action="store_true",
1314 579d4337 Alexander Schreiber
                           help="Ignore errors from secondaries"),
1315 579d4337 Alexander Schreiber
               m_node_opt, m_pri_node_opt, m_sec_node_opt,
1316 579d4337 Alexander Schreiber
               m_clust_opt, m_inst_opt,
1317 6340bb0a Iustin Pop
               SUBMIT_OPT,
1318 579d4337 Alexander Schreiber
               ],
1319 9a033156 Iustin Pop
            "<instance>", "Reboots an instance"),
1320 6340bb0a Iustin Pop
  'activate-disks': (ActivateDisks, ARGS_ONE, [DEBUG_OPT, SUBMIT_OPT],
1321 9a033156 Iustin Pop
                     "<instance>",
1322 a8083063 Iustin Pop
                     "Activate an instance's disks"),
1323 6340bb0a Iustin Pop
  'deactivate-disks': (DeactivateDisks, ARGS_ONE, [DEBUG_OPT, SUBMIT_OPT],
1324 9a033156 Iustin Pop
                       "<instance>",
1325 a8083063 Iustin Pop
                       "Deactivate an instance's disks"),
1326 6605411d Iustin Pop
  'grow-disk': (GrowDisk, ARGS_FIXED(3),
1327 6605411d Iustin Pop
                [DEBUG_OPT, SUBMIT_OPT,
1328 6605411d Iustin Pop
                 make_option("--no-wait-for-sync",
1329 6605411d Iustin Pop
                             dest="wait_for_sync", default=True,
1330 6605411d Iustin Pop
                             action="store_false",
1331 6605411d Iustin Pop
                             help="Don't wait for sync (DANGEROUS!)"),
1332 6605411d Iustin Pop
                 ],
1333 c6e911bc Iustin Pop
                "<instance> <disk> <size>", "Grow an instance's disk"),
1334 846baef9 Iustin Pop
  'list-tags': (ListTags, ARGS_ONE, [DEBUG_OPT],
1335 746ea1da Guido Trotter
                "<instance_name>", "List the tags of the given instance"),
1336 810c50b7 Iustin Pop
  'add-tags': (AddTags, ARGS_ATLEAST(1), [DEBUG_OPT, TAG_SRC_OPT],
1337 746ea1da Guido Trotter
               "<instance_name> tag...", "Add tags to the given instance"),
1338 810c50b7 Iustin Pop
  'remove-tags': (RemoveTags, ARGS_ATLEAST(1), [DEBUG_OPT, TAG_SRC_OPT],
1339 746ea1da Guido Trotter
                  "<instance_name> tag...", "Remove tags from given instance"),
1340 a8083063 Iustin Pop
  }
1341 a8083063 Iustin Pop
1342 7232c04c Iustin Pop
#: dictionary with aliases for commands
1343 dbfd89dd Guido Trotter
aliases = {
1344 dbfd89dd Guido Trotter
  'activate_block_devs': 'activate-disks',
1345 00ce8b29 Guido Trotter
  'replace_disks': 'replace-disks',
1346 536fda25 Guido Trotter
  'start': 'startup',
1347 536fda25 Guido Trotter
  'stop': 'shutdown',
1348 dbfd89dd Guido Trotter
  }
1349 dbfd89dd Guido Trotter
1350 a8083063 Iustin Pop
if __name__ == '__main__':
1351 dbfd89dd Guido Trotter
  sys.exit(GenericMain(commands, aliases=aliases,
1352 846baef9 Iustin Pop
                       override={"tag_type": constants.TAG_INSTANCE}))