Statistics
| Branch: | Tag: | Revision:

root / scripts / gnt-instance @ e0e31530

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