Statistics
| Branch: | Tag: | Revision:

root / scripts / gnt-instance @ 2f79bd34

History | View | Annotate | Download (43.1 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 48c4dfa8 Iustin Pop
_LIST_DEF_FIELDS = [
51 e69d05fd Iustin Pop
  "name", "hypervisor", "os", "pnode", "status", "oper_ram",
52 48c4dfa8 Iustin Pop
  ]
53 48c4dfa8 Iustin Pop
54 bdb7d4e8 Michael Hanselmann
55 312ac745 Iustin Pop
def _ExpandMultiNames(mode, names):
56 312ac745 Iustin Pop
  """Expand the given names using the passed mode.
57 312ac745 Iustin Pop
58 312ac745 Iustin Pop
  Args:
59 312ac745 Iustin Pop
    - mode, which can be one of _SHUTDOWN_CLUSTER, _SHUTDOWN_NODES_BOTH,
60 312ac745 Iustin Pop
      _SHUTDOWN_NODES_PRI, _SHUTDOWN_NODES_SEC or _SHUTDOWN_INSTANCES
61 312ac745 Iustin Pop
    - names, which is a list of names; for cluster, it must be empty,
62 312ac745 Iustin Pop
      and for node and instance it must be a list of valid item
63 312ac745 Iustin Pop
      names (short names are valid as usual, e.g. node1 instead of
64 312ac745 Iustin Pop
      node1.example.com)
65 312ac745 Iustin Pop
66 312ac745 Iustin Pop
  For _SHUTDOWN_CLUSTER, all instances will be returned. For
67 312ac745 Iustin Pop
  _SHUTDOWN_NODES_PRI/SEC, all instances having those nodes as
68 312ac745 Iustin Pop
  primary/secondary will be shutdown. For _SHUTDOWN_NODES_BOTH, all
69 312ac745 Iustin Pop
  instances having those nodes as either primary or secondary will be
70 312ac745 Iustin Pop
  returned. For _SHUTDOWN_INSTANCES, the given instances will be
71 312ac745 Iustin Pop
  returned.
72 312ac745 Iustin Pop
73 312ac745 Iustin Pop
  """
74 312ac745 Iustin Pop
  if mode == _SHUTDOWN_CLUSTER:
75 312ac745 Iustin Pop
    if names:
76 312ac745 Iustin Pop
      raise errors.OpPrereqError("Cluster filter mode takes no arguments")
77 b7329c9c Iustin Pop
    client = GetClient()
78 b7329c9c Iustin Pop
    idata = client.QueryInstances([], ["name"])
79 312ac745 Iustin Pop
    inames = [row[0] for row in idata]
80 312ac745 Iustin Pop
81 312ac745 Iustin Pop
  elif mode in (_SHUTDOWN_NODES_BOTH,
82 312ac745 Iustin Pop
                _SHUTDOWN_NODES_PRI,
83 312ac745 Iustin Pop
                _SHUTDOWN_NODES_SEC):
84 312ac745 Iustin Pop
    if not names:
85 312ac745 Iustin Pop
      raise errors.OpPrereqError("No node names passed")
86 b7329c9c Iustin Pop
    client = GetClient()
87 b7329c9c Iustin Pop
    ndata = client.QueryNodes(names, ["name", "pinst_list", "sinst_list"])
88 312ac745 Iustin Pop
    ipri = [row[1] for row in ndata]
89 312ac745 Iustin Pop
    pri_names = list(itertools.chain(*ipri))
90 312ac745 Iustin Pop
    isec = [row[2] for row in ndata]
91 312ac745 Iustin Pop
    sec_names = list(itertools.chain(*isec))
92 312ac745 Iustin Pop
    if mode == _SHUTDOWN_NODES_BOTH:
93 312ac745 Iustin Pop
      inames = pri_names + sec_names
94 312ac745 Iustin Pop
    elif mode == _SHUTDOWN_NODES_PRI:
95 312ac745 Iustin Pop
      inames = pri_names
96 312ac745 Iustin Pop
    elif mode == _SHUTDOWN_NODES_SEC:
97 312ac745 Iustin Pop
      inames = sec_names
98 312ac745 Iustin Pop
    else:
99 312ac745 Iustin Pop
      raise errors.ProgrammerError("Unhandled shutdown type")
100 312ac745 Iustin Pop
101 312ac745 Iustin Pop
  elif mode == _SHUTDOWN_INSTANCES:
102 312ac745 Iustin Pop
    if not names:
103 312ac745 Iustin Pop
      raise errors.OpPrereqError("No instance names passed")
104 b7329c9c Iustin Pop
    client = GetClient()
105 b7329c9c Iustin Pop
    idata = client.QueryInstances(names, ["name"])
106 312ac745 Iustin Pop
    inames = [row[0] for row in idata]
107 312ac745 Iustin Pop
108 312ac745 Iustin Pop
  else:
109 312ac745 Iustin Pop
    raise errors.OpPrereqError("Unknown mode '%s'" % mode)
110 312ac745 Iustin Pop
111 312ac745 Iustin Pop
  return inames
112 a8083063 Iustin Pop
113 a8083063 Iustin Pop
114 804a1e8e Iustin Pop
def _ConfirmOperation(inames, text):
115 804a1e8e Iustin Pop
  """Ask the user to confirm an operation on a list of instances.
116 804a1e8e Iustin Pop
117 804a1e8e Iustin Pop
  This function is used to request confirmation for doing an operation
118 804a1e8e Iustin Pop
  on a given list of instances.
119 804a1e8e Iustin Pop
120 804a1e8e Iustin Pop
  The inames argument is what the selection algorithm computed, and
121 804a1e8e Iustin Pop
  the text argument is the operation we should tell the user to
122 804a1e8e Iustin Pop
  confirm (e.g. 'shutdown' or 'startup').
123 804a1e8e Iustin Pop
124 804a1e8e Iustin Pop
  Returns: boolean depending on user's confirmation.
125 804a1e8e Iustin Pop
126 804a1e8e Iustin Pop
  """
127 804a1e8e Iustin Pop
  count = len(inames)
128 804a1e8e Iustin Pop
  msg = ("The %s will operate on %d instances.\n"
129 804a1e8e Iustin Pop
         "Do you want to continue?" % (text, count))
130 804a1e8e Iustin Pop
  affected = ("\nAffected instances:\n" +
131 804a1e8e Iustin Pop
              "\n".join(["  %s" % name for name in inames]))
132 804a1e8e Iustin Pop
133 804a1e8e Iustin Pop
  choices = [('y', True, 'Yes, execute the %s' % text),
134 804a1e8e Iustin Pop
             ('n', False, 'No, abort the %s' % text)]
135 804a1e8e Iustin Pop
136 804a1e8e Iustin Pop
  if count > 20:
137 804a1e8e Iustin Pop
    choices.insert(1, ('v', 'v', 'View the list of affected instances'))
138 804a1e8e Iustin Pop
    ask = msg
139 804a1e8e Iustin Pop
  else:
140 804a1e8e Iustin Pop
    ask = msg + affected
141 804a1e8e Iustin Pop
142 804a1e8e Iustin Pop
  choice = AskUser(ask, choices)
143 804a1e8e Iustin Pop
  if choice == 'v':
144 804a1e8e Iustin Pop
    choices.pop(1)
145 5e66b7e6 Iustin Pop
    choice = AskUser(msg + affected, choices)
146 804a1e8e Iustin Pop
  return choice
147 804a1e8e Iustin Pop
148 804a1e8e Iustin Pop
149 973d7867 Iustin Pop
def _TransformPath(user_input):
150 973d7867 Iustin Pop
  """Transform a user path into a canonical value.
151 973d7867 Iustin Pop
152 973d7867 Iustin Pop
  This function transforms the a path passed as textual information
153 973d7867 Iustin Pop
  into the constants that the LU code expects.
154 973d7867 Iustin Pop
155 973d7867 Iustin Pop
  """
156 973d7867 Iustin Pop
  if user_input:
157 973d7867 Iustin Pop
    if user_input.lower() == "default":
158 973d7867 Iustin Pop
      result_path = constants.VALUE_DEFAULT
159 973d7867 Iustin Pop
    elif user_input.lower() == "none":
160 973d7867 Iustin Pop
      result_path = constants.VALUE_NONE
161 973d7867 Iustin Pop
    else:
162 973d7867 Iustin Pop
      if not os.path.isabs(user_input):
163 973d7867 Iustin Pop
        raise errors.OpPrereqError("Path '%s' is not an absolute filename" %
164 973d7867 Iustin Pop
                                   user_input)
165 973d7867 Iustin Pop
      result_path = user_input
166 973d7867 Iustin Pop
  else:
167 973d7867 Iustin Pop
    result_path = constants.VALUE_DEFAULT
168 973d7867 Iustin Pop
169 973d7867 Iustin Pop
  return result_path
170 973d7867 Iustin Pop
171 973d7867 Iustin Pop
172 a8083063 Iustin Pop
def ListInstances(opts, args):
173 f5abe9bd Oleksiy Mishchenko
  """List instances and their properties.
174 a8083063 Iustin Pop
175 a8083063 Iustin Pop
  """
176 a8083063 Iustin Pop
  if opts.output is None:
177 48c4dfa8 Iustin Pop
    selected_fields = _LIST_DEF_FIELDS
178 48c4dfa8 Iustin Pop
  elif opts.output.startswith("+"):
179 48c4dfa8 Iustin Pop
    selected_fields = _LIST_DEF_FIELDS + opts.output[1:].split(",")
180 a8083063 Iustin Pop
  else:
181 a8083063 Iustin Pop
    selected_fields = opts.output.split(",")
182 a8083063 Iustin Pop
183 1f05af2b Michael Hanselmann
  output = GetClient().QueryInstances([], selected_fields)
184 a8083063 Iustin Pop
185 a8083063 Iustin Pop
  if not opts.no_headers:
186 d8052456 Iustin Pop
    headers = {
187 d8052456 Iustin Pop
      "name": "Instance", "os": "OS", "pnode": "Primary_node",
188 d8052456 Iustin Pop
      "snodes": "Secondary_Nodes", "admin_state": "Autostart",
189 338e51e8 Iustin Pop
      "oper_state": "Running",
190 d8052456 Iustin Pop
      "oper_ram": "Memory", "disk_template": "Disk_template",
191 3fb1e1c5 Alexander Schreiber
      "ip": "IP_address", "mac": "MAC_address",
192 338e51e8 Iustin Pop
      "bridge": "Bridge",
193 d8052456 Iustin Pop
      "sda_size": "Disk/0", "sdb_size": "Disk/1",
194 130a6a6f Iustin Pop
      "status": "Status", "tags": "Tags",
195 3fb1e1c5 Alexander Schreiber
      "network_port": "Network_port",
196 5018a335 Iustin Pop
      "hv/kernel_path": "Kernel_path",
197 5018a335 Iustin Pop
      "hv/initrd_path": "Initrd_path",
198 5018a335 Iustin Pop
      "hv/boot_order": "HVM_boot_order",
199 5018a335 Iustin Pop
      "hv/acpi": "HVM_ACPI",
200 5018a335 Iustin Pop
      "hv/pae": "HVM_PAE",
201 5018a335 Iustin Pop
      "hv/cdrom_image_path": "HVM_CDROM_image_path",
202 5018a335 Iustin Pop
      "hv/nic_type": "HVM_NIC_type",
203 5018a335 Iustin Pop
      "hv/disk_type": "HVM_Disk_type",
204 7ac1fc45 Guido Trotter
      "hv/vnc_bind_address": "VNC_bind_address",
205 e69d05fd Iustin Pop
      "serial_no": "SerialNo", "hypervisor": "Hypervisor",
206 5018a335 Iustin Pop
      "hvparams": "Hypervisor_parameters",
207 338e51e8 Iustin Pop
      "be/memory": "Configured_memory",
208 338e51e8 Iustin Pop
      "be/vcpus": "VCPUs",
209 c0f2b229 Iustin Pop
      "be/auto_balance": "Auto_balance",
210 d8052456 Iustin Pop
      }
211 137161c9 Michael Hanselmann
  else:
212 137161c9 Michael Hanselmann
    headers = None
213 137161c9 Michael Hanselmann
214 137161c9 Michael Hanselmann
  if opts.human_readable:
215 338e51e8 Iustin Pop
    unitfields = ["be/memory", "oper_ram", "sda_size", "sdb_size"]
216 137161c9 Michael Hanselmann
  else:
217 137161c9 Michael Hanselmann
    unitfields = None
218 137161c9 Michael Hanselmann
219 338e51e8 Iustin Pop
  numfields = ["be/memory", "oper_ram", "sda_size", "sdb_size", "be/vcpus",
220 38d7239a Iustin Pop
               "serial_no"]
221 137161c9 Michael Hanselmann
222 130a6a6f Iustin Pop
  list_type_fields = ("tags",)
223 8a23d2d3 Iustin Pop
  # change raw values to nicer strings
224 8a23d2d3 Iustin Pop
  for row in output:
225 8a23d2d3 Iustin Pop
    for idx, field in enumerate(selected_fields):
226 8a23d2d3 Iustin Pop
      val = row[idx]
227 8a23d2d3 Iustin Pop
      if field == "snodes":
228 8a23d2d3 Iustin Pop
        val = ",".join(val) or "-"
229 8a23d2d3 Iustin Pop
      elif field == "admin_state":
230 8a23d2d3 Iustin Pop
        if val:
231 8a23d2d3 Iustin Pop
          val = "yes"
232 8a23d2d3 Iustin Pop
        else:
233 8a23d2d3 Iustin Pop
          val = "no"
234 8a23d2d3 Iustin Pop
      elif field == "oper_state":
235 8a23d2d3 Iustin Pop
        if val is None:
236 8a23d2d3 Iustin Pop
          val = "(node down)"
237 8a23d2d3 Iustin Pop
        elif val: # True
238 8a23d2d3 Iustin Pop
          val = "running"
239 8a23d2d3 Iustin Pop
        else:
240 8a23d2d3 Iustin Pop
          val = "stopped"
241 8a23d2d3 Iustin Pop
      elif field == "oper_ram":
242 8a23d2d3 Iustin Pop
        if val is None:
243 8a23d2d3 Iustin Pop
          val = "(node down)"
244 8a23d2d3 Iustin Pop
      elif field == "sda_size" or field == "sdb_size":
245 8a23d2d3 Iustin Pop
        if val is None:
246 8a23d2d3 Iustin Pop
          val = "N/A"
247 130a6a6f Iustin Pop
      elif field in list_type_fields:
248 130a6a6f Iustin Pop
        val = ",".join(val)
249 5018a335 Iustin Pop
      elif val is None:
250 5018a335 Iustin Pop
        val = "-"
251 8a23d2d3 Iustin Pop
      row[idx] = str(val)
252 8a23d2d3 Iustin Pop
253 16be8703 Iustin Pop
  data = GenerateTable(separator=opts.separator, headers=headers,
254 16be8703 Iustin Pop
                       fields=selected_fields, unitfields=unitfields,
255 16be8703 Iustin Pop
                       numfields=numfields, data=output)
256 16be8703 Iustin Pop
257 16be8703 Iustin Pop
  for line in data:
258 3a24c527 Iustin Pop
    ToStdout(line)
259 a8083063 Iustin Pop
260 a8083063 Iustin Pop
  return 0
261 a8083063 Iustin Pop
262 a8083063 Iustin Pop
263 a8083063 Iustin Pop
def AddInstance(opts, args):
264 a8083063 Iustin Pop
  """Add an instance to the cluster.
265 a8083063 Iustin Pop
266 a8083063 Iustin Pop
  Args:
267 a8083063 Iustin Pop
    opts - class with options as members
268 a8083063 Iustin Pop
    args - list with a single element, the instance name
269 a8083063 Iustin Pop
  Opts used:
270 a8083063 Iustin Pop
    mem - amount of memory to allocate to instance (MiB)
271 a8083063 Iustin Pop
    size - amount of disk space to allocate to instance (MiB)
272 a8083063 Iustin Pop
    os - which OS to run on instance
273 a8083063 Iustin Pop
    node - node to run new instance on
274 a8083063 Iustin Pop
275 a8083063 Iustin Pop
  """
276 a8083063 Iustin Pop
  instance = args[0]
277 a8083063 Iustin Pop
278 60d49723 Michael Hanselmann
  (pnode, snode) = SplitNodeOption(opts.node)
279 60d49723 Michael Hanselmann
280 6785674e Iustin Pop
  hypervisor = None
281 6785674e Iustin Pop
  hvparams = {}
282 6785674e Iustin Pop
  if opts.hypervisor:
283 6785674e Iustin Pop
    hypervisor, hvparams = opts.hypervisor
284 3b6d8c9b Iustin Pop
285 7399cd55 Guido Trotter
  ValidateBeParams(opts.beparams)
286 338e51e8 Iustin Pop
287 6785674e Iustin Pop
##  kernel_path = _TransformPath(opts.kernel_path)
288 6785674e Iustin Pop
##  initrd_path = _TransformPath(opts.initrd_path)
289 31a853d2 Iustin Pop
290 6785674e Iustin Pop
##  hvm_acpi = opts.hvm_acpi == _VALUE_TRUE
291 6785674e Iustin Pop
##  hvm_pae = opts.hvm_pae == _VALUE_TRUE
292 6785674e Iustin Pop
293 6785674e Iustin Pop
##  if ((opts.hvm_cdrom_image_path is not None) and
294 6785674e Iustin Pop
##      (opts.hvm_cdrom_image_path.lower() == constants.VALUE_NONE)):
295 6785674e Iustin Pop
##    hvm_cdrom_image_path = None
296 6785674e Iustin Pop
##  else:
297 6785674e Iustin Pop
##    hvm_cdrom_image_path = opts.hvm_cdrom_image_path
298 31a853d2 Iustin Pop
299 338e51e8 Iustin Pop
  op = opcodes.OpCreateInstance(instance_name=instance,
300 a8083063 Iustin Pop
                                disk_size=opts.size, swap_size=opts.swap,
301 a8083063 Iustin Pop
                                disk_template=opts.disk_template,
302 a8083063 Iustin Pop
                                mode=constants.INSTANCE_CREATE,
303 60d49723 Michael Hanselmann
                                os_type=opts.os, pnode=pnode,
304 338e51e8 Iustin Pop
                                snode=snode,
305 bdd55f71 Iustin Pop
                                ip=opts.ip, bridge=opts.bridge,
306 bdd55f71 Iustin Pop
                                start=opts.start, ip_check=opts.ip_check,
307 3b6d8c9b Iustin Pop
                                wait_for_sync=opts.wait_for_sync,
308 3b6d8c9b Iustin Pop
                                mac=opts.mac,
309 6785674e Iustin Pop
                                hypervisor=hypervisor,
310 6785674e Iustin Pop
                                hvparams=hvparams,
311 338e51e8 Iustin Pop
                                beparams=opts.beparams,
312 31a853d2 Iustin Pop
                                iallocator=opts.iallocator,
313 35a0d128 Iustin Pop
                                file_storage_dir=opts.file_storage_dir,
314 35a0d128 Iustin Pop
                                file_driver=opts.file_driver,
315 6785674e Iustin Pop
                                )
316 31a853d2 Iustin Pop
317 6340bb0a Iustin Pop
  SubmitOrSend(op, opts)
318 a8083063 Iustin Pop
  return 0
319 a8083063 Iustin Pop
320 a8083063 Iustin Pop
321 0d0e9090 René Nussbaumer
def BatchCreate(opts, args):
322 0d0e9090 René Nussbaumer
  """Create instances on a batched base.
323 0d0e9090 René Nussbaumer
324 0d0e9090 René Nussbaumer
  This function reads a json with instances defined in the form:
325 0d0e9090 René Nussbaumer
326 0d0e9090 René Nussbaumer
  {"instance-name": {"disk_size": 25,
327 0d0e9090 René Nussbaumer
                     "swap_size": 1024,
328 0d0e9090 René Nussbaumer
                     "template": "drbd",
329 0d0e9090 René Nussbaumer
                     "backend": { "memory": 512,
330 0d0e9090 René Nussbaumer
                                  "vcpus": 1 },
331 0d0e9090 René Nussbaumer
                     "os": "etch-image",
332 0d0e9090 René Nussbaumer
                     "primary_node": "firstnode",
333 0d0e9090 René Nussbaumer
                     "secondary_node": "secondnode",
334 0d0e9090 René Nussbaumer
                     "iallocator": "dumb"}}
335 0d0e9090 René Nussbaumer
336 0d0e9090 René Nussbaumer
  primary_node and secondary_node has precedence over iallocator.
337 0d0e9090 René Nussbaumer
338 0d0e9090 René Nussbaumer
  Args:
339 0d0e9090 René Nussbaumer
    opts: The parsed command line options
340 0d0e9090 René Nussbaumer
    args: Argument passed to the command in our case the json file
341 0d0e9090 René Nussbaumer
342 0d0e9090 René Nussbaumer
  """
343 0d0e9090 René Nussbaumer
  _DEFAULT_SPECS = {"disk_size": 20 * 1024,
344 0d0e9090 René Nussbaumer
                    "swap_size": 4 * 1024,
345 0d0e9090 René Nussbaumer
                    "backend": {},
346 0d0e9090 René Nussbaumer
                    "iallocator": None,
347 0d0e9090 René Nussbaumer
                    "primary_node": None,
348 0d0e9090 René Nussbaumer
                    "secondary_node": None,
349 0d0e9090 René Nussbaumer
                    "ip": 'none',
350 0d0e9090 René Nussbaumer
                    "mac": 'auto',
351 0d0e9090 René Nussbaumer
                    "bridge": None,
352 0d0e9090 René Nussbaumer
                    "start": True,
353 0d0e9090 René Nussbaumer
                    "ip_check": True,
354 0d0e9090 René Nussbaumer
                    "hypervisor": None,
355 0d0e9090 René Nussbaumer
                    "file_storage_dir": None,
356 0d0e9090 René Nussbaumer
                    "file_driver": 'loop'}
357 0d0e9090 René Nussbaumer
358 0d0e9090 René Nussbaumer
  def _PopulateWithDefaults(spec):
359 0d0e9090 René Nussbaumer
    """Returns a new hash combined with default values."""
360 2f79bd34 Iustin Pop
    mydict = _DEFAULT_SPECS.copy()
361 2f79bd34 Iustin Pop
    mydict.update(spec)
362 2f79bd34 Iustin Pop
    return mydict
363 0d0e9090 René Nussbaumer
364 0d0e9090 René Nussbaumer
  def _Validate(spec):
365 0d0e9090 René Nussbaumer
    """Validate the instance specs."""
366 0d0e9090 René Nussbaumer
    # Validate fields required under any circumstances
367 0d0e9090 René Nussbaumer
    for required_field in ('os', 'template'):
368 0d0e9090 René Nussbaumer
      if required_field not in spec:
369 0d0e9090 René Nussbaumer
        raise errors.OpPrereqError('Required field "%s" is missing.' %
370 0d0e9090 René Nussbaumer
                                   required_field)
371 0d0e9090 René Nussbaumer
    # Validate special fields
372 0d0e9090 René Nussbaumer
    if spec['primary_node'] is not None:
373 0d0e9090 René Nussbaumer
      if (spec['template'] in constants.DTS_NET_MIRROR and
374 0d0e9090 René Nussbaumer
          spec['secondary_node'] is None):
375 0d0e9090 René Nussbaumer
        raise errors.OpPrereqError('Template requires secondary node, but'
376 0d0e9090 René Nussbaumer
                                   ' there was no secondary provided.')
377 0d0e9090 René Nussbaumer
    elif spec['iallocator'] is None:
378 0d0e9090 René Nussbaumer
      raise errors.OpPrereqError('You have to provide at least a primary_node'
379 0d0e9090 René Nussbaumer
                                 ' or an iallocator.')
380 0d0e9090 René Nussbaumer
381 0d0e9090 René Nussbaumer
    if (spec['hypervisor'] and
382 0d0e9090 René Nussbaumer
        not isinstance(spec['hypervisor'], dict)):
383 0d0e9090 René Nussbaumer
      raise errors.OpPrereqError('Hypervisor parameters must be a dict.')
384 0d0e9090 René Nussbaumer
385 0d0e9090 René Nussbaumer
  json_filename = args[0]
386 0d0e9090 René Nussbaumer
  fd = open(json_filename, 'r')
387 0d0e9090 René Nussbaumer
  try:
388 0d0e9090 René Nussbaumer
    instance_data = simplejson.load(fd)
389 0d0e9090 René Nussbaumer
  finally:
390 0d0e9090 René Nussbaumer
    fd.close()
391 0d0e9090 René Nussbaumer
392 0d0e9090 René Nussbaumer
  # Iterate over the instances and do:
393 0d0e9090 René Nussbaumer
  #  * Populate the specs with default value
394 0d0e9090 René Nussbaumer
  #  * Validate the instance specs
395 0d0e9090 René Nussbaumer
  for (name, specs) in instance_data.iteritems():
396 0d0e9090 René Nussbaumer
    specs = _PopulateWithDefaults(specs)
397 0d0e9090 René Nussbaumer
    _Validate(specs)
398 0d0e9090 René Nussbaumer
399 0d0e9090 René Nussbaumer
    hypervisor = None
400 0d0e9090 René Nussbaumer
    hvparams = {}
401 0d0e9090 René Nussbaumer
    if specs['hypervisor']:
402 0d0e9090 René Nussbaumer
      hypervisor, hvparams = specs['hypervisor'].iteritems()
403 0d0e9090 René Nussbaumer
404 0d0e9090 René Nussbaumer
    op = opcodes.OpCreateInstance(instance_name=name,
405 0d0e9090 René Nussbaumer
                                  disk_size=specs['disk_size'],
406 0d0e9090 René Nussbaumer
                                  swap_size=specs['swap_size'],
407 0d0e9090 René Nussbaumer
                                  disk_template=specs['template'],
408 0d0e9090 René Nussbaumer
                                  mode=constants.INSTANCE_CREATE,
409 0d0e9090 René Nussbaumer
                                  os_type=specs['os'],
410 0d0e9090 René Nussbaumer
                                  pnode=specs['primary_node'],
411 0d0e9090 René Nussbaumer
                                  snode=specs['secondary_node'],
412 0d0e9090 René Nussbaumer
                                  ip=specs['ip'], bridge=specs['bridge'],
413 0d0e9090 René Nussbaumer
                                  start=specs['start'],
414 0d0e9090 René Nussbaumer
                                  ip_check=specs['ip_check'],
415 0d0e9090 René Nussbaumer
                                  wait_for_sync=True,
416 0d0e9090 René Nussbaumer
                                  mac=specs['mac'],
417 0d0e9090 René Nussbaumer
                                  iallocator=specs['iallocator'],
418 0d0e9090 René Nussbaumer
                                  hypervisor=hypervisor,
419 0d0e9090 René Nussbaumer
                                  hvparams=hvparams,
420 0d0e9090 René Nussbaumer
                                  beparams=specs['backend'],
421 0d0e9090 René Nussbaumer
                                  file_storage_dir=specs['file_storage_dir'],
422 0d0e9090 René Nussbaumer
                                  file_driver=specs['file_driver'])
423 0d0e9090 René Nussbaumer
424 3a24c527 Iustin Pop
    ToStdout("%s: %s", name, cli.SendJob([op]))
425 0d0e9090 René Nussbaumer
426 0d0e9090 René Nussbaumer
  return 0
427 0d0e9090 René Nussbaumer
428 0d0e9090 René Nussbaumer
429 fe7b0351 Michael Hanselmann
def ReinstallInstance(opts, args):
430 fe7b0351 Michael Hanselmann
  """Reinstall an instance.
431 fe7b0351 Michael Hanselmann
432 fe7b0351 Michael Hanselmann
  Args:
433 fe7b0351 Michael Hanselmann
    opts - class with options as members
434 fe7b0351 Michael Hanselmann
    args - list containing a single element, the instance name
435 fe7b0351 Michael Hanselmann
436 fe7b0351 Michael Hanselmann
  """
437 fe7b0351 Michael Hanselmann
  instance_name = args[0]
438 fe7b0351 Michael Hanselmann
439 20e23543 Alexander Schreiber
  if opts.select_os is True:
440 20e23543 Alexander Schreiber
    op = opcodes.OpDiagnoseOS(output_fields=["name", "valid"], names=[])
441 20e23543 Alexander Schreiber
    result = SubmitOpCode(op)
442 20e23543 Alexander Schreiber
443 20e23543 Alexander Schreiber
    if not result:
444 3a24c527 Iustin Pop
      ToStdout("Can't get the OS list")
445 20e23543 Alexander Schreiber
      return 1
446 20e23543 Alexander Schreiber
447 3a24c527 Iustin Pop
    ToStdout("Available OS templates:")
448 20e23543 Alexander Schreiber
    number = 0
449 20e23543 Alexander Schreiber
    choices = []
450 20e23543 Alexander Schreiber
    for entry in result:
451 3a24c527 Iustin Pop
      ToStdout("%3s: %s", number, entry[0])
452 20e23543 Alexander Schreiber
      choices.append(("%s" % number, entry[0], entry[0]))
453 20e23543 Alexander Schreiber
      number = number + 1
454 20e23543 Alexander Schreiber
455 20e23543 Alexander Schreiber
    choices.append(('x', 'exit', 'Exit gnt-instance reinstall'))
456 20e23543 Alexander Schreiber
    selected = AskUser("Enter OS template name or number (or x to abort):",
457 20e23543 Alexander Schreiber
                       choices)
458 20e23543 Alexander Schreiber
459 20e23543 Alexander Schreiber
    if selected == 'exit':
460 3a24c527 Iustin Pop
      ToStdout("User aborted reinstall, exiting")
461 20e23543 Alexander Schreiber
      return 1
462 20e23543 Alexander Schreiber
463 2f79bd34 Iustin Pop
    os_name = selected
464 20e23543 Alexander Schreiber
  else:
465 2f79bd34 Iustin Pop
    os_name = opts.os
466 20e23543 Alexander Schreiber
467 fe7b0351 Michael Hanselmann
  if not opts.force:
468 f4bc1f2c Michael Hanselmann
    usertext = ("This will reinstall the instance %s and remove"
469 f4bc1f2c Michael Hanselmann
                " all data. Continue?") % instance_name
470 47988778 Iustin Pop
    if not AskUser(usertext):
471 fe7b0351 Michael Hanselmann
      return 1
472 fe7b0351 Michael Hanselmann
473 d0834de3 Michael Hanselmann
  op = opcodes.OpReinstallInstance(instance_name=instance_name,
474 2f79bd34 Iustin Pop
                                   os_type=os_name)
475 6340bb0a Iustin Pop
  SubmitOrSend(op, opts)
476 fe7b0351 Michael Hanselmann
477 fe7b0351 Michael Hanselmann
  return 0
478 fe7b0351 Michael Hanselmann
479 fe7b0351 Michael Hanselmann
480 a8083063 Iustin Pop
def RemoveInstance(opts, args):
481 a8083063 Iustin Pop
  """Remove an instance.
482 a8083063 Iustin Pop
483 a8083063 Iustin Pop
  Args:
484 a8083063 Iustin Pop
    opts - class with options as members
485 a8083063 Iustin Pop
    args - list containing a single element, the instance name
486 a8083063 Iustin Pop
487 a8083063 Iustin Pop
  """
488 a8083063 Iustin Pop
  instance_name = args[0]
489 a8083063 Iustin Pop
  force = opts.force
490 a8083063 Iustin Pop
491 a8083063 Iustin Pop
  if not force:
492 a8083063 Iustin Pop
    usertext = ("This will remove the volumes of the instance %s"
493 a8083063 Iustin Pop
                " (including mirrors), thus removing all the data"
494 a8083063 Iustin Pop
                " of the instance. Continue?") % instance_name
495 47988778 Iustin Pop
    if not AskUser(usertext):
496 a8083063 Iustin Pop
      return 1
497 a8083063 Iustin Pop
498 1d67656e Iustin Pop
  op = opcodes.OpRemoveInstance(instance_name=instance_name,
499 1d67656e Iustin Pop
                                ignore_failures=opts.ignore_failures)
500 6340bb0a Iustin Pop
  SubmitOrSend(op, opts)
501 a8083063 Iustin Pop
  return 0
502 a8083063 Iustin Pop
503 a8083063 Iustin Pop
504 decd5f45 Iustin Pop
def RenameInstance(opts, args):
505 4ab0b9e3 Guido Trotter
  """Rename an instance.
506 decd5f45 Iustin Pop
507 decd5f45 Iustin Pop
  Args:
508 decd5f45 Iustin Pop
    opts - class with options as members
509 decd5f45 Iustin Pop
    args - list containing two elements, the instance name and the new name
510 decd5f45 Iustin Pop
511 decd5f45 Iustin Pop
  """
512 decd5f45 Iustin Pop
  op = opcodes.OpRenameInstance(instance_name=args[0],
513 decd5f45 Iustin Pop
                                new_name=args[1],
514 decd5f45 Iustin Pop
                                ignore_ip=opts.ignore_ip)
515 6340bb0a Iustin Pop
  SubmitOrSend(op, opts)
516 decd5f45 Iustin Pop
  return 0
517 decd5f45 Iustin Pop
518 decd5f45 Iustin Pop
519 a8083063 Iustin Pop
def ActivateDisks(opts, args):
520 a8083063 Iustin Pop
  """Activate an instance's disks.
521 a8083063 Iustin Pop
522 a8083063 Iustin Pop
  This serves two purposes:
523 a8083063 Iustin Pop
    - it allows one (as long as the instance is not running) to mount
524 a8083063 Iustin Pop
    the disks and modify them from the node
525 a8083063 Iustin Pop
    - it repairs inactive secondary drbds
526 a8083063 Iustin Pop
527 a8083063 Iustin Pop
  """
528 a8083063 Iustin Pop
  instance_name = args[0]
529 a8083063 Iustin Pop
  op = opcodes.OpActivateInstanceDisks(instance_name=instance_name)
530 6340bb0a Iustin Pop
  disks_info = SubmitOrSend(op, opts)
531 a8083063 Iustin Pop
  for host, iname, nname in disks_info:
532 3a24c527 Iustin Pop
    ToStdout("%s:%s:%s", host, iname, nname)
533 a8083063 Iustin Pop
  return 0
534 a8083063 Iustin Pop
535 a8083063 Iustin Pop
536 a8083063 Iustin Pop
def DeactivateDisks(opts, args):
537 a8083063 Iustin Pop
  """Command-line interface for _ShutdownInstanceBlockDevices.
538 a8083063 Iustin Pop
539 a8083063 Iustin Pop
  This function takes the instance name, looks for its primary node
540 a8083063 Iustin Pop
  and the tries to shutdown its block devices on that node.
541 a8083063 Iustin Pop
542 a8083063 Iustin Pop
  """
543 a8083063 Iustin Pop
  instance_name = args[0]
544 a8083063 Iustin Pop
  op = opcodes.OpDeactivateInstanceDisks(instance_name=instance_name)
545 6340bb0a Iustin Pop
  SubmitOrSend(op, opts)
546 a8083063 Iustin Pop
  return 0
547 a8083063 Iustin Pop
548 a8083063 Iustin Pop
549 c6e911bc Iustin Pop
def GrowDisk(opts, args):
550 c6e911bc Iustin Pop
  """Command-line interface for _ShutdownInstanceBlockDevices.
551 c6e911bc Iustin Pop
552 c6e911bc Iustin Pop
  This function takes the instance name, looks for its primary node
553 c6e911bc Iustin Pop
  and the tries to shutdown its block devices on that node.
554 c6e911bc Iustin Pop
555 c6e911bc Iustin Pop
  """
556 c6e911bc Iustin Pop
  instance = args[0]
557 c6e911bc Iustin Pop
  disk = args[1]
558 c6e911bc Iustin Pop
  amount = utils.ParseUnit(args[2])
559 6605411d Iustin Pop
  op = opcodes.OpGrowDisk(instance_name=instance, disk=disk, amount=amount,
560 6605411d Iustin Pop
                          wait_for_sync=opts.wait_for_sync)
561 6340bb0a Iustin Pop
  SubmitOrSend(op, opts)
562 c6e911bc Iustin Pop
  return 0
563 c6e911bc Iustin Pop
564 c6e911bc Iustin Pop
565 a8083063 Iustin Pop
def StartupInstance(opts, args):
566 decd5f45 Iustin Pop
  """Startup an instance.
567 a8083063 Iustin Pop
568 a8083063 Iustin Pop
  Args:
569 a8083063 Iustin Pop
    opts - class with options as members
570 a8083063 Iustin Pop
    args - list containing a single element, the instance name
571 a8083063 Iustin Pop
572 a8083063 Iustin Pop
  """
573 312ac745 Iustin Pop
  if opts.multi_mode is None:
574 312ac745 Iustin Pop
    opts.multi_mode = _SHUTDOWN_INSTANCES
575 312ac745 Iustin Pop
  inames = _ExpandMultiNames(opts.multi_mode, args)
576 bcee9cb4 Iustin Pop
  if not inames:
577 bcee9cb4 Iustin Pop
    raise errors.OpPrereqError("Selection filter does not match any instances")
578 804a1e8e Iustin Pop
  multi_on = opts.multi_mode != _SHUTDOWN_INSTANCES or len(inames) > 1
579 804a1e8e Iustin Pop
  if not (opts.force_multi or not multi_on
580 804a1e8e Iustin Pop
          or _ConfirmOperation(inames, "startup")):
581 804a1e8e Iustin Pop
    return 1
582 312ac745 Iustin Pop
  for name in inames:
583 312ac745 Iustin Pop
    op = opcodes.OpStartupInstance(instance_name=name,
584 312ac745 Iustin Pop
                                   force=opts.force,
585 312ac745 Iustin Pop
                                   extra_args=opts.extra_args)
586 312ac745 Iustin Pop
    if multi_on:
587 3a24c527 Iustin Pop
      ToStdout("Starting up %s", name)
588 aefef4f4 Iustin Pop
    try:
589 aefef4f4 Iustin Pop
      SubmitOrSend(op, opts)
590 aefef4f4 Iustin Pop
    except JobSubmittedException, err:
591 aefef4f4 Iustin Pop
      _, txt = FormatError(err)
592 3a24c527 Iustin Pop
      ToStdout("%s", txt)
593 a8083063 Iustin Pop
  return 0
594 a8083063 Iustin Pop
595 7c0d6283 Michael Hanselmann
596 579d4337 Alexander Schreiber
def RebootInstance(opts, args):
597 579d4337 Alexander Schreiber
  """Reboot an instance
598 579d4337 Alexander Schreiber
599 579d4337 Alexander Schreiber
  Args:
600 579d4337 Alexander Schreiber
    opts - class with options as members
601 579d4337 Alexander Schreiber
    args - list containing a single element, the instance name
602 579d4337 Alexander Schreiber
603 579d4337 Alexander Schreiber
  """
604 579d4337 Alexander Schreiber
  if opts.multi_mode is None:
605 579d4337 Alexander Schreiber
    opts.multi_mode = _SHUTDOWN_INSTANCES
606 579d4337 Alexander Schreiber
  inames = _ExpandMultiNames(opts.multi_mode, args)
607 bcee9cb4 Iustin Pop
  if not inames:
608 bcee9cb4 Iustin Pop
    raise errors.OpPrereqError("Selection filter does not match any instances")
609 579d4337 Alexander Schreiber
  multi_on = opts.multi_mode != _SHUTDOWN_INSTANCES or len(inames) > 1
610 579d4337 Alexander Schreiber
  if not (opts.force_multi or not multi_on
611 579d4337 Alexander Schreiber
          or _ConfirmOperation(inames, "reboot")):
612 579d4337 Alexander Schreiber
    return 1
613 579d4337 Alexander Schreiber
  for name in inames:
614 579d4337 Alexander Schreiber
    op = opcodes.OpRebootInstance(instance_name=name,
615 579d4337 Alexander Schreiber
                                  reboot_type=opts.reboot_type,
616 579d4337 Alexander Schreiber
                                  ignore_secondaries=opts.ignore_secondaries)
617 579d4337 Alexander Schreiber
618 6340bb0a Iustin Pop
    SubmitOrSend(op, opts)
619 579d4337 Alexander Schreiber
  return 0
620 a8083063 Iustin Pop
621 7c0d6283 Michael Hanselmann
622 a8083063 Iustin Pop
def ShutdownInstance(opts, args):
623 a8083063 Iustin Pop
  """Shutdown an instance.
624 a8083063 Iustin Pop
625 a8083063 Iustin Pop
  Args:
626 a8083063 Iustin Pop
    opts - class with options as members
627 a8083063 Iustin Pop
    args - list containing a single element, the instance name
628 a8083063 Iustin Pop
629 a8083063 Iustin Pop
  """
630 312ac745 Iustin Pop
  if opts.multi_mode is None:
631 312ac745 Iustin Pop
    opts.multi_mode = _SHUTDOWN_INSTANCES
632 312ac745 Iustin Pop
  inames = _ExpandMultiNames(opts.multi_mode, args)
633 bcee9cb4 Iustin Pop
  if not inames:
634 bcee9cb4 Iustin Pop
    raise errors.OpPrereqError("Selection filter does not match any instances")
635 804a1e8e Iustin Pop
  multi_on = opts.multi_mode != _SHUTDOWN_INSTANCES or len(inames) > 1
636 804a1e8e Iustin Pop
  if not (opts.force_multi or not multi_on
637 804a1e8e Iustin Pop
          or _ConfirmOperation(inames, "shutdown")):
638 804a1e8e Iustin Pop
    return 1
639 312ac745 Iustin Pop
  for name in inames:
640 312ac745 Iustin Pop
    op = opcodes.OpShutdownInstance(instance_name=name)
641 312ac745 Iustin Pop
    if multi_on:
642 3a24c527 Iustin Pop
      ToStdout("Shutting down %s", name)
643 aefef4f4 Iustin Pop
    try:
644 aefef4f4 Iustin Pop
      SubmitOrSend(op, opts)
645 aefef4f4 Iustin Pop
    except JobSubmittedException, err:
646 aefef4f4 Iustin Pop
      _, txt = FormatError(err)
647 3a24c527 Iustin Pop
      ToStdout("%s", txt)
648 a8083063 Iustin Pop
  return 0
649 a8083063 Iustin Pop
650 a8083063 Iustin Pop
651 a8083063 Iustin Pop
def ReplaceDisks(opts, args):
652 a8083063 Iustin Pop
  """Replace the disks of an instance
653 a8083063 Iustin Pop
654 a8083063 Iustin Pop
  Args:
655 a8083063 Iustin Pop
    opts - class with options as members
656 a8083063 Iustin Pop
    args - list with a single element, the instance name
657 a8083063 Iustin Pop
658 a8083063 Iustin Pop
  """
659 a8083063 Iustin Pop
  instance_name = args[0]
660 a9e0c397 Iustin Pop
  new_2ndary = opts.new_secondary
661 b6e82a65 Iustin Pop
  iallocator = opts.iallocator
662 a9e0c397 Iustin Pop
  if opts.disks is None:
663 a9e0c397 Iustin Pop
    disks = ["sda", "sdb"]
664 a9e0c397 Iustin Pop
  else:
665 a9e0c397 Iustin Pop
    disks = opts.disks.split(",")
666 a9e0c397 Iustin Pop
  if opts.on_primary == opts.on_secondary: # no -p or -s passed, or both passed
667 a9e0c397 Iustin Pop
    mode = constants.REPLACE_DISK_ALL
668 a9e0c397 Iustin Pop
  elif opts.on_primary: # only on primary:
669 a9e0c397 Iustin Pop
    mode = constants.REPLACE_DISK_PRI
670 b6e82a65 Iustin Pop
    if new_2ndary is not None or iallocator is not None:
671 a9e0c397 Iustin Pop
      raise errors.OpPrereqError("Can't change secondary node on primary disk"
672 a9e0c397 Iustin Pop
                                 " replacement")
673 b6e82a65 Iustin Pop
  elif opts.on_secondary is not None or iallocator is not None:
674 b6e82a65 Iustin Pop
    # only on secondary
675 a9e0c397 Iustin Pop
    mode = constants.REPLACE_DISK_SEC
676 a9e0c397 Iustin Pop
677 a9e0c397 Iustin Pop
  op = opcodes.OpReplaceDisks(instance_name=args[0], disks=disks,
678 b6e82a65 Iustin Pop
                              remote_node=new_2ndary, mode=mode,
679 b6e82a65 Iustin Pop
                              iallocator=iallocator)
680 6340bb0a Iustin Pop
  SubmitOrSend(op, opts)
681 a8083063 Iustin Pop
  return 0
682 a8083063 Iustin Pop
683 a8083063 Iustin Pop
684 a8083063 Iustin Pop
def FailoverInstance(opts, args):
685 a8083063 Iustin Pop
  """Failover an instance.
686 a8083063 Iustin Pop
687 a8083063 Iustin Pop
  The failover is done by shutting it down on its present node and
688 a8083063 Iustin Pop
  starting it on the secondary.
689 a8083063 Iustin Pop
690 a8083063 Iustin Pop
  Args:
691 a8083063 Iustin Pop
    opts - class with options as members
692 a8083063 Iustin Pop
    args - list with a single element, the instance name
693 a8083063 Iustin Pop
  Opts used:
694 a8083063 Iustin Pop
    force - whether to failover without asking questions.
695 a8083063 Iustin Pop
696 a8083063 Iustin Pop
  """
697 80de0e3f Iustin Pop
  instance_name = args[0]
698 80de0e3f Iustin Pop
  force = opts.force
699 a8083063 Iustin Pop
700 80de0e3f Iustin Pop
  if not force:
701 80de0e3f Iustin Pop
    usertext = ("Failover will happen to image %s."
702 80de0e3f Iustin Pop
                " This requires a shutdown of the instance. Continue?" %
703 80de0e3f Iustin Pop
                (instance_name,))
704 80de0e3f Iustin Pop
    if not AskUser(usertext):
705 80de0e3f Iustin Pop
      return 1
706 a8083063 Iustin Pop
707 80de0e3f Iustin Pop
  op = opcodes.OpFailoverInstance(instance_name=instance_name,
708 80de0e3f Iustin Pop
                                  ignore_consistency=opts.ignore_consistency)
709 6340bb0a Iustin Pop
  SubmitOrSend(op, opts)
710 80de0e3f Iustin Pop
  return 0
711 a8083063 Iustin Pop
712 a8083063 Iustin Pop
713 a8083063 Iustin Pop
def ConnectToInstanceConsole(opts, args):
714 a8083063 Iustin Pop
  """Connect to the console of an instance.
715 a8083063 Iustin Pop
716 a8083063 Iustin Pop
  Args:
717 a8083063 Iustin Pop
    opts - class with options as members
718 a8083063 Iustin Pop
    args - list with a single element, the instance name
719 a8083063 Iustin Pop
720 a8083063 Iustin Pop
  """
721 a8083063 Iustin Pop
  instance_name = args[0]
722 a8083063 Iustin Pop
723 a8083063 Iustin Pop
  op = opcodes.OpConnectConsole(instance_name=instance_name)
724 0a80a26f Michael Hanselmann
  cmd = SubmitOpCode(op)
725 51c6e7b5 Michael Hanselmann
726 51c6e7b5 Michael Hanselmann
  if opts.show_command:
727 3a24c527 Iustin Pop
    ToStdout("%s", utils.ShellQuoteArgs(cmd))
728 51c6e7b5 Michael Hanselmann
  else:
729 51c6e7b5 Michael Hanselmann
    try:
730 51c6e7b5 Michael Hanselmann
      os.execvp(cmd[0], cmd)
731 51c6e7b5 Michael Hanselmann
    finally:
732 3a24c527 Iustin Pop
      ToStderr("Can't run console command %s with arguments:\n'%s'",
733 2f79bd34 Iustin Pop
               cmd[0], " ".join(cmd))
734 51c6e7b5 Michael Hanselmann
      os._exit(1)
735 a8083063 Iustin Pop
736 a8083063 Iustin Pop
737 57821cac Iustin Pop
def _FormatBlockDevInfo(buf, dev, indent_level, static):
738 a8083063 Iustin Pop
  """Show block device information.
739 a8083063 Iustin Pop
740 a8083063 Iustin Pop
  This is only used by ShowInstanceConfig(), but it's too big to be
741 a8083063 Iustin Pop
  left for an inline definition.
742 a8083063 Iustin Pop
743 a8083063 Iustin Pop
  """
744 a8083063 Iustin Pop
  def helper(buf, dtype, status):
745 f2e9e0e8 Alexander Schreiber
    """Format one line for physical device status."""
746 a8083063 Iustin Pop
    if not status:
747 a8083063 Iustin Pop
      buf.write("not active\n")
748 a8083063 Iustin Pop
    else:
749 0834c866 Iustin Pop
      (path, major, minor, syncp, estt, degr, ldisk) = status
750 fd38ef95 Manuel Franceschini
      if major is None:
751 fd38ef95 Manuel Franceschini
        major_string = "N/A"
752 fd38ef95 Manuel Franceschini
      else:
753 fd38ef95 Manuel Franceschini
        major_string = str(major)
754 fd38ef95 Manuel Franceschini
755 fd38ef95 Manuel Franceschini
      if minor is None:
756 fd38ef95 Manuel Franceschini
        minor_string = "N/A"
757 fd38ef95 Manuel Franceschini
      else:
758 fd38ef95 Manuel Franceschini
        minor_string = str(minor)
759 fd38ef95 Manuel Franceschini
760 fd38ef95 Manuel Franceschini
      buf.write("%s (%s:%s)" % (path, major_string, minor_string))
761 00fb8246 Michael Hanselmann
      if dtype in (constants.LD_DRBD8, ):
762 a8083063 Iustin Pop
        if syncp is not None:
763 a8083063 Iustin Pop
          sync_text = "*RECOVERING* %5.2f%%," % syncp
764 a8083063 Iustin Pop
          if estt:
765 a8083063 Iustin Pop
            sync_text += " ETA %ds" % estt
766 a8083063 Iustin Pop
          else:
767 a8083063 Iustin Pop
            sync_text += " ETA unknown"
768 a8083063 Iustin Pop
        else:
769 a8083063 Iustin Pop
          sync_text = "in sync"
770 a8083063 Iustin Pop
        if degr:
771 a8083063 Iustin Pop
          degr_text = "*DEGRADED*"
772 a8083063 Iustin Pop
        else:
773 a8083063 Iustin Pop
          degr_text = "ok"
774 0834c866 Iustin Pop
        if ldisk:
775 0834c866 Iustin Pop
          ldisk_text = " *MISSING DISK*"
776 0834c866 Iustin Pop
        else:
777 0834c866 Iustin Pop
          ldisk_text = ""
778 0834c866 Iustin Pop
        buf.write(" %s, status %s%s" % (sync_text, degr_text, ldisk_text))
779 9db6dbce Iustin Pop
      elif dtype == constants.LD_LV:
780 0834c866 Iustin Pop
        if ldisk:
781 0834c866 Iustin Pop
          ldisk_text = " *FAILED* (failed drive?)"
782 9db6dbce Iustin Pop
        else:
783 0834c866 Iustin Pop
          ldisk_text = ""
784 0834c866 Iustin Pop
        buf.write(ldisk_text)
785 a8083063 Iustin Pop
      buf.write("\n")
786 a8083063 Iustin Pop
787 a8083063 Iustin Pop
  if dev["iv_name"] is not None:
788 a8083063 Iustin Pop
    data = "  - %s, " % dev["iv_name"]
789 a8083063 Iustin Pop
  else:
790 a8083063 Iustin Pop
    data = "  - "
791 a8083063 Iustin Pop
  data += "type: %s" % dev["dev_type"]
792 a8083063 Iustin Pop
  if dev["logical_id"] is not None:
793 a8083063 Iustin Pop
    data += ", logical_id: %s" % (dev["logical_id"],)
794 a8083063 Iustin Pop
  elif dev["physical_id"] is not None:
795 a8083063 Iustin Pop
    data += ", physical_id: %s" % (dev["physical_id"],)
796 a8083063 Iustin Pop
  buf.write("%*s%s\n" % (2*indent_level, "", data))
797 57821cac Iustin Pop
  if not static:
798 57821cac Iustin Pop
    buf.write("%*s    primary:   " % (2*indent_level, ""))
799 57821cac Iustin Pop
    helper(buf, dev["dev_type"], dev["pstatus"])
800 a8083063 Iustin Pop
801 57821cac Iustin Pop
  if dev["sstatus"] and not static:
802 a8083063 Iustin Pop
    buf.write("%*s    secondary: " % (2*indent_level, ""))
803 a8083063 Iustin Pop
    helper(buf, dev["dev_type"], dev["sstatus"])
804 a8083063 Iustin Pop
805 a8083063 Iustin Pop
  if dev["children"]:
806 a8083063 Iustin Pop
    for child in dev["children"]:
807 57821cac Iustin Pop
      _FormatBlockDevInfo(buf, child, indent_level+1, static)
808 a8083063 Iustin Pop
809 a8083063 Iustin Pop
810 a8083063 Iustin Pop
def ShowInstanceConfig(opts, args):
811 a8083063 Iustin Pop
  """Compute instance run-time status.
812 a8083063 Iustin Pop
813 a8083063 Iustin Pop
  """
814 a8083063 Iustin Pop
  retcode = 0
815 57821cac Iustin Pop
  op = opcodes.OpQueryInstanceData(instances=args, static=opts.static)
816 a8083063 Iustin Pop
  result = SubmitOpCode(op)
817 a8083063 Iustin Pop
  if not result:
818 3a24c527 Iustin Pop
    ToStdout("No instances.")
819 a8083063 Iustin Pop
    return 1
820 a8083063 Iustin Pop
821 a8083063 Iustin Pop
  buf = StringIO()
822 a8083063 Iustin Pop
  retcode = 0
823 a8083063 Iustin Pop
  for instance_name in result:
824 a8083063 Iustin Pop
    instance = result[instance_name]
825 a8083063 Iustin Pop
    buf.write("Instance name: %s\n" % instance["name"])
826 57821cac Iustin Pop
    buf.write("State: configured to be %s" % instance["config_state"])
827 57821cac Iustin Pop
    if not opts.static:
828 57821cac Iustin Pop
      buf.write(", actual state is %s" % instance["run_state"])
829 57821cac Iustin Pop
    buf.write("\n")
830 57821cac Iustin Pop
    ##buf.write("Considered for memory checks in cluster verify: %s\n" %
831 57821cac Iustin Pop
    ##          instance["auto_balance"])
832 a8083063 Iustin Pop
    buf.write("  Nodes:\n")
833 a8083063 Iustin Pop
    buf.write("    - primary: %s\n" % instance["pnode"])
834 a8083063 Iustin Pop
    buf.write("    - secondaries: %s\n" % ", ".join(instance["snodes"]))
835 a8083063 Iustin Pop
    buf.write("  Operating system: %s\n" % instance["os"])
836 a8340917 Iustin Pop
    if instance.has_key("network_port"):
837 a8340917 Iustin Pop
      buf.write("  Allocated network port: %s\n" % instance["network_port"])
838 24838135 Iustin Pop
    buf.write("  Hypervisor: %s\n" % instance["hypervisor"])
839 24838135 Iustin Pop
    if instance["hypervisor"] == constants.HT_XEN_PVM:
840 24838135 Iustin Pop
      hvattrs = ((constants.HV_KERNEL_PATH, "kernel path"),
841 24838135 Iustin Pop
                 (constants.HV_INITRD_PATH, "initrd path"))
842 24838135 Iustin Pop
    elif instance["hypervisor"] == constants.HT_XEN_HVM:
843 24838135 Iustin Pop
      hvattrs = ((constants.HV_BOOT_ORDER, "boot order"),
844 24838135 Iustin Pop
                 (constants.HV_ACPI, "ACPI"),
845 24838135 Iustin Pop
                 (constants.HV_PAE, "PAE"),
846 24838135 Iustin Pop
                 (constants.HV_CDROM_IMAGE_PATH, "virtual CDROM"),
847 24838135 Iustin Pop
                 (constants.HV_NIC_TYPE, "NIC type"),
848 24838135 Iustin Pop
                 (constants.HV_DISK_TYPE, "Disk type"),
849 24838135 Iustin Pop
                 (constants.HV_VNC_BIND_ADDRESS, "VNC bind address"),
850 24838135 Iustin Pop
                 )
851 24838135 Iustin Pop
      # custom console information for HVM
852 24838135 Iustin Pop
      vnc_bind_address = instance["hv_actual"][constants.HV_VNC_BIND_ADDRESS]
853 24838135 Iustin Pop
      if vnc_bind_address == constants.BIND_ADDRESS_GLOBAL:
854 24838135 Iustin Pop
        vnc_console_port = "%s:%s" % (instance["pnode"],
855 24838135 Iustin Pop
                                      instance["network_port"])
856 24838135 Iustin Pop
      elif vnc_bind_address == constants.LOCALHOST_IP_ADDRESS:
857 24838135 Iustin Pop
        vnc_console_port = "%s:%s on node %s" % (vnc_bind_address,
858 24838135 Iustin Pop
                                                 instance["network_port"],
859 24838135 Iustin Pop
                                                 instance["pnode"])
860 a8340917 Iustin Pop
      else:
861 24838135 Iustin Pop
        vnc_console_port = "%s:%s" % (vnc_bind_address,
862 24838135 Iustin Pop
                                      instance["network_port"])
863 24838135 Iustin Pop
      buf.write("    - console connection: vnc to %s\n" % vnc_console_port)
864 24838135 Iustin Pop
865 24838135 Iustin Pop
    else:
866 24838135 Iustin Pop
      # auto-handle other hypervisor types
867 24838135 Iustin Pop
      hvattrs = [(key, key) for key in instance["hv_actual"]]
868 24838135 Iustin Pop
869 24838135 Iustin Pop
    for key, desc in hvattrs:
870 24838135 Iustin Pop
      if key in instance["hv_instance"]:
871 24838135 Iustin Pop
        val = instance["hv_instance"][key]
872 a8340917 Iustin Pop
      else:
873 24838135 Iustin Pop
        val = "default (%s)" % instance["hv_actual"][key]
874 24838135 Iustin Pop
      buf.write("    - %s: %s\n" % (desc, val))
875 a8083063 Iustin Pop
    buf.write("  Hardware:\n")
876 338e51e8 Iustin Pop
    buf.write("    - VCPUs: %d\n" %
877 338e51e8 Iustin Pop
              instance["be_actual"][constants.BE_VCPUS])
878 338e51e8 Iustin Pop
    buf.write("    - memory: %dMiB\n" %
879 338e51e8 Iustin Pop
              instance["be_actual"][constants.BE_MEMORY])
880 a8083063 Iustin Pop
    buf.write("    - NICs: %s\n" %
881 24838135 Iustin Pop
              ", ".join(["{MAC: %s, IP: %s, bridge: %s}" %
882 24838135 Iustin Pop
                         (mac, ip, bridge)
883 24838135 Iustin Pop
                         for mac, ip, bridge in instance["nics"]]))
884 a8083063 Iustin Pop
    buf.write("  Block devices:\n")
885 a8083063 Iustin Pop
886 a8083063 Iustin Pop
    for device in instance["disks"]:
887 57821cac Iustin Pop
      _FormatBlockDevInfo(buf, device, 1, opts.static)
888 a8083063 Iustin Pop
889 3a24c527 Iustin Pop
  ToStdout(buf.getvalue().rstrip('\n'))
890 a8083063 Iustin Pop
  return retcode
891 a8083063 Iustin Pop
892 a8083063 Iustin Pop
893 7767bbf5 Manuel Franceschini
def SetInstanceParams(opts, args):
894 a8083063 Iustin Pop
  """Modifies an instance.
895 a8083063 Iustin Pop
896 a8083063 Iustin Pop
  All parameters take effect only at the next restart of the instance.
897 a8083063 Iustin Pop
898 a8083063 Iustin Pop
  Args:
899 a8083063 Iustin Pop
    opts - class with options as members
900 a8083063 Iustin Pop
    args - list with a single element, the instance name
901 a8083063 Iustin Pop
  Opts used:
902 1862d460 Alexander Schreiber
    mac - the new MAC address of the instance
903 a8083063 Iustin Pop
904 a8083063 Iustin Pop
  """
905 61be6ba4 Iustin Pop
  if not (opts.ip or opts.bridge or opts.mac or
906 61be6ba4 Iustin Pop
          opts.hypervisor or opts.beparams):
907 3a24c527 Iustin Pop
    ToStderr("Please give at least one of the parameters.")
908 a8083063 Iustin Pop
    return 1
909 a8083063 Iustin Pop
910 61be6ba4 Iustin Pop
  if constants.BE_MEMORY in opts.beparams:
911 61be6ba4 Iustin Pop
    opts.beparams[constants.BE_MEMORY] = utils.ParseUnit(
912 61be6ba4 Iustin Pop
      opts.beparams[constants.BE_MEMORY])
913 61be6ba4 Iustin Pop
914 338e51e8 Iustin Pop
  op = opcodes.OpSetInstanceParams(instance_name=args[0],
915 338e51e8 Iustin Pop
                                   ip=opts.ip,
916 7767bbf5 Manuel Franceschini
                                   bridge=opts.bridge, mac=opts.mac,
917 74409b12 Iustin Pop
                                   hvparams=opts.hypervisor,
918 338e51e8 Iustin Pop
                                   beparams=opts.beparams,
919 4300c4b6 Guido Trotter
                                   force=opts.force)
920 31a853d2 Iustin Pop
921 6340bb0a Iustin Pop
  # even if here we process the result, we allow submit only
922 6340bb0a Iustin Pop
  result = SubmitOrSend(op, opts)
923 a8083063 Iustin Pop
924 a8083063 Iustin Pop
  if result:
925 3a24c527 Iustin Pop
    ToStdout("Modified instance %s", args[0])
926 a8083063 Iustin Pop
    for param, data in result:
927 3a24c527 Iustin Pop
      ToStdout(" - %-5s -> %s", param, data)
928 3a24c527 Iustin Pop
    ToStdout("Please don't forget that these parameters take effect"
929 3a24c527 Iustin Pop
             " only at the next start of the instance.")
930 a8083063 Iustin Pop
  return 0
931 a8083063 Iustin Pop
932 a8083063 Iustin Pop
933 a8083063 Iustin Pop
# options used in more than one cmd
934 a8083063 Iustin Pop
node_opt = make_option("-n", "--node", dest="node", help="Target node",
935 a8083063 Iustin Pop
                       metavar="<node>")
936 a8083063 Iustin Pop
937 d0834de3 Michael Hanselmann
os_opt = cli_option("-o", "--os-type", dest="os", help="What OS to run",
938 739ecd56 Michael Hanselmann
                    metavar="<os>")
939 d0834de3 Michael Hanselmann
940 312ac745 Iustin Pop
# multi-instance selection options
941 804a1e8e Iustin Pop
m_force_multi = make_option("--force-multiple", dest="force_multi",
942 804a1e8e Iustin Pop
                            help="Do not ask for confirmation when more than"
943 804a1e8e Iustin Pop
                            " one instance is affected",
944 804a1e8e Iustin Pop
                            action="store_true", default=False)
945 804a1e8e Iustin Pop
946 312ac745 Iustin Pop
m_pri_node_opt = make_option("--primary", dest="multi_mode",
947 312ac745 Iustin Pop
                             help="Filter by nodes (primary only)",
948 312ac745 Iustin Pop
                             const=_SHUTDOWN_NODES_PRI, action="store_const")
949 312ac745 Iustin Pop
950 312ac745 Iustin Pop
m_sec_node_opt = make_option("--secondary", dest="multi_mode",
951 312ac745 Iustin Pop
                             help="Filter by nodes (secondary only)",
952 312ac745 Iustin Pop
                             const=_SHUTDOWN_NODES_SEC, action="store_const")
953 312ac745 Iustin Pop
954 312ac745 Iustin Pop
m_node_opt = make_option("--node", dest="multi_mode",
955 312ac745 Iustin Pop
                         help="Filter by nodes (primary and secondary)",
956 312ac745 Iustin Pop
                         const=_SHUTDOWN_NODES_BOTH, action="store_const")
957 312ac745 Iustin Pop
958 312ac745 Iustin Pop
m_clust_opt = make_option("--all", dest="multi_mode",
959 312ac745 Iustin Pop
                          help="Select all instances in the cluster",
960 312ac745 Iustin Pop
                          const=_SHUTDOWN_CLUSTER, action="store_const")
961 312ac745 Iustin Pop
962 312ac745 Iustin Pop
m_inst_opt = make_option("--instance", dest="multi_mode",
963 312ac745 Iustin Pop
                         help="Filter by instance name [default]",
964 312ac745 Iustin Pop
                         const=_SHUTDOWN_INSTANCES, action="store_const")
965 312ac745 Iustin Pop
966 312ac745 Iustin Pop
967 a8083063 Iustin Pop
# this is defined separately due to readability only
968 a8083063 Iustin Pop
add_opts = [
969 a8083063 Iustin Pop
  DEBUG_OPT,
970 60d49723 Michael Hanselmann
  make_option("-n", "--node", dest="node",
971 60d49723 Michael Hanselmann
              help="Target node and optional secondary node",
972 60d49723 Michael Hanselmann
              metavar="<pnode>[:<snode>]"),
973 b9ac33e9 Iustin Pop
  cli_option("-s", "--os-size", dest="size", help="Disk size, in MiB unless"
974 b9ac33e9 Iustin Pop
             " a suffix is used",
975 a8083063 Iustin Pop
             default=20 * 1024, type="unit", metavar="<size>"),
976 b9ac33e9 Iustin Pop
  cli_option("--swap-size", dest="swap", help="Swap size, in MiB unless a"
977 b9ac33e9 Iustin Pop
             " suffix is used",
978 a8083063 Iustin Pop
             default=4 * 1024, type="unit", metavar="<size>"),
979 d0834de3 Michael Hanselmann
  os_opt,
980 338e51e8 Iustin Pop
  keyval_option("-B", "--backend", dest="beparams",
981 338e51e8 Iustin Pop
                type="keyval", default={},
982 338e51e8 Iustin Pop
                help="Backend parameters"),
983 a8083063 Iustin Pop
  make_option("-t", "--disk-template", dest="disk_template",
984 45873083 Manuel Franceschini
              help="Custom disk setup (diskless, file, plain or drbd)",
985 f9193417 Iustin Pop
              default=None, metavar="TEMPL"),
986 a8083063 Iustin Pop
  make_option("-i", "--ip", dest="ip",
987 a8083063 Iustin Pop
              help="IP address ('none' [default], 'auto', or specify address)",
988 a8083063 Iustin Pop
              default='none', type="string", metavar="<ADDRESS>"),
989 1862d460 Alexander Schreiber
  make_option("--mac", dest="mac",
990 1862d460 Alexander Schreiber
              help="MAC address ('auto' [default], or specify address)",
991 1862d460 Alexander Schreiber
              default='auto', type="string", metavar="<MACADDRESS>"),
992 a8083063 Iustin Pop
  make_option("--no-wait-for-sync", dest="wait_for_sync", default=True,
993 a8083063 Iustin Pop
              action="store_false", help="Don't wait for sync (DANGEROUS!)"),
994 a8083063 Iustin Pop
  make_option("-b", "--bridge", dest="bridge",
995 a8083063 Iustin Pop
              help="Bridge to connect this instance to",
996 bdd55f71 Iustin Pop
              default=None, metavar="<bridge>"),
997 bdd55f71 Iustin Pop
  make_option("--no-start", dest="start", default=True,
998 bdd55f71 Iustin Pop
              action="store_false", help="Don't start the instance after"
999 bdd55f71 Iustin Pop
              " creation"),
1000 bdd55f71 Iustin Pop
  make_option("--no-ip-check", dest="ip_check", default=True,
1001 bdd55f71 Iustin Pop
              action="store_false", help="Don't check that the instance's IP"
1002 bdd55f71 Iustin Pop
              " is alive (only valid with --no-start)"),
1003 45873083 Manuel Franceschini
  make_option("--file-storage-dir", dest="file_storage_dir",
1004 45873083 Manuel Franceschini
              help="Relative path under default cluster-wide file storage dir"
1005 45873083 Manuel Franceschini
              " to store file-based disks", default=None,
1006 45873083 Manuel Franceschini
              metavar="<DIR>"),
1007 45873083 Manuel Franceschini
  make_option("--file-driver", dest="file_driver", help="Driver to use"
1008 538475ca Iustin Pop
              " for image files", default="loop", metavar="<DRIVER>"),
1009 538475ca Iustin Pop
  make_option("--iallocator", metavar="<NAME>",
1010 538475ca Iustin Pop
              help="Select nodes for the instance automatically using the"
1011 538475ca Iustin Pop
              " <NAME> iallocator plugin", default=None, type="string"),
1012 6785674e Iustin Pop
  ikv_option("-H", "--hypervisor", dest="hypervisor",
1013 6785674e Iustin Pop
              help="Hypervisor and hypervisor options, in the format"
1014 6785674e Iustin Pop
              " hypervisor:option=value,option=value,...", default=None,
1015 6785674e Iustin Pop
              type="identkeyval"),
1016 6340bb0a Iustin Pop
  SUBMIT_OPT,
1017 a8083063 Iustin Pop
  ]
1018 a8083063 Iustin Pop
1019 a8083063 Iustin Pop
commands = {
1020 a8083063 Iustin Pop
  'add': (AddInstance, ARGS_ONE, add_opts,
1021 bdb7d4e8 Michael Hanselmann
          "[...] -t disk-type -n node[:secondary-node] -o os-type <name>",
1022 a8083063 Iustin Pop
          "Creates and adds a new instance to the cluster"),
1023 0d0e9090 René Nussbaumer
  'batch-create': (BatchCreate, ARGS_ONE,
1024 0d0e9090 René Nussbaumer
                   [DEBUG_OPT],
1025 0d0e9090 René Nussbaumer
                   "<instances_file.json>",
1026 0d0e9090 René Nussbaumer
                   "Create a bunch of instances based on specs in the file."),
1027 51c6e7b5 Michael Hanselmann
  'console': (ConnectToInstanceConsole, ARGS_ONE,
1028 51c6e7b5 Michael Hanselmann
              [DEBUG_OPT,
1029 51c6e7b5 Michael Hanselmann
               make_option("--show-cmd", dest="show_command",
1030 51c6e7b5 Michael Hanselmann
                           action="store_true", default=False,
1031 51c6e7b5 Michael Hanselmann
                           help=("Show command instead of executing it"))],
1032 9a033156 Iustin Pop
              "[--show-cmd] <instance>",
1033 a8083063 Iustin Pop
              "Opens a console on the specified instance"),
1034 80de0e3f Iustin Pop
  'failover': (FailoverInstance, ARGS_ONE,
1035 fe7b0351 Michael Hanselmann
               [DEBUG_OPT, FORCE_OPT,
1036 a8083063 Iustin Pop
                make_option("--ignore-consistency", dest="ignore_consistency",
1037 a8083063 Iustin Pop
                            action="store_true", default=False,
1038 a8083063 Iustin Pop
                            help="Ignore the consistency of the disks on"
1039 a8083063 Iustin Pop
                            " the secondary"),
1040 6340bb0a Iustin Pop
                SUBMIT_OPT,
1041 a8083063 Iustin Pop
                ],
1042 9a033156 Iustin Pop
               "[-f] <instance>",
1043 a8083063 Iustin Pop
               "Stops the instance and starts it on the backup node, using"
1044 99e2be3b Guido Trotter
               " the remote mirror (only for instances of type drbd)"),
1045 57821cac Iustin Pop
  'info': (ShowInstanceConfig, ARGS_ANY,
1046 57821cac Iustin Pop
           [DEBUG_OPT,
1047 57821cac Iustin Pop
            make_option("-s", "--static", dest="static",
1048 57821cac Iustin Pop
                        action="store_true", default=False,
1049 57821cac Iustin Pop
                        help="Only show configuration data, not runtime data"),
1050 57821cac Iustin Pop
            ], "[-s] [<instance>...]",
1051 57821cac Iustin Pop
           "Show information on the specified instance(s)"),
1052 a8083063 Iustin Pop
  'list': (ListInstances, ARGS_NONE,
1053 9a033156 Iustin Pop
           [DEBUG_OPT, NOHDR_OPT, SEP_OPT, USEUNITS_OPT, FIELDS_OPT], "",
1054 d8052456 Iustin Pop
           "Lists the instances and their status. The available fields are"
1055 d8052456 Iustin Pop
           " (see the man page for details): status, oper_state, oper_ram,"
1056 d8a4b51d Iustin Pop
           " name, os, pnode, snodes, admin_state, admin_ram, disk_template,"
1057 e69d05fd Iustin Pop
           " ip, mac, bridge, sda_size, sdb_size, vcpus, serial_no,"
1058 e69d05fd Iustin Pop
           " hypervisor."
1059 38d7239a Iustin Pop
           " The default field"
1060 48c4dfa8 Iustin Pop
           " list is (in order): %s." % ", ".join(_LIST_DEF_FIELDS),
1061 48c4dfa8 Iustin Pop
           ),
1062 20e23543 Alexander Schreiber
  'reinstall': (ReinstallInstance, ARGS_ONE,
1063 20e23543 Alexander Schreiber
                [DEBUG_OPT, FORCE_OPT, os_opt,
1064 20e23543 Alexander Schreiber
                 make_option("--select-os", dest="select_os",
1065 20e23543 Alexander Schreiber
                             action="store_true", default=False,
1066 20e23543 Alexander Schreiber
                             help="Interactive OS reinstall, lists available"
1067 6340bb0a Iustin Pop
                             " OS templates for selection"),
1068 6340bb0a Iustin Pop
                 SUBMIT_OPT,
1069 6340bb0a Iustin Pop
                 ],
1070 9a033156 Iustin Pop
                "[-f] <instance>", "Reinstall a stopped instance"),
1071 1d67656e Iustin Pop
  'remove': (RemoveInstance, ARGS_ONE,
1072 1d67656e Iustin Pop
             [DEBUG_OPT, FORCE_OPT,
1073 1d67656e Iustin Pop
              make_option("--ignore-failures", dest="ignore_failures",
1074 1d67656e Iustin Pop
                          action="store_true", default=False,
1075 1d67656e Iustin Pop
                          help=("Remove the instance from the cluster even"
1076 1d67656e Iustin Pop
                                " if there are failures during the removal"
1077 1d67656e Iustin Pop
                                " process (shutdown, disk removal, etc.)")),
1078 6340bb0a Iustin Pop
              SUBMIT_OPT,
1079 1d67656e Iustin Pop
              ],
1080 9a033156 Iustin Pop
             "[-f] <instance>", "Shuts down the instance and removes it"),
1081 decd5f45 Iustin Pop
  'rename': (RenameInstance, ARGS_FIXED(2),
1082 decd5f45 Iustin Pop
             [DEBUG_OPT,
1083 decd5f45 Iustin Pop
              make_option("--no-ip-check", dest="ignore_ip",
1084 decd5f45 Iustin Pop
                          help="Do not check that the IP of the new name"
1085 decd5f45 Iustin Pop
                          " is alive",
1086 decd5f45 Iustin Pop
                          default=False, action="store_true"),
1087 6340bb0a Iustin Pop
              SUBMIT_OPT,
1088 decd5f45 Iustin Pop
              ],
1089 9a033156 Iustin Pop
             "<instance> <new_name>", "Rename the instance"),
1090 a8083063 Iustin Pop
  'replace-disks': (ReplaceDisks, ARGS_ONE,
1091 a8083063 Iustin Pop
                    [DEBUG_OPT,
1092 a8083063 Iustin Pop
                     make_option("-n", "--new-secondary", dest="new_secondary",
1093 a9e0c397 Iustin Pop
                                 help=("New secondary node (for secondary"
1094 a9e0c397 Iustin Pop
                                       " node change)"), metavar="NODE"),
1095 a9e0c397 Iustin Pop
                     make_option("-p", "--on-primary", dest="on_primary",
1096 a9e0c397 Iustin Pop
                                 default=False, action="store_true",
1097 a9e0c397 Iustin Pop
                                 help=("Replace the disk(s) on the primary"
1098 12c3449a Michael Hanselmann
                                       " node (only for the drbd template)")),
1099 a9e0c397 Iustin Pop
                     make_option("-s", "--on-secondary", dest="on_secondary",
1100 a9e0c397 Iustin Pop
                                 default=False, action="store_true",
1101 a9e0c397 Iustin Pop
                                 help=("Replace the disk(s) on the secondary"
1102 12c3449a Michael Hanselmann
                                       " node (only for the drbd template)")),
1103 a9e0c397 Iustin Pop
                     make_option("--disks", dest="disks", default=None,
1104 a9e0c397 Iustin Pop
                                 help=("Comma-separated list of disks"
1105 a9e0c397 Iustin Pop
                                       " to replace (e.g. sda) (optional,"
1106 a9e0c397 Iustin Pop
                                       " defaults to all disks")),
1107 b6e82a65 Iustin Pop
                     make_option("--iallocator", metavar="<NAME>",
1108 b6e82a65 Iustin Pop
                                 help="Select new secondary for the instance"
1109 b6e82a65 Iustin Pop
                                 " automatically using the"
1110 b6e82a65 Iustin Pop
                                 " <NAME> iallocator plugin (enables"
1111 b6e82a65 Iustin Pop
                                 " secondary node replacement)",
1112 b6e82a65 Iustin Pop
                                 default=None, type="string"),
1113 6340bb0a Iustin Pop
                     SUBMIT_OPT,
1114 a9e0c397 Iustin Pop
                     ],
1115 9a033156 Iustin Pop
                    "[-s|-p|-n NODE] <instance>",
1116 a8083063 Iustin Pop
                    "Replaces all disks for the instance"),
1117 7767bbf5 Manuel Franceschini
  'modify': (SetInstanceParams, ARGS_ONE,
1118 fe7b0351 Michael Hanselmann
             [DEBUG_OPT, FORCE_OPT,
1119 a8083063 Iustin Pop
              make_option("-i", "--ip", dest="ip",
1120 a8083063 Iustin Pop
                          help="IP address ('none' or numeric IP)",
1121 a8083063 Iustin Pop
                          default=None, type="string", metavar="<ADDRESS>"),
1122 a8083063 Iustin Pop
              make_option("-b", "--bridge", dest="bridge",
1123 a8083063 Iustin Pop
                          help="Bridge to connect this instance to",
1124 decd5f45 Iustin Pop
                          default=None, type="string", metavar="<bridge>"),
1125 1862d460 Alexander Schreiber
              make_option("--mac", dest="mac",
1126 1862d460 Alexander Schreiber
                          help="MAC address", default=None,
1127 1862d460 Alexander Schreiber
                          type="string", metavar="<MACADDRESS>"),
1128 74409b12 Iustin Pop
              keyval_option("-H", "--hypervisor", type="keyval",
1129 74409b12 Iustin Pop
                            default={}, dest="hypervisor",
1130 74409b12 Iustin Pop
                            help="Change hypervisor parameters"),
1131 61be6ba4 Iustin Pop
              keyval_option("-B", "--backend", type="keyval",
1132 61be6ba4 Iustin Pop
                            default={}, dest="beparams",
1133 61be6ba4 Iustin Pop
                            help="Change backend parameters"),
1134 6340bb0a Iustin Pop
              SUBMIT_OPT,
1135 a8083063 Iustin Pop
              ],
1136 9a033156 Iustin Pop
             "<instance>", "Alters the parameters of an instance"),
1137 312ac745 Iustin Pop
  'shutdown': (ShutdownInstance, ARGS_ANY,
1138 312ac745 Iustin Pop
               [DEBUG_OPT, m_node_opt, m_pri_node_opt, m_sec_node_opt,
1139 6340bb0a Iustin Pop
                m_clust_opt, m_inst_opt, m_force_multi,
1140 6340bb0a Iustin Pop
                SUBMIT_OPT,
1141 6340bb0a Iustin Pop
                ],
1142 9a033156 Iustin Pop
               "<instance>", "Stops an instance"),
1143 312ac745 Iustin Pop
  'startup': (StartupInstance, ARGS_ANY,
1144 804a1e8e Iustin Pop
              [DEBUG_OPT, FORCE_OPT, m_force_multi,
1145 a8083063 Iustin Pop
               make_option("-e", "--extra", dest="extra_args",
1146 a8083063 Iustin Pop
                           help="Extra arguments for the instance's kernel",
1147 a8083063 Iustin Pop
                           default=None, type="string", metavar="<PARAMS>"),
1148 312ac745 Iustin Pop
               m_node_opt, m_pri_node_opt, m_sec_node_opt,
1149 312ac745 Iustin Pop
               m_clust_opt, m_inst_opt,
1150 6340bb0a Iustin Pop
               SUBMIT_OPT,
1151 a8083063 Iustin Pop
               ],
1152 9a033156 Iustin Pop
            "<instance>", "Starts an instance"),
1153 579d4337 Alexander Schreiber
1154 579d4337 Alexander Schreiber
  'reboot': (RebootInstance, ARGS_ANY,
1155 579d4337 Alexander Schreiber
              [DEBUG_OPT, m_force_multi,
1156 579d4337 Alexander Schreiber
               make_option("-e", "--extra", dest="extra_args",
1157 579d4337 Alexander Schreiber
                           help="Extra arguments for the instance's kernel",
1158 579d4337 Alexander Schreiber
                           default=None, type="string", metavar="<PARAMS>"),
1159 579d4337 Alexander Schreiber
               make_option("-t", "--type", dest="reboot_type",
1160 579d4337 Alexander Schreiber
                           help="Type of reboot: soft/hard/full",
1161 bf2fd71e Alexander Schreiber
                           default=constants.INSTANCE_REBOOT_HARD,
1162 579d4337 Alexander Schreiber
                           type="string", metavar="<REBOOT>"),
1163 579d4337 Alexander Schreiber
               make_option("--ignore-secondaries", dest="ignore_secondaries",
1164 579d4337 Alexander Schreiber
                           default=False, action="store_true",
1165 579d4337 Alexander Schreiber
                           help="Ignore errors from secondaries"),
1166 579d4337 Alexander Schreiber
               m_node_opt, m_pri_node_opt, m_sec_node_opt,
1167 579d4337 Alexander Schreiber
               m_clust_opt, m_inst_opt,
1168 6340bb0a Iustin Pop
               SUBMIT_OPT,
1169 579d4337 Alexander Schreiber
               ],
1170 9a033156 Iustin Pop
            "<instance>", "Reboots an instance"),
1171 6340bb0a Iustin Pop
  'activate-disks': (ActivateDisks, ARGS_ONE, [DEBUG_OPT, SUBMIT_OPT],
1172 9a033156 Iustin Pop
                     "<instance>",
1173 a8083063 Iustin Pop
                     "Activate an instance's disks"),
1174 6340bb0a Iustin Pop
  'deactivate-disks': (DeactivateDisks, ARGS_ONE, [DEBUG_OPT, SUBMIT_OPT],
1175 9a033156 Iustin Pop
                       "<instance>",
1176 a8083063 Iustin Pop
                       "Deactivate an instance's disks"),
1177 6605411d Iustin Pop
  'grow-disk': (GrowDisk, ARGS_FIXED(3),
1178 6605411d Iustin Pop
                [DEBUG_OPT, SUBMIT_OPT,
1179 6605411d Iustin Pop
                 make_option("--no-wait-for-sync",
1180 6605411d Iustin Pop
                             dest="wait_for_sync", default=True,
1181 6605411d Iustin Pop
                             action="store_false",
1182 6605411d Iustin Pop
                             help="Don't wait for sync (DANGEROUS!)"),
1183 6605411d Iustin Pop
                 ],
1184 c6e911bc Iustin Pop
                "<instance> <disk> <size>", "Grow an instance's disk"),
1185 846baef9 Iustin Pop
  'list-tags': (ListTags, ARGS_ONE, [DEBUG_OPT],
1186 746ea1da Guido Trotter
                "<instance_name>", "List the tags of the given instance"),
1187 810c50b7 Iustin Pop
  'add-tags': (AddTags, ARGS_ATLEAST(1), [DEBUG_OPT, TAG_SRC_OPT],
1188 746ea1da Guido Trotter
               "<instance_name> tag...", "Add tags to the given instance"),
1189 810c50b7 Iustin Pop
  'remove-tags': (RemoveTags, ARGS_ATLEAST(1), [DEBUG_OPT, TAG_SRC_OPT],
1190 746ea1da Guido Trotter
                  "<instance_name> tag...", "Remove tags from given instance"),
1191 a8083063 Iustin Pop
  }
1192 a8083063 Iustin Pop
1193 dbfd89dd Guido Trotter
aliases = {
1194 dbfd89dd Guido Trotter
  'activate_block_devs': 'activate-disks',
1195 00ce8b29 Guido Trotter
  'replace_disks': 'replace-disks',
1196 536fda25 Guido Trotter
  'start': 'startup',
1197 536fda25 Guido Trotter
  'stop': 'shutdown',
1198 dbfd89dd Guido Trotter
  }
1199 dbfd89dd Guido Trotter
1200 a8083063 Iustin Pop
if __name__ == '__main__':
1201 dbfd89dd Guido Trotter
  sys.exit(GenericMain(commands, aliases=aliases,
1202 846baef9 Iustin Pop
                       override={"tag_type": constants.TAG_INSTANCE}))