Statistics
| Branch: | Tag: | Revision:

root / scripts / gnt-instance @ 0d0e9090

History | View | Annotate | Download (43.2 kB)

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