Statistics
| Branch: | Tag: | Revision:

root / lib / client / gnt_instance.py @ 66d1f035

History | View | Annotate | Download (51.6 kB)

1 e792102d Michael Hanselmann
#
2 a8083063 Iustin Pop
#
3 a8083063 Iustin Pop
4 60472d29 Iustin Pop
# Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011 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 7260cfbe Iustin Pop
"""Instance related commands"""
22 a8083063 Iustin Pop
23 7260cfbe Iustin Pop
# pylint: disable-msg=W0401,W0614,C0103
24 2f79bd34 Iustin Pop
# W0401: Wildcard import ganeti.cli
25 2f79bd34 Iustin Pop
# W0614: Unused import %s from wildcard import (since we need cli)
26 7260cfbe Iustin Pop
# C0103: Invalid name gnt-instance
27 2f79bd34 Iustin Pop
28 312ac745 Iustin Pop
import itertools
29 0d0e9090 René Nussbaumer
import simplejson
30 25ce3ec4 Michael Hanselmann
import logging
31 a8083063 Iustin Pop
from cStringIO import StringIO
32 a8083063 Iustin Pop
33 a8083063 Iustin Pop
from ganeti.cli import *
34 a8083063 Iustin Pop
from ganeti import opcodes
35 a8083063 Iustin Pop
from ganeti import constants
36 e2736e40 Guido Trotter
from ganeti import compat
37 a8083063 Iustin Pop
from ganeti import utils
38 312ac745 Iustin Pop
from ganeti import errors
39 a744b676 Manuel Franceschini
from ganeti import netutils
40 25ce3ec4 Michael Hanselmann
from ganeti import ssh
41 25ce3ec4 Michael Hanselmann
from ganeti import objects
42 312ac745 Iustin Pop
43 312ac745 Iustin Pop
44 312ac745 Iustin Pop
_SHUTDOWN_CLUSTER = "cluster"
45 312ac745 Iustin Pop
_SHUTDOWN_NODES_BOTH = "nodes"
46 312ac745 Iustin Pop
_SHUTDOWN_NODES_PRI = "nodes-pri"
47 312ac745 Iustin Pop
_SHUTDOWN_NODES_SEC = "nodes-sec"
48 39dfd93e René Nussbaumer
_SHUTDOWN_NODES_BOTH_BY_TAGS = "nodes-by-tags"
49 39dfd93e René Nussbaumer
_SHUTDOWN_NODES_PRI_BY_TAGS = "nodes-pri-by-tags"
50 39dfd93e René Nussbaumer
_SHUTDOWN_NODES_SEC_BY_TAGS = "nodes-sec-by-tags"
51 312ac745 Iustin Pop
_SHUTDOWN_INSTANCES = "instances"
52 39dfd93e René Nussbaumer
_SHUTDOWN_INSTANCES_BY_TAGS = "instances-by-tags"
53 39dfd93e René Nussbaumer
54 39dfd93e René Nussbaumer
_SHUTDOWN_NODES_TAGS_MODES = (
55 39dfd93e René Nussbaumer
    _SHUTDOWN_NODES_BOTH_BY_TAGS,
56 39dfd93e René Nussbaumer
    _SHUTDOWN_NODES_PRI_BY_TAGS,
57 39dfd93e René Nussbaumer
    _SHUTDOWN_NODES_SEC_BY_TAGS)
58 312ac745 Iustin Pop
59 7c0d6283 Michael Hanselmann
60 7232c04c Iustin Pop
#: default list of options for L{ListInstances}
61 48c4dfa8 Iustin Pop
_LIST_DEF_FIELDS = [
62 e69d05fd Iustin Pop
  "name", "hypervisor", "os", "pnode", "status", "oper_ram",
63 48c4dfa8 Iustin Pop
  ]
64 48c4dfa8 Iustin Pop
65 bdb7d4e8 Michael Hanselmann
66 479636a3 Iustin Pop
def _ExpandMultiNames(mode, names, client=None):
67 312ac745 Iustin Pop
  """Expand the given names using the passed mode.
68 312ac745 Iustin Pop

69 312ac745 Iustin Pop
  For _SHUTDOWN_CLUSTER, all instances will be returned. For
70 312ac745 Iustin Pop
  _SHUTDOWN_NODES_PRI/SEC, all instances having those nodes as
71 7232c04c Iustin Pop
  primary/secondary will be returned. For _SHUTDOWN_NODES_BOTH, all
72 312ac745 Iustin Pop
  instances having those nodes as either primary or secondary will be
73 312ac745 Iustin Pop
  returned. For _SHUTDOWN_INSTANCES, the given instances will be
74 312ac745 Iustin Pop
  returned.
75 312ac745 Iustin Pop

76 7232c04c Iustin Pop
  @param mode: one of L{_SHUTDOWN_CLUSTER}, L{_SHUTDOWN_NODES_BOTH},
77 7232c04c Iustin Pop
      L{_SHUTDOWN_NODES_PRI}, L{_SHUTDOWN_NODES_SEC} or
78 7232c04c Iustin Pop
      L{_SHUTDOWN_INSTANCES}
79 7232c04c Iustin Pop
  @param names: a list of names; for cluster, it must be empty,
80 7232c04c Iustin Pop
      and for node and instance it must be a list of valid item
81 7232c04c Iustin Pop
      names (short names are valid as usual, e.g. node1 instead of
82 7232c04c Iustin Pop
      node1.example.com)
83 7232c04c Iustin Pop
  @rtype: list
84 7232c04c Iustin Pop
  @return: the list of names after the expansion
85 7232c04c Iustin Pop
  @raise errors.ProgrammerError: for unknown selection type
86 7232c04c Iustin Pop
  @raise errors.OpPrereqError: for invalid input parameters
87 7232c04c Iustin Pop

88 312ac745 Iustin Pop
  """
89 7260cfbe Iustin Pop
  # pylint: disable-msg=W0142
90 39dfd93e René Nussbaumer
91 479636a3 Iustin Pop
  if client is None:
92 479636a3 Iustin Pop
    client = GetClient()
93 312ac745 Iustin Pop
  if mode == _SHUTDOWN_CLUSTER:
94 312ac745 Iustin Pop
    if names:
95 debac808 Iustin Pop
      raise errors.OpPrereqError("Cluster filter mode takes no arguments",
96 debac808 Iustin Pop
                                 errors.ECODE_INVAL)
97 ec79568d Iustin Pop
    idata = client.QueryInstances([], ["name"], False)
98 312ac745 Iustin Pop
    inames = [row[0] for row in idata]
99 312ac745 Iustin Pop
100 312ac745 Iustin Pop
  elif mode in (_SHUTDOWN_NODES_BOTH,
101 312ac745 Iustin Pop
                _SHUTDOWN_NODES_PRI,
102 39dfd93e René Nussbaumer
                _SHUTDOWN_NODES_SEC) + _SHUTDOWN_NODES_TAGS_MODES:
103 39dfd93e René Nussbaumer
    if mode in _SHUTDOWN_NODES_TAGS_MODES:
104 39dfd93e René Nussbaumer
      if not names:
105 39dfd93e René Nussbaumer
        raise errors.OpPrereqError("No node tags passed", errors.ECODE_INVAL)
106 39dfd93e René Nussbaumer
      ndata = client.QueryNodes([], ["name", "pinst_list",
107 39dfd93e René Nussbaumer
                                     "sinst_list", "tags"], False)
108 39dfd93e René Nussbaumer
      ndata = [row for row in ndata if set(row[3]).intersection(names)]
109 39dfd93e René Nussbaumer
    else:
110 39dfd93e René Nussbaumer
      if not names:
111 39dfd93e René Nussbaumer
        raise errors.OpPrereqError("No node names passed", errors.ECODE_INVAL)
112 39dfd93e René Nussbaumer
      ndata = client.QueryNodes(names, ["name", "pinst_list", "sinst_list"],
113 77921a95 Iustin Pop
                              False)
114 39dfd93e René Nussbaumer
115 312ac745 Iustin Pop
    ipri = [row[1] for row in ndata]
116 312ac745 Iustin Pop
    pri_names = list(itertools.chain(*ipri))
117 312ac745 Iustin Pop
    isec = [row[2] for row in ndata]
118 312ac745 Iustin Pop
    sec_names = list(itertools.chain(*isec))
119 39dfd93e René Nussbaumer
    if mode in (_SHUTDOWN_NODES_BOTH, _SHUTDOWN_NODES_BOTH_BY_TAGS):
120 312ac745 Iustin Pop
      inames = pri_names + sec_names
121 39dfd93e René Nussbaumer
    elif mode in (_SHUTDOWN_NODES_PRI, _SHUTDOWN_NODES_PRI_BY_TAGS):
122 312ac745 Iustin Pop
      inames = pri_names
123 39dfd93e René Nussbaumer
    elif mode in (_SHUTDOWN_NODES_SEC, _SHUTDOWN_NODES_SEC_BY_TAGS):
124 312ac745 Iustin Pop
      inames = sec_names
125 312ac745 Iustin Pop
    else:
126 312ac745 Iustin Pop
      raise errors.ProgrammerError("Unhandled shutdown type")
127 312ac745 Iustin Pop
  elif mode == _SHUTDOWN_INSTANCES:
128 312ac745 Iustin Pop
    if not names:
129 debac808 Iustin Pop
      raise errors.OpPrereqError("No instance names passed",
130 debac808 Iustin Pop
                                 errors.ECODE_INVAL)
131 ec79568d Iustin Pop
    idata = client.QueryInstances(names, ["name"], False)
132 312ac745 Iustin Pop
    inames = [row[0] for row in idata]
133 39dfd93e René Nussbaumer
  elif mode == _SHUTDOWN_INSTANCES_BY_TAGS:
134 39dfd93e René Nussbaumer
    if not names:
135 39dfd93e René Nussbaumer
      raise errors.OpPrereqError("No instance tags passed",
136 39dfd93e René Nussbaumer
                                 errors.ECODE_INVAL)
137 39dfd93e René Nussbaumer
    idata = client.QueryInstances([], ["name", "tags"], False)
138 39dfd93e René Nussbaumer
    inames = [row[0] for row in idata if set(row[1]).intersection(names)]
139 312ac745 Iustin Pop
  else:
140 debac808 Iustin Pop
    raise errors.OpPrereqError("Unknown mode '%s'" % mode, errors.ECODE_INVAL)
141 312ac745 Iustin Pop
142 312ac745 Iustin Pop
  return inames
143 a8083063 Iustin Pop
144 a8083063 Iustin Pop
145 a76f0c4a Iustin Pop
def _EnsureInstancesExist(client, names):
146 a76f0c4a Iustin Pop
  """Check for and ensure the given instance names exist.
147 a76f0c4a Iustin Pop

148 a76f0c4a Iustin Pop
  This function will raise an OpPrereqError in case they don't
149 a76f0c4a Iustin Pop
  exist. Otherwise it will exit cleanly.
150 a76f0c4a Iustin Pop

151 f2fd87d7 Iustin Pop
  @type client: L{ganeti.luxi.Client}
152 a76f0c4a Iustin Pop
  @param client: the client to use for the query
153 a76f0c4a Iustin Pop
  @type names: list
154 a76f0c4a Iustin Pop
  @param names: the list of instance names to query
155 a76f0c4a Iustin Pop
  @raise errors.OpPrereqError: in case any instance is missing
156 a76f0c4a Iustin Pop

157 a76f0c4a Iustin Pop
  """
158 f2af0bec Iustin Pop
  # TODO: change LUInstanceQuery to that it actually returns None
159 a76f0c4a Iustin Pop
  # instead of raising an exception, or devise a better mechanism
160 ec79568d Iustin Pop
  result = client.QueryInstances(names, ["name"], False)
161 a76f0c4a Iustin Pop
  for orig_name, row in zip(names, result):
162 a76f0c4a Iustin Pop
    if row[0] is None:
163 debac808 Iustin Pop
      raise errors.OpPrereqError("Instance '%s' does not exist" % orig_name,
164 debac808 Iustin Pop
                                 errors.ECODE_NOENT)
165 a76f0c4a Iustin Pop
166 a76f0c4a Iustin Pop
167 1c5945b6 Iustin Pop
def GenericManyOps(operation, fn):
168 1c5945b6 Iustin Pop
  """Generic multi-instance operations.
169 1c5945b6 Iustin Pop

170 1c5945b6 Iustin Pop
  The will return a wrapper that processes the options and arguments
171 1c5945b6 Iustin Pop
  given, and uses the passed function to build the opcode needed for
172 1c5945b6 Iustin Pop
  the specific operation. Thus all the generic loop/confirmation code
173 1c5945b6 Iustin Pop
  is abstracted into this function.
174 1c5945b6 Iustin Pop

175 1c5945b6 Iustin Pop
  """
176 1c5945b6 Iustin Pop
  def realfn(opts, args):
177 1c5945b6 Iustin Pop
    if opts.multi_mode is None:
178 1c5945b6 Iustin Pop
      opts.multi_mode = _SHUTDOWN_INSTANCES
179 1c5945b6 Iustin Pop
    cl = GetClient()
180 1c5945b6 Iustin Pop
    inames = _ExpandMultiNames(opts.multi_mode, args, client=cl)
181 1c5945b6 Iustin Pop
    if not inames:
182 c37bb2c6 Stephen Shirley
      if opts.multi_mode == _SHUTDOWN_CLUSTER:
183 c37bb2c6 Stephen Shirley
        ToStdout("Cluster is empty, no instances to shutdown")
184 c37bb2c6 Stephen Shirley
        return 0
185 1c5945b6 Iustin Pop
      raise errors.OpPrereqError("Selection filter does not match"
186 debac808 Iustin Pop
                                 " any instances", errors.ECODE_INVAL)
187 1c5945b6 Iustin Pop
    multi_on = opts.multi_mode != _SHUTDOWN_INSTANCES or len(inames) > 1
188 1c5945b6 Iustin Pop
    if not (opts.force_multi or not multi_on
189 25bd815c René Nussbaumer
            or ConfirmOperation(inames, "instances", operation)):
190 1c5945b6 Iustin Pop
      return 1
191 cb573a31 Iustin Pop
    jex = JobExecutor(verbose=multi_on, cl=cl, opts=opts)
192 1c5945b6 Iustin Pop
    for name in inames:
193 1c5945b6 Iustin Pop
      op = fn(name, opts)
194 1c5945b6 Iustin Pop
      jex.QueueJob(name, op)
195 b4e68848 Iustin Pop
    results = jex.WaitOrShow(not opts.submit_only)
196 b4e68848 Iustin Pop
    rcode = compat.all(row[0] for row in results)
197 b4e68848 Iustin Pop
    return int(not rcode)
198 1c5945b6 Iustin Pop
  return realfn
199 1c5945b6 Iustin Pop
200 1c5945b6 Iustin Pop
201 a8083063 Iustin Pop
def ListInstances(opts, args):
202 f5abe9bd Oleksiy Mishchenko
  """List instances and their properties.
203 a8083063 Iustin Pop

204 7232c04c Iustin Pop
  @param opts: the command line options selected by the user
205 7232c04c Iustin Pop
  @type args: list
206 7232c04c Iustin Pop
  @param args: should be an empty list
207 7232c04c Iustin Pop
  @rtype: int
208 7232c04c Iustin Pop
  @return: the desired exit code
209 7232c04c Iustin Pop

210 a8083063 Iustin Pop
  """
211 a4ebd726 Michael Hanselmann
  selected_fields = ParseFields(opts.output, _LIST_DEF_FIELDS)
212 a8083063 Iustin Pop
213 b82c5ff5 Michael Hanselmann
  fmtoverride = dict.fromkeys(["tags", "disk.sizes", "nic.macs", "nic.ips",
214 b82c5ff5 Michael Hanselmann
                               "nic.modes", "nic.links", "nic.bridges",
215 b82c5ff5 Michael Hanselmann
                               "snodes"],
216 b82c5ff5 Michael Hanselmann
                              (lambda value: ",".join(str(item)
217 b82c5ff5 Michael Hanselmann
                                                      for item in value),
218 b82c5ff5 Michael Hanselmann
                               False))
219 a8083063 Iustin Pop
220 b82c5ff5 Michael Hanselmann
  return GenericList(constants.QR_INSTANCE, selected_fields, args, opts.units,
221 b82c5ff5 Michael Hanselmann
                     opts.separator, not opts.no_headers,
222 f0b1bafe Iustin Pop
                     format_override=fmtoverride, verbose=opts.verbose)
223 b82c5ff5 Michael Hanselmann
224 b82c5ff5 Michael Hanselmann
225 b82c5ff5 Michael Hanselmann
def ListInstanceFields(opts, args):
226 b82c5ff5 Michael Hanselmann
  """List instance fields.
227 b82c5ff5 Michael Hanselmann

228 b82c5ff5 Michael Hanselmann
  @param opts: the command line options selected by the user
229 b82c5ff5 Michael Hanselmann
  @type args: list
230 b82c5ff5 Michael Hanselmann
  @param args: fields to list, or empty for all
231 b82c5ff5 Michael Hanselmann
  @rtype: int
232 b82c5ff5 Michael Hanselmann
  @return: the desired exit code
233 b82c5ff5 Michael Hanselmann

234 b82c5ff5 Michael Hanselmann
  """
235 b82c5ff5 Michael Hanselmann
  return GenericListFields(constants.QR_INSTANCE, args, opts.separator,
236 b82c5ff5 Michael Hanselmann
                           not opts.no_headers)
237 a8083063 Iustin Pop
238 a8083063 Iustin Pop
239 a8083063 Iustin Pop
def AddInstance(opts, args):
240 a8083063 Iustin Pop
  """Add an instance to the cluster.
241 a8083063 Iustin Pop

242 d77490c5 Iustin Pop
  This is just a wrapper over GenericInstanceCreate.
243 a8083063 Iustin Pop

244 a8083063 Iustin Pop
  """
245 d77490c5 Iustin Pop
  return GenericInstanceCreate(constants.INSTANCE_CREATE, opts, args)
246 a8083063 Iustin Pop
247 a8083063 Iustin Pop
248 0d0e9090 René Nussbaumer
def BatchCreate(opts, args):
249 7232c04c Iustin Pop
  """Create instances using a definition file.
250 7232c04c Iustin Pop

251 7232c04c Iustin Pop
  This function reads a json file with instances defined
252 7232c04c Iustin Pop
  in the form::
253 7232c04c Iustin Pop

254 7232c04c Iustin Pop
    {"instance-name":{
255 9939547b Iustin Pop
      "disk_size": [20480],
256 7232c04c Iustin Pop
      "template": "drbd",
257 7232c04c Iustin Pop
      "backend": {
258 7232c04c Iustin Pop
        "memory": 512,
259 7232c04c Iustin Pop
        "vcpus": 1 },
260 9939547b Iustin Pop
      "os": "debootstrap",
261 7232c04c Iustin Pop
      "primary_node": "firstnode",
262 7232c04c Iustin Pop
      "secondary_node": "secondnode",
263 7232c04c Iustin Pop
      "iallocator": "dumb"}
264 7232c04c Iustin Pop
    }
265 7232c04c Iustin Pop

266 7232c04c Iustin Pop
  Note that I{primary_node} and I{secondary_node} have precedence over
267 7232c04c Iustin Pop
  I{iallocator}.
268 7232c04c Iustin Pop

269 7232c04c Iustin Pop
  @param opts: the command line options selected by the user
270 7232c04c Iustin Pop
  @type args: list
271 7232c04c Iustin Pop
  @param args: should contain one element, the json filename
272 7232c04c Iustin Pop
  @rtype: int
273 7232c04c Iustin Pop
  @return: the desired exit code
274 0d0e9090 René Nussbaumer

275 0d0e9090 René Nussbaumer
  """
276 9939547b Iustin Pop
  _DEFAULT_SPECS = {"disk_size": [20 * 1024],
277 0d0e9090 René Nussbaumer
                    "backend": {},
278 0d0e9090 René Nussbaumer
                    "iallocator": None,
279 0d0e9090 René Nussbaumer
                    "primary_node": None,
280 0d0e9090 René Nussbaumer
                    "secondary_node": None,
281 a379d9bd Guido Trotter
                    "nics": None,
282 0d0e9090 René Nussbaumer
                    "start": True,
283 0d0e9090 René Nussbaumer
                    "ip_check": True,
284 460d22be Iustin Pop
                    "name_check": True,
285 0d0e9090 René Nussbaumer
                    "hypervisor": None,
286 4082e6f9 Iustin Pop
                    "hvparams": {},
287 0d0e9090 René Nussbaumer
                    "file_storage_dir": None,
288 27ba7eab Guido Trotter
                    "force_variant": False,
289 0d0e9090 René Nussbaumer
                    "file_driver": 'loop'}
290 0d0e9090 René Nussbaumer
291 0d0e9090 René Nussbaumer
  def _PopulateWithDefaults(spec):
292 0d0e9090 René Nussbaumer
    """Returns a new hash combined with default values."""
293 2f79bd34 Iustin Pop
    mydict = _DEFAULT_SPECS.copy()
294 2f79bd34 Iustin Pop
    mydict.update(spec)
295 2f79bd34 Iustin Pop
    return mydict
296 0d0e9090 René Nussbaumer
297 0d0e9090 René Nussbaumer
  def _Validate(spec):
298 0d0e9090 René Nussbaumer
    """Validate the instance specs."""
299 0d0e9090 René Nussbaumer
    # Validate fields required under any circumstances
300 0d0e9090 René Nussbaumer
    for required_field in ('os', 'template'):
301 0d0e9090 René Nussbaumer
      if required_field not in spec:
302 0d0e9090 René Nussbaumer
        raise errors.OpPrereqError('Required field "%s" is missing.' %
303 debac808 Iustin Pop
                                   required_field, errors.ECODE_INVAL)
304 0d0e9090 René Nussbaumer
    # Validate special fields
305 0d0e9090 René Nussbaumer
    if spec['primary_node'] is not None:
306 0d0e9090 René Nussbaumer
      if (spec['template'] in constants.DTS_NET_MIRROR and
307 0d0e9090 René Nussbaumer
          spec['secondary_node'] is None):
308 0d0e9090 René Nussbaumer
        raise errors.OpPrereqError('Template requires secondary node, but'
309 debac808 Iustin Pop
                                   ' there was no secondary provided.',
310 debac808 Iustin Pop
                                   errors.ECODE_INVAL)
311 0d0e9090 René Nussbaumer
    elif spec['iallocator'] is None:
312 0d0e9090 René Nussbaumer
      raise errors.OpPrereqError('You have to provide at least a primary_node'
313 debac808 Iustin Pop
                                 ' or an iallocator.',
314 debac808 Iustin Pop
                                 errors.ECODE_INVAL)
315 0d0e9090 René Nussbaumer
316 4082e6f9 Iustin Pop
    if (spec['hvparams'] and
317 4082e6f9 Iustin Pop
        not isinstance(spec['hvparams'], dict)):
318 debac808 Iustin Pop
      raise errors.OpPrereqError('Hypervisor parameters must be a dict.',
319 debac808 Iustin Pop
                                 errors.ECODE_INVAL)
320 0d0e9090 René Nussbaumer
321 0d0e9090 René Nussbaumer
  json_filename = args[0]
322 0d0e9090 René Nussbaumer
  try:
323 13998ef2 Michael Hanselmann
    instance_data = simplejson.loads(utils.ReadFile(json_filename))
324 7260cfbe Iustin Pop
  except Exception, err: # pylint: disable-msg=W0703
325 4082e6f9 Iustin Pop
    ToStderr("Can't parse the instance definition file: %s" % str(err))
326 4082e6f9 Iustin Pop
    return 1
327 0d0e9090 René Nussbaumer
328 fe7c59d5 Guido Trotter
  if not isinstance(instance_data, dict):
329 fe7c59d5 Guido Trotter
    ToStderr("The instance definition file is not in dict format.")
330 fe7c59d5 Guido Trotter
    return 1
331 fe7c59d5 Guido Trotter
332 cb573a31 Iustin Pop
  jex = JobExecutor(opts=opts)
333 d4dd4b74 Iustin Pop
334 0d0e9090 René Nussbaumer
  # Iterate over the instances and do:
335 0d0e9090 René Nussbaumer
  #  * Populate the specs with default value
336 0d0e9090 René Nussbaumer
  #  * Validate the instance specs
337 fe7c59d5 Guido Trotter
  i_names = utils.NiceSort(instance_data.keys()) # pylint: disable-msg=E1103
338 7312b33d Iustin Pop
  for name in i_names:
339 7312b33d Iustin Pop
    specs = instance_data[name]
340 0d0e9090 René Nussbaumer
    specs = _PopulateWithDefaults(specs)
341 0d0e9090 René Nussbaumer
    _Validate(specs)
342 0d0e9090 René Nussbaumer
343 4082e6f9 Iustin Pop
    hypervisor = specs['hypervisor']
344 4082e6f9 Iustin Pop
    hvparams = specs['hvparams']
345 0d0e9090 René Nussbaumer
346 9939547b Iustin Pop
    disks = []
347 9939547b Iustin Pop
    for elem in specs['disk_size']:
348 9939547b Iustin Pop
      try:
349 9939547b Iustin Pop
        size = utils.ParseUnit(elem)
350 691744c4 Iustin Pop
      except (TypeError, ValueError), err:
351 9939547b Iustin Pop
        raise errors.OpPrereqError("Invalid disk size '%s' for"
352 9939547b Iustin Pop
                                   " instance %s: %s" %
353 debac808 Iustin Pop
                                   (elem, name, err), errors.ECODE_INVAL)
354 9939547b Iustin Pop
      disks.append({"size": size})
355 9939547b Iustin Pop
356 a5728081 Guido Trotter
    utils.ForceDictType(specs['backend'], constants.BES_PARAMETER_TYPES)
357 a5728081 Guido Trotter
    utils.ForceDictType(hvparams, constants.HVS_PARAMETER_TYPES)
358 a5728081 Guido Trotter
359 a379d9bd Guido Trotter
    tmp_nics = []
360 a379d9bd Guido Trotter
    for field in ('ip', 'mac', 'mode', 'link', 'bridge'):
361 a379d9bd Guido Trotter
      if field in specs:
362 a379d9bd Guido Trotter
        if not tmp_nics:
363 a379d9bd Guido Trotter
          tmp_nics.append({})
364 a379d9bd Guido Trotter
        tmp_nics[0][field] = specs[field]
365 a379d9bd Guido Trotter
366 a379d9bd Guido Trotter
    if specs['nics'] is not None and tmp_nics:
367 a379d9bd Guido Trotter
      raise errors.OpPrereqError("'nics' list incompatible with using"
368 debac808 Iustin Pop
                                 " individual nic fields as well",
369 debac808 Iustin Pop
                                 errors.ECODE_INVAL)
370 a379d9bd Guido Trotter
    elif specs['nics'] is not None:
371 a379d9bd Guido Trotter
      tmp_nics = specs['nics']
372 a379d9bd Guido Trotter
    elif not tmp_nics:
373 a379d9bd Guido Trotter
      tmp_nics = [{}]
374 a379d9bd Guido Trotter
375 e1530b10 Iustin Pop
    op = opcodes.OpInstanceCreate(instance_name=name,
376 9939547b Iustin Pop
                                  disks=disks,
377 0d0e9090 René Nussbaumer
                                  disk_template=specs['template'],
378 0d0e9090 René Nussbaumer
                                  mode=constants.INSTANCE_CREATE,
379 0d0e9090 René Nussbaumer
                                  os_type=specs['os'],
380 de372295 Guido Trotter
                                  force_variant=specs["force_variant"],
381 0d0e9090 René Nussbaumer
                                  pnode=specs['primary_node'],
382 0d0e9090 René Nussbaumer
                                  snode=specs['secondary_node'],
383 a379d9bd Guido Trotter
                                  nics=tmp_nics,
384 0d0e9090 René Nussbaumer
                                  start=specs['start'],
385 0d0e9090 René Nussbaumer
                                  ip_check=specs['ip_check'],
386 460d22be Iustin Pop
                                  name_check=specs['name_check'],
387 0d0e9090 René Nussbaumer
                                  wait_for_sync=True,
388 0d0e9090 René Nussbaumer
                                  iallocator=specs['iallocator'],
389 0d0e9090 René Nussbaumer
                                  hypervisor=hypervisor,
390 0d0e9090 René Nussbaumer
                                  hvparams=hvparams,
391 0d0e9090 René Nussbaumer
                                  beparams=specs['backend'],
392 0d0e9090 René Nussbaumer
                                  file_storage_dir=specs['file_storage_dir'],
393 0d0e9090 René Nussbaumer
                                  file_driver=specs['file_driver'])
394 0d0e9090 René Nussbaumer
395 d4dd4b74 Iustin Pop
    jex.QueueJob(name, op)
396 d4dd4b74 Iustin Pop
  # we never want to wait, just show the submitted job IDs
397 d4dd4b74 Iustin Pop
  jex.WaitOrShow(False)
398 0d0e9090 René Nussbaumer
399 0d0e9090 René Nussbaumer
  return 0
400 0d0e9090 René Nussbaumer
401 0d0e9090 René Nussbaumer
402 fe7b0351 Michael Hanselmann
def ReinstallInstance(opts, args):
403 fe7b0351 Michael Hanselmann
  """Reinstall an instance.
404 fe7b0351 Michael Hanselmann

405 7232c04c Iustin Pop
  @param opts: the command line options selected by the user
406 7232c04c Iustin Pop
  @type args: list
407 7232c04c Iustin Pop
  @param args: should contain only one element, the name of the
408 7232c04c Iustin Pop
      instance to be reinstalled
409 7232c04c Iustin Pop
  @rtype: int
410 7232c04c Iustin Pop
  @return: the desired exit code
411 fe7b0351 Michael Hanselmann

412 fe7b0351 Michael Hanselmann
  """
413 55efe6da Iustin Pop
  # first, compute the desired name list
414 55efe6da Iustin Pop
  if opts.multi_mode is None:
415 55efe6da Iustin Pop
    opts.multi_mode = _SHUTDOWN_INSTANCES
416 55efe6da Iustin Pop
417 55efe6da Iustin Pop
  inames = _ExpandMultiNames(opts.multi_mode, args)
418 55efe6da Iustin Pop
  if not inames:
419 debac808 Iustin Pop
    raise errors.OpPrereqError("Selection filter does not match any instances",
420 debac808 Iustin Pop
                               errors.ECODE_INVAL)
421 fe7b0351 Michael Hanselmann
422 55efe6da Iustin Pop
  # second, if requested, ask for an OS
423 20e23543 Alexander Schreiber
  if opts.select_os is True:
424 da2d02e7 Iustin Pop
    op = opcodes.OpOsDiagnose(output_fields=["name", "variants"], names=[])
425 400ca2f7 Iustin Pop
    result = SubmitOpCode(op, opts=opts)
426 20e23543 Alexander Schreiber
427 20e23543 Alexander Schreiber
    if not result:
428 3a24c527 Iustin Pop
      ToStdout("Can't get the OS list")
429 20e23543 Alexander Schreiber
      return 1
430 20e23543 Alexander Schreiber
431 3a24c527 Iustin Pop
    ToStdout("Available OS templates:")
432 20e23543 Alexander Schreiber
    number = 0
433 20e23543 Alexander Schreiber
    choices = []
434 d22dfef7 Iustin Pop
    for (name, variants) in result:
435 d22dfef7 Iustin Pop
      for entry in CalculateOSNames(name, variants):
436 d22dfef7 Iustin Pop
        ToStdout("%3s: %s", number, entry)
437 d22dfef7 Iustin Pop
        choices.append(("%s" % number, entry, entry))
438 d22dfef7 Iustin Pop
        number += 1
439 20e23543 Alexander Schreiber
440 20e23543 Alexander Schreiber
    choices.append(('x', 'exit', 'Exit gnt-instance reinstall'))
441 949bdabe Iustin Pop
    selected = AskUser("Enter OS template number (or x to abort):",
442 20e23543 Alexander Schreiber
                       choices)
443 20e23543 Alexander Schreiber
444 20e23543 Alexander Schreiber
    if selected == 'exit':
445 55efe6da Iustin Pop
      ToStderr("User aborted reinstall, exiting")
446 20e23543 Alexander Schreiber
      return 1
447 20e23543 Alexander Schreiber
448 2f79bd34 Iustin Pop
    os_name = selected
449 f86426f5 Iustin Pop
    os_msg = "change the OS to '%s'" % selected
450 20e23543 Alexander Schreiber
  else:
451 2f79bd34 Iustin Pop
    os_name = opts.os
452 f86426f5 Iustin Pop
    if opts.os is not None:
453 f86426f5 Iustin Pop
      os_msg = "change the OS to '%s'" % os_name
454 f86426f5 Iustin Pop
    else:
455 f86426f5 Iustin Pop
      os_msg = "keep the same OS"
456 20e23543 Alexander Schreiber
457 297ddce9 Iustin Pop
  # third, get confirmation: multi-reinstall requires --force-multi,
458 297ddce9 Iustin Pop
  # single-reinstall either --force or --force-multi (--force-multi is
459 297ddce9 Iustin Pop
  # a stronger --force)
460 55efe6da Iustin Pop
  multi_on = opts.multi_mode != _SHUTDOWN_INSTANCES or len(inames) > 1
461 55efe6da Iustin Pop
  if multi_on:
462 f86426f5 Iustin Pop
    warn_msg = ("Note: this will remove *all* data for the"
463 f86426f5 Iustin Pop
                " below instances! It will %s.\n" % os_msg)
464 297ddce9 Iustin Pop
    if not (opts.force_multi or
465 25bd815c René Nussbaumer
            ConfirmOperation(inames, "instances", "reinstall", extra=warn_msg)):
466 fe7b0351 Michael Hanselmann
      return 1
467 55efe6da Iustin Pop
  else:
468 297ddce9 Iustin Pop
    if not (opts.force or opts.force_multi):
469 f86426f5 Iustin Pop
      usertext = ("This will reinstall the instance '%s' (and %s) which"
470 f86426f5 Iustin Pop
                  " removes all data. Continue?") % (inames[0], os_msg)
471 55efe6da Iustin Pop
      if not AskUser(usertext):
472 55efe6da Iustin Pop
        return 1
473 55efe6da Iustin Pop
474 cb573a31 Iustin Pop
  jex = JobExecutor(verbose=multi_on, opts=opts)
475 55efe6da Iustin Pop
  for instance_name in inames:
476 5073fd8f Iustin Pop
    op = opcodes.OpInstanceReinstall(instance_name=instance_name,
477 06073e85 Guido Trotter
                                     os_type=os_name,
478 8d8c4eff Michael Hanselmann
                                     force_variant=opts.force_variant,
479 8d8c4eff Michael Hanselmann
                                     osparams=opts.osparams)
480 55efe6da Iustin Pop
    jex.QueueJob(instance_name, op)
481 fe7b0351 Michael Hanselmann
482 55efe6da Iustin Pop
  jex.WaitOrShow(not opts.submit_only)
483 fe7b0351 Michael Hanselmann
  return 0
484 fe7b0351 Michael Hanselmann
485 fe7b0351 Michael Hanselmann
486 a8083063 Iustin Pop
def RemoveInstance(opts, args):
487 a8083063 Iustin Pop
  """Remove an instance.
488 a8083063 Iustin Pop

489 7232c04c Iustin Pop
  @param opts: the command line options selected by the user
490 7232c04c Iustin Pop
  @type args: list
491 7232c04c Iustin Pop
  @param args: should contain only one element, the name of
492 7232c04c Iustin Pop
      the instance to be removed
493 7232c04c Iustin Pop
  @rtype: int
494 7232c04c Iustin Pop
  @return: the desired exit code
495 a8083063 Iustin Pop

496 a8083063 Iustin Pop
  """
497 a8083063 Iustin Pop
  instance_name = args[0]
498 a8083063 Iustin Pop
  force = opts.force
499 a76f0c4a Iustin Pop
  cl = GetClient()
500 a8083063 Iustin Pop
501 a8083063 Iustin Pop
  if not force:
502 a76f0c4a Iustin Pop
    _EnsureInstancesExist(cl, [instance_name])
503 a76f0c4a Iustin Pop
504 a8083063 Iustin Pop
    usertext = ("This will remove the volumes of the instance %s"
505 a8083063 Iustin Pop
                " (including mirrors), thus removing all the data"
506 a8083063 Iustin Pop
                " of the instance. Continue?") % instance_name
507 47988778 Iustin Pop
    if not AskUser(usertext):
508 a8083063 Iustin Pop
      return 1
509 a8083063 Iustin Pop
510 3cd2d4b1 Iustin Pop
  op = opcodes.OpInstanceRemove(instance_name=instance_name,
511 17c3f802 Guido Trotter
                                ignore_failures=opts.ignore_failures,
512 4d98c565 Guido Trotter
                                shutdown_timeout=opts.shutdown_timeout)
513 a76f0c4a Iustin Pop
  SubmitOrSend(op, opts, cl=cl)
514 a8083063 Iustin Pop
  return 0
515 a8083063 Iustin Pop
516 a8083063 Iustin Pop
517 decd5f45 Iustin Pop
def RenameInstance(opts, args):
518 4ab0b9e3 Guido Trotter
  """Rename an instance.
519 decd5f45 Iustin Pop

520 7232c04c Iustin Pop
  @param opts: the command line options selected by the user
521 7232c04c Iustin Pop
  @type args: list
522 7232c04c Iustin Pop
  @param args: should contain two elements, the old and the
523 7232c04c Iustin Pop
      new instance names
524 7232c04c Iustin Pop
  @rtype: int
525 7232c04c Iustin Pop
  @return: the desired exit code
526 decd5f45 Iustin Pop

527 decd5f45 Iustin Pop
  """
528 90ed09b0 René Nussbaumer
  if not opts.name_check:
529 1b6dddc8 René Nussbaumer
    if not AskUser("As you disabled the check of the DNS entry, please verify"
530 1b6dddc8 René Nussbaumer
                   " that '%s' is a FQDN. Continue?" % args[1]):
531 1b6dddc8 René Nussbaumer
      return 1
532 1b6dddc8 René Nussbaumer
533 5659e2e2 Iustin Pop
  op = opcodes.OpInstanceRename(instance_name=args[0],
534 decd5f45 Iustin Pop
                                new_name=args[1],
535 3fe11ba3 Manuel Franceschini
                                ip_check=opts.ip_check,
536 3fe11ba3 Manuel Franceschini
                                name_check=opts.name_check)
537 6a016df9 Michael Hanselmann
  result = SubmitOrSend(op, opts)
538 6a016df9 Michael Hanselmann
539 48418fea Iustin Pop
  if result:
540 48418fea Iustin Pop
    ToStdout("Instance '%s' renamed to '%s'", args[0], result)
541 6a016df9 Michael Hanselmann
542 decd5f45 Iustin Pop
  return 0
543 decd5f45 Iustin Pop
544 decd5f45 Iustin Pop
545 a8083063 Iustin Pop
def ActivateDisks(opts, args):
546 a8083063 Iustin Pop
  """Activate an instance's disks.
547 a8083063 Iustin Pop

548 a8083063 Iustin Pop
  This serves two purposes:
549 7232c04c Iustin Pop
    - it allows (as long as the instance is not running)
550 7232c04c Iustin Pop
      mounting the disks and modifying them from the node
551 a8083063 Iustin Pop
    - it repairs inactive secondary drbds
552 a8083063 Iustin Pop

553 7232c04c Iustin Pop
  @param opts: the command line options selected by the user
554 7232c04c Iustin Pop
  @type args: list
555 7232c04c Iustin Pop
  @param args: should contain only one element, the instance name
556 7232c04c Iustin Pop
  @rtype: int
557 7232c04c Iustin Pop
  @return: the desired exit code
558 7232c04c Iustin Pop

559 a8083063 Iustin Pop
  """
560 a8083063 Iustin Pop
  instance_name = args[0]
561 83f5d475 Iustin Pop
  op = opcodes.OpInstanceActivateDisks(instance_name=instance_name,
562 b4ec07f8 Iustin Pop
                                       ignore_size=opts.ignore_size)
563 6340bb0a Iustin Pop
  disks_info = SubmitOrSend(op, opts)
564 a8083063 Iustin Pop
  for host, iname, nname in disks_info:
565 3a24c527 Iustin Pop
    ToStdout("%s:%s:%s", host, iname, nname)
566 a8083063 Iustin Pop
  return 0
567 a8083063 Iustin Pop
568 a8083063 Iustin Pop
569 a8083063 Iustin Pop
def DeactivateDisks(opts, args):
570 bd315bfa Iustin Pop
  """Deactivate an instance's disks.
571 a8083063 Iustin Pop

572 a8083063 Iustin Pop
  This function takes the instance name, looks for its primary node
573 a8083063 Iustin Pop
  and the tries to shutdown its block devices on that node.
574 a8083063 Iustin Pop

575 7232c04c Iustin Pop
  @param opts: the command line options selected by the user
576 7232c04c Iustin Pop
  @type args: list
577 7232c04c Iustin Pop
  @param args: should contain only one element, the instance name
578 7232c04c Iustin Pop
  @rtype: int
579 7232c04c Iustin Pop
  @return: the desired exit code
580 7232c04c Iustin Pop

581 a8083063 Iustin Pop
  """
582 a8083063 Iustin Pop
  instance_name = args[0]
583 c9c41373 Iustin Pop
  op = opcodes.OpInstanceDeactivateDisks(instance_name=instance_name,
584 c9c41373 Iustin Pop
                                         force=opts.force)
585 6340bb0a Iustin Pop
  SubmitOrSend(op, opts)
586 a8083063 Iustin Pop
  return 0
587 a8083063 Iustin Pop
588 a8083063 Iustin Pop
589 bd315bfa Iustin Pop
def RecreateDisks(opts, args):
590 bd315bfa Iustin Pop
  """Recreate an instance's disks.
591 bd315bfa Iustin Pop

592 bd315bfa Iustin Pop
  @param opts: the command line options selected by the user
593 bd315bfa Iustin Pop
  @type args: list
594 bd315bfa Iustin Pop
  @param args: should contain only one element, the instance name
595 bd315bfa Iustin Pop
  @rtype: int
596 bd315bfa Iustin Pop
  @return: the desired exit code
597 bd315bfa Iustin Pop

598 bd315bfa Iustin Pop
  """
599 bd315bfa Iustin Pop
  instance_name = args[0]
600 bd315bfa Iustin Pop
  if opts.disks:
601 bd315bfa Iustin Pop
    try:
602 bd315bfa Iustin Pop
      opts.disks = [int(v) for v in opts.disks.split(",")]
603 bd315bfa Iustin Pop
    except (ValueError, TypeError), err:
604 bd315bfa Iustin Pop
      ToStderr("Invalid disks value: %s" % str(err))
605 bd315bfa Iustin Pop
      return 1
606 bd315bfa Iustin Pop
  else:
607 bd315bfa Iustin Pop
    opts.disks = []
608 bd315bfa Iustin Pop
609 6b273e78 Iustin Pop
  op = opcodes.OpInstanceRecreateDisks(instance_name=instance_name,
610 bd315bfa Iustin Pop
                                       disks=opts.disks)
611 bd315bfa Iustin Pop
  SubmitOrSend(op, opts)
612 bd315bfa Iustin Pop
  return 0
613 bd315bfa Iustin Pop
614 bd315bfa Iustin Pop
615 c6e911bc Iustin Pop
def GrowDisk(opts, args):
616 7232c04c Iustin Pop
  """Grow an instance's disks.
617 c6e911bc Iustin Pop

618 7232c04c Iustin Pop
  @param opts: the command line options selected by the user
619 7232c04c Iustin Pop
  @type args: list
620 7232c04c Iustin Pop
  @param args: should contain two elements, the instance name
621 7232c04c Iustin Pop
      whose disks we grow and the disk name, e.g. I{sda}
622 7232c04c Iustin Pop
  @rtype: int
623 7232c04c Iustin Pop
  @return: the desired exit code
624 c6e911bc Iustin Pop

625 c6e911bc Iustin Pop
  """
626 c6e911bc Iustin Pop
  instance = args[0]
627 c6e911bc Iustin Pop
  disk = args[1]
628 ad24e046 Iustin Pop
  try:
629 ad24e046 Iustin Pop
    disk = int(disk)
630 691744c4 Iustin Pop
  except (TypeError, ValueError), err:
631 debac808 Iustin Pop
    raise errors.OpPrereqError("Invalid disk index: %s" % str(err),
632 debac808 Iustin Pop
                               errors.ECODE_INVAL)
633 c6e911bc Iustin Pop
  amount = utils.ParseUnit(args[2])
634 60472d29 Iustin Pop
  op = opcodes.OpInstanceGrowDisk(instance_name=instance,
635 60472d29 Iustin Pop
                                  disk=disk, amount=amount,
636 60472d29 Iustin Pop
                                  wait_for_sync=opts.wait_for_sync)
637 6340bb0a Iustin Pop
  SubmitOrSend(op, opts)
638 c6e911bc Iustin Pop
  return 0
639 c6e911bc Iustin Pop
640 c6e911bc Iustin Pop
641 1c5945b6 Iustin Pop
def _StartupInstance(name, opts):
642 7232c04c Iustin Pop
  """Startup instances.
643 a8083063 Iustin Pop

644 1c5945b6 Iustin Pop
  This returns the opcode to start an instance, and its decorator will
645 1c5945b6 Iustin Pop
  wrap this into a loop starting all desired instances.
646 7232c04c Iustin Pop

647 1c5945b6 Iustin Pop
  @param name: the name of the instance to act on
648 7232c04c Iustin Pop
  @param opts: the command line options selected by the user
649 1c5945b6 Iustin Pop
  @return: the opcode needed for the operation
650 a8083063 Iustin Pop

651 a8083063 Iustin Pop
  """
652 c873d91c Iustin Pop
  op = opcodes.OpInstanceStartup(instance_name=name,
653 b44bd844 Michael Hanselmann
                                 force=opts.force,
654 b44bd844 Michael Hanselmann
                                 ignore_offline_nodes=opts.ignore_offline)
655 1c5945b6 Iustin Pop
  # do not add these parameters to the opcode unless they're defined
656 1c5945b6 Iustin Pop
  if opts.hvparams:
657 1c5945b6 Iustin Pop
    op.hvparams = opts.hvparams
658 1c5945b6 Iustin Pop
  if opts.beparams:
659 1c5945b6 Iustin Pop
    op.beparams = opts.beparams
660 1c5945b6 Iustin Pop
  return op
661 a8083063 Iustin Pop
662 7c0d6283 Michael Hanselmann
663 1c5945b6 Iustin Pop
def _RebootInstance(name, opts):
664 7232c04c Iustin Pop
  """Reboot instance(s).
665 7232c04c Iustin Pop

666 1c5945b6 Iustin Pop
  This returns the opcode to reboot an instance, and its decorator
667 1c5945b6 Iustin Pop
  will wrap this into a loop rebooting all desired instances.
668 579d4337 Alexander Schreiber

669 1c5945b6 Iustin Pop
  @param name: the name of the instance to act on
670 7232c04c Iustin Pop
  @param opts: the command line options selected by the user
671 1c5945b6 Iustin Pop
  @return: the opcode needed for the operation
672 579d4337 Alexander Schreiber

673 579d4337 Alexander Schreiber
  """
674 90ab1a95 Iustin Pop
  return opcodes.OpInstanceReboot(instance_name=name,
675 579d4337 Alexander Schreiber
                                  reboot_type=opts.reboot_type,
676 17c3f802 Guido Trotter
                                  ignore_secondaries=opts.ignore_secondaries,
677 4d98c565 Guido Trotter
                                  shutdown_timeout=opts.shutdown_timeout)
678 a8083063 Iustin Pop
679 7c0d6283 Michael Hanselmann
680 1c5945b6 Iustin Pop
def _ShutdownInstance(name, opts):
681 a8083063 Iustin Pop
  """Shutdown an instance.
682 a8083063 Iustin Pop

683 1c5945b6 Iustin Pop
  This returns the opcode to shutdown an instance, and its decorator
684 1c5945b6 Iustin Pop
  will wrap this into a loop shutting down all desired instances.
685 1c5945b6 Iustin Pop

686 1c5945b6 Iustin Pop
  @param name: the name of the instance to act on
687 7232c04c Iustin Pop
  @param opts: the command line options selected by the user
688 1c5945b6 Iustin Pop
  @return: the opcode needed for the operation
689 a8083063 Iustin Pop

690 a8083063 Iustin Pop
  """
691 ee3e37a7 Iustin Pop
  return opcodes.OpInstanceShutdown(instance_name=name,
692 b44bd844 Michael Hanselmann
                                    timeout=opts.timeout,
693 b44bd844 Michael Hanselmann
                                    ignore_offline_nodes=opts.ignore_offline)
694 a8083063 Iustin Pop
695 a8083063 Iustin Pop
696 a8083063 Iustin Pop
def ReplaceDisks(opts, args):
697 a8083063 Iustin Pop
  """Replace the disks of an instance
698 a8083063 Iustin Pop

699 7232c04c Iustin Pop
  @param opts: the command line options selected by the user
700 7232c04c Iustin Pop
  @type args: list
701 7232c04c Iustin Pop
  @param args: should contain only one element, the instance name
702 7232c04c Iustin Pop
  @rtype: int
703 7232c04c Iustin Pop
  @return: the desired exit code
704 a8083063 Iustin Pop

705 a8083063 Iustin Pop
  """
706 a14db5ff Iustin Pop
  new_2ndary = opts.dst_node
707 b6e82a65 Iustin Pop
  iallocator = opts.iallocator
708 a9e0c397 Iustin Pop
  if opts.disks is None:
709 54155f52 Iustin Pop
    disks = []
710 a9e0c397 Iustin Pop
  else:
711 54155f52 Iustin Pop
    try:
712 54155f52 Iustin Pop
      disks = [int(i) for i in opts.disks.split(",")]
713 691744c4 Iustin Pop
    except (TypeError, ValueError), err:
714 debac808 Iustin Pop
      raise errors.OpPrereqError("Invalid disk index passed: %s" % str(err),
715 debac808 Iustin Pop
                                 errors.ECODE_INVAL)
716 05d47e33 Michael Hanselmann
  cnt = [opts.on_primary, opts.on_secondary, opts.auto,
717 7e9366f7 Iustin Pop
         new_2ndary is not None, iallocator is not None].count(True)
718 7e9366f7 Iustin Pop
  if cnt != 1:
719 05d47e33 Michael Hanselmann
    raise errors.OpPrereqError("One and only one of the -p, -s, -a, -n and -i"
720 debac808 Iustin Pop
                               " options must be passed", errors.ECODE_INVAL)
721 7e9366f7 Iustin Pop
  elif opts.on_primary:
722 a9e0c397 Iustin Pop
    mode = constants.REPLACE_DISK_PRI
723 7e9366f7 Iustin Pop
  elif opts.on_secondary:
724 a9e0c397 Iustin Pop
    mode = constants.REPLACE_DISK_SEC
725 05d47e33 Michael Hanselmann
  elif opts.auto:
726 05d47e33 Michael Hanselmann
    mode = constants.REPLACE_DISK_AUTO
727 05d47e33 Michael Hanselmann
    if disks:
728 05d47e33 Michael Hanselmann
      raise errors.OpPrereqError("Cannot specify disks when using automatic"
729 debac808 Iustin Pop
                                 " mode", errors.ECODE_INVAL)
730 7e9366f7 Iustin Pop
  elif new_2ndary is not None or iallocator is not None:
731 7e9366f7 Iustin Pop
    # replace secondary
732 7e9366f7 Iustin Pop
    mode = constants.REPLACE_DISK_CHG
733 a9e0c397 Iustin Pop
734 668f755d Iustin Pop
  op = opcodes.OpInstanceReplaceDisks(instance_name=args[0], disks=disks,
735 668f755d Iustin Pop
                                      remote_node=new_2ndary, mode=mode,
736 668f755d Iustin Pop
                                      iallocator=iallocator,
737 668f755d Iustin Pop
                                      early_release=opts.early_release)
738 6340bb0a Iustin Pop
  SubmitOrSend(op, opts)
739 a8083063 Iustin Pop
  return 0
740 a8083063 Iustin Pop
741 a8083063 Iustin Pop
742 a8083063 Iustin Pop
def FailoverInstance(opts, args):
743 a8083063 Iustin Pop
  """Failover an instance.
744 a8083063 Iustin Pop

745 a8083063 Iustin Pop
  The failover is done by shutting it down on its present node and
746 a8083063 Iustin Pop
  starting it on the secondary.
747 a8083063 Iustin Pop

748 7232c04c Iustin Pop
  @param opts: the command line options selected by the user
749 7232c04c Iustin Pop
  @type args: list
750 7232c04c Iustin Pop
  @param args: should contain only one element, the instance name
751 7232c04c Iustin Pop
  @rtype: int
752 7232c04c Iustin Pop
  @return: the desired exit code
753 a8083063 Iustin Pop

754 a8083063 Iustin Pop
  """
755 a76f0c4a Iustin Pop
  cl = GetClient()
756 80de0e3f Iustin Pop
  instance_name = args[0]
757 80de0e3f Iustin Pop
  force = opts.force
758 a8083063 Iustin Pop
759 80de0e3f Iustin Pop
  if not force:
760 a76f0c4a Iustin Pop
    _EnsureInstancesExist(cl, [instance_name])
761 a76f0c4a Iustin Pop
762 80de0e3f Iustin Pop
    usertext = ("Failover will happen to image %s."
763 80de0e3f Iustin Pop
                " This requires a shutdown of the instance. Continue?" %
764 80de0e3f Iustin Pop
                (instance_name,))
765 80de0e3f Iustin Pop
    if not AskUser(usertext):
766 80de0e3f Iustin Pop
      return 1
767 a8083063 Iustin Pop
768 019dbee1 Iustin Pop
  op = opcodes.OpInstanceFailover(instance_name=instance_name,
769 17c3f802 Guido Trotter
                                  ignore_consistency=opts.ignore_consistency,
770 4d98c565 Guido Trotter
                                  shutdown_timeout=opts.shutdown_timeout)
771 a76f0c4a Iustin Pop
  SubmitOrSend(op, opts, cl=cl)
772 80de0e3f Iustin Pop
  return 0
773 a8083063 Iustin Pop
774 a8083063 Iustin Pop
775 53c776b5 Iustin Pop
def MigrateInstance(opts, args):
776 53c776b5 Iustin Pop
  """Migrate an instance.
777 53c776b5 Iustin Pop

778 53c776b5 Iustin Pop
  The migrate is done without shutdown.
779 53c776b5 Iustin Pop

780 2f907a8c Iustin Pop
  @param opts: the command line options selected by the user
781 2f907a8c Iustin Pop
  @type args: list
782 2f907a8c Iustin Pop
  @param args: should contain only one element, the instance name
783 2f907a8c Iustin Pop
  @rtype: int
784 2f907a8c Iustin Pop
  @return: the desired exit code
785 53c776b5 Iustin Pop

786 53c776b5 Iustin Pop
  """
787 a76f0c4a Iustin Pop
  cl = GetClient()
788 53c776b5 Iustin Pop
  instance_name = args[0]
789 53c776b5 Iustin Pop
  force = opts.force
790 53c776b5 Iustin Pop
791 53c776b5 Iustin Pop
  if not force:
792 a76f0c4a Iustin Pop
    _EnsureInstancesExist(cl, [instance_name])
793 a76f0c4a Iustin Pop
794 53c776b5 Iustin Pop
    if opts.cleanup:
795 53c776b5 Iustin Pop
      usertext = ("Instance %s will be recovered from a failed migration."
796 53c776b5 Iustin Pop
                  " Note that the migration procedure (including cleanup)" %
797 53c776b5 Iustin Pop
                  (instance_name,))
798 53c776b5 Iustin Pop
    else:
799 53c776b5 Iustin Pop
      usertext = ("Instance %s will be migrated. Note that migration" %
800 53c776b5 Iustin Pop
                  (instance_name,))
801 cf29cfb6 Iustin Pop
    usertext += (" might impact the instance if anything goes wrong"
802 cf29cfb6 Iustin Pop
                 " (e.g. due to bugs in the hypervisor). Continue?")
803 53c776b5 Iustin Pop
    if not AskUser(usertext):
804 53c776b5 Iustin Pop
      return 1
805 53c776b5 Iustin Pop
806 e71b9ef4 Iustin Pop
  # this should be removed once --non-live is deprecated
807 783a6c0b Iustin Pop
  if not opts.live and opts.migration_mode is not None:
808 e71b9ef4 Iustin Pop
    raise errors.OpPrereqError("Only one of the --non-live and "
809 783a6c0b Iustin Pop
                               "--migration-mode options can be passed",
810 e71b9ef4 Iustin Pop
                               errors.ECODE_INVAL)
811 e71b9ef4 Iustin Pop
  if not opts.live: # --non-live passed
812 8c35561f Iustin Pop
    mode = constants.HT_MIGRATION_NONLIVE
813 e71b9ef4 Iustin Pop
  else:
814 8c35561f Iustin Pop
    mode = opts.migration_mode
815 e71b9ef4 Iustin Pop
816 75c866c2 Iustin Pop
  op = opcodes.OpInstanceMigrate(instance_name=instance_name, mode=mode,
817 53c776b5 Iustin Pop
                                 cleanup=opts.cleanup)
818 400ca2f7 Iustin Pop
  SubmitOpCode(op, cl=cl, opts=opts)
819 53c776b5 Iustin Pop
  return 0
820 53c776b5 Iustin Pop
821 53c776b5 Iustin Pop
822 fbf5a861 Iustin Pop
def MoveInstance(opts, args):
823 fbf5a861 Iustin Pop
  """Move an instance.
824 fbf5a861 Iustin Pop

825 fbf5a861 Iustin Pop
  @param opts: the command line options selected by the user
826 fbf5a861 Iustin Pop
  @type args: list
827 fbf5a861 Iustin Pop
  @param args: should contain only one element, the instance name
828 fbf5a861 Iustin Pop
  @rtype: int
829 fbf5a861 Iustin Pop
  @return: the desired exit code
830 fbf5a861 Iustin Pop

831 fbf5a861 Iustin Pop
  """
832 fbf5a861 Iustin Pop
  cl = GetClient()
833 fbf5a861 Iustin Pop
  instance_name = args[0]
834 fbf5a861 Iustin Pop
  force = opts.force
835 fbf5a861 Iustin Pop
836 fbf5a861 Iustin Pop
  if not force:
837 fbf5a861 Iustin Pop
    usertext = ("Instance %s will be moved."
838 fbf5a861 Iustin Pop
                " This requires a shutdown of the instance. Continue?" %
839 fbf5a861 Iustin Pop
                (instance_name,))
840 fbf5a861 Iustin Pop
    if not AskUser(usertext):
841 fbf5a861 Iustin Pop
      return 1
842 fbf5a861 Iustin Pop
843 0091b480 Iustin Pop
  op = opcodes.OpInstanceMove(instance_name=instance_name,
844 17c3f802 Guido Trotter
                              target_node=opts.node,
845 4d98c565 Guido Trotter
                              shutdown_timeout=opts.shutdown_timeout)
846 fbf5a861 Iustin Pop
  SubmitOrSend(op, opts, cl=cl)
847 fbf5a861 Iustin Pop
  return 0
848 fbf5a861 Iustin Pop
849 fbf5a861 Iustin Pop
850 a8083063 Iustin Pop
def ConnectToInstanceConsole(opts, args):
851 a8083063 Iustin Pop
  """Connect to the console of an instance.
852 a8083063 Iustin Pop

853 7232c04c Iustin Pop
  @param opts: the command line options selected by the user
854 7232c04c Iustin Pop
  @type args: list
855 7232c04c Iustin Pop
  @param args: should contain only one element, the instance name
856 7232c04c Iustin Pop
  @rtype: int
857 7232c04c Iustin Pop
  @return: the desired exit code
858 a8083063 Iustin Pop

859 a8083063 Iustin Pop
  """
860 a8083063 Iustin Pop
  instance_name = args[0]
861 a8083063 Iustin Pop
862 cc0dec7b Iustin Pop
  op = opcodes.OpInstanceConsole(instance_name=instance_name)
863 51c6e7b5 Michael Hanselmann
864 25ce3ec4 Michael Hanselmann
  cl = GetClient()
865 25ce3ec4 Michael Hanselmann
  try:
866 25ce3ec4 Michael Hanselmann
    cluster_name = cl.QueryConfigValues(["cluster_name"])[0]
867 25ce3ec4 Michael Hanselmann
    console_data = SubmitOpCode(op, opts=opts, cl=cl)
868 25ce3ec4 Michael Hanselmann
  finally:
869 25ce3ec4 Michael Hanselmann
    # Ensure client connection is closed while external commands are run
870 25ce3ec4 Michael Hanselmann
    cl.Close()
871 25ce3ec4 Michael Hanselmann
872 25ce3ec4 Michael Hanselmann
  del cl
873 25ce3ec4 Michael Hanselmann
874 25ce3ec4 Michael Hanselmann
  return _DoConsole(objects.InstanceConsole.FromDict(console_data),
875 25ce3ec4 Michael Hanselmann
                    opts.show_command, cluster_name)
876 25ce3ec4 Michael Hanselmann
877 25ce3ec4 Michael Hanselmann
878 25ce3ec4 Michael Hanselmann
def _DoConsole(console, show_command, cluster_name, feedback_fn=ToStdout,
879 25ce3ec4 Michael Hanselmann
               _runcmd_fn=utils.RunCmd):
880 cc0dec7b Iustin Pop
  """Acts based on the result of L{opcodes.OpInstanceConsole}.
881 25ce3ec4 Michael Hanselmann

882 25ce3ec4 Michael Hanselmann
  @type console: L{objects.InstanceConsole}
883 25ce3ec4 Michael Hanselmann
  @param console: Console object
884 25ce3ec4 Michael Hanselmann
  @type show_command: bool
885 25ce3ec4 Michael Hanselmann
  @param show_command: Whether to just display commands
886 25ce3ec4 Michael Hanselmann
  @type cluster_name: string
887 25ce3ec4 Michael Hanselmann
  @param cluster_name: Cluster name as retrieved from master daemon
888 25ce3ec4 Michael Hanselmann

889 25ce3ec4 Michael Hanselmann
  """
890 25ce3ec4 Michael Hanselmann
  assert console.Validate()
891 25ce3ec4 Michael Hanselmann
892 25ce3ec4 Michael Hanselmann
  if console.kind == constants.CONS_MESSAGE:
893 25ce3ec4 Michael Hanselmann
    feedback_fn(console.message)
894 25ce3ec4 Michael Hanselmann
  elif console.kind == constants.CONS_VNC:
895 25ce3ec4 Michael Hanselmann
    feedback_fn("Instance %s has VNC listening on %s:%s (display %s),"
896 25ce3ec4 Michael Hanselmann
                " URL <vnc://%s:%s/>",
897 25ce3ec4 Michael Hanselmann
                console.instance, console.host, console.port,
898 25ce3ec4 Michael Hanselmann
                console.display, console.host, console.port)
899 25ce3ec4 Michael Hanselmann
  elif console.kind == constants.CONS_SSH:
900 25ce3ec4 Michael Hanselmann
    # Convert to string if not already one
901 25ce3ec4 Michael Hanselmann
    if isinstance(console.command, basestring):
902 25ce3ec4 Michael Hanselmann
      cmd = console.command
903 25ce3ec4 Michael Hanselmann
    else:
904 25ce3ec4 Michael Hanselmann
      cmd = utils.ShellQuoteArgs(console.command)
905 25ce3ec4 Michael Hanselmann
906 25ce3ec4 Michael Hanselmann
    srun = ssh.SshRunner(cluster_name=cluster_name)
907 25ce3ec4 Michael Hanselmann
    ssh_cmd = srun.BuildCmd(console.host, console.user, cmd,
908 25ce3ec4 Michael Hanselmann
                            batch=True, quiet=False, tty=True)
909 25ce3ec4 Michael Hanselmann
910 25ce3ec4 Michael Hanselmann
    if show_command:
911 25ce3ec4 Michael Hanselmann
      feedback_fn(utils.ShellQuoteArgs(ssh_cmd))
912 25ce3ec4 Michael Hanselmann
    else:
913 25ce3ec4 Michael Hanselmann
      result = _runcmd_fn(ssh_cmd, interactive=True)
914 25ce3ec4 Michael Hanselmann
      if result.failed:
915 25ce3ec4 Michael Hanselmann
        logging.error("Console command \"%s\" failed with reason '%s' and"
916 25ce3ec4 Michael Hanselmann
                      " output %r", result.cmd, result.fail_reason,
917 25ce3ec4 Michael Hanselmann
                      result.output)
918 25ce3ec4 Michael Hanselmann
        raise errors.OpExecError("Connection to console of instance %s failed,"
919 25ce3ec4 Michael Hanselmann
                                 " please check cluster configuration" %
920 25ce3ec4 Michael Hanselmann
                                 console.instance)
921 51c6e7b5 Michael Hanselmann
  else:
922 25ce3ec4 Michael Hanselmann
    raise errors.GenericError("Unknown console type '%s'" % console.kind)
923 678aa6d3 Michael Hanselmann
924 678aa6d3 Michael Hanselmann
  return constants.EXIT_SUCCESS
925 a8083063 Iustin Pop
926 a8083063 Iustin Pop
927 e2736e40 Guido Trotter
def _FormatLogicalID(dev_type, logical_id, roman):
928 19708787 Iustin Pop
  """Formats the logical_id of a disk.
929 19708787 Iustin Pop

930 19708787 Iustin Pop
  """
931 19708787 Iustin Pop
  if dev_type == constants.LD_DRBD8:
932 19708787 Iustin Pop
    node_a, node_b, port, minor_a, minor_b, key = logical_id
933 19708787 Iustin Pop
    data = [
934 e2736e40 Guido Trotter
      ("nodeA", "%s, minor=%s" % (node_a, compat.TryToRoman(minor_a,
935 e2736e40 Guido Trotter
                                                            convert=roman))),
936 e2736e40 Guido Trotter
      ("nodeB", "%s, minor=%s" % (node_b, compat.TryToRoman(minor_b,
937 e2736e40 Guido Trotter
                                                            convert=roman))),
938 e2736e40 Guido Trotter
      ("port", compat.TryToRoman(port, convert=roman)),
939 19708787 Iustin Pop
      ("auth key", key),
940 19708787 Iustin Pop
      ]
941 19708787 Iustin Pop
  elif dev_type == constants.LD_LV:
942 19708787 Iustin Pop
    vg_name, lv_name = logical_id
943 19708787 Iustin Pop
    data = ["%s/%s" % (vg_name, lv_name)]
944 19708787 Iustin Pop
  else:
945 19708787 Iustin Pop
    data = [str(logical_id)]
946 19708787 Iustin Pop
947 19708787 Iustin Pop
  return data
948 19708787 Iustin Pop
949 19708787 Iustin Pop
950 e2736e40 Guido Trotter
def _FormatBlockDevInfo(idx, top_level, dev, static, roman):
951 a8083063 Iustin Pop
  """Show block device information.
952 a8083063 Iustin Pop

953 7232c04c Iustin Pop
  This is only used by L{ShowInstanceConfig}, but it's too big to be
954 a8083063 Iustin Pop
  left for an inline definition.
955 a8083063 Iustin Pop

956 19708787 Iustin Pop
  @type idx: int
957 19708787 Iustin Pop
  @param idx: the index of the current disk
958 19708787 Iustin Pop
  @type top_level: boolean
959 19708787 Iustin Pop
  @param top_level: if this a top-level disk?
960 7232c04c Iustin Pop
  @type dev: dict
961 7232c04c Iustin Pop
  @param dev: dictionary with disk information
962 7232c04c Iustin Pop
  @type static: boolean
963 7232c04c Iustin Pop
  @param static: wheter the device information doesn't contain
964 7232c04c Iustin Pop
      runtime information but only static data
965 e2736e40 Guido Trotter
  @type roman: boolean
966 e2736e40 Guido Trotter
  @param roman: whether to try to use roman integers
967 19708787 Iustin Pop
  @return: a list of either strings, tuples or lists
968 19708787 Iustin Pop
      (which should be formatted at a higher indent level)
969 7232c04c Iustin Pop

970 a8083063 Iustin Pop
  """
971 19708787 Iustin Pop
  def helper(dtype, status):
972 7232c04c Iustin Pop
    """Format one line for physical device status.
973 7232c04c Iustin Pop

974 7232c04c Iustin Pop
    @type dtype: str
975 7232c04c Iustin Pop
    @param dtype: a constant from the L{constants.LDS_BLOCK} set
976 7232c04c Iustin Pop
    @type status: tuple
977 7232c04c Iustin Pop
    @param status: a tuple as returned from L{backend.FindBlockDevice}
978 19708787 Iustin Pop
    @return: the string representing the status
979 7232c04c Iustin Pop

980 7232c04c Iustin Pop
    """
981 a8083063 Iustin Pop
    if not status:
982 19708787 Iustin Pop
      return "not active"
983 19708787 Iustin Pop
    txt = ""
984 f208978a Michael Hanselmann
    (path, major, minor, syncp, estt, degr, ldisk_status) = status
985 19708787 Iustin Pop
    if major is None:
986 19708787 Iustin Pop
      major_string = "N/A"
987 a8083063 Iustin Pop
    else:
988 e2736e40 Guido Trotter
      major_string = str(compat.TryToRoman(major, convert=roman))
989 fd38ef95 Manuel Franceschini
990 19708787 Iustin Pop
    if minor is None:
991 19708787 Iustin Pop
      minor_string = "N/A"
992 19708787 Iustin Pop
    else:
993 e2736e40 Guido Trotter
      minor_string = str(compat.TryToRoman(minor, convert=roman))
994 19708787 Iustin Pop
995 19708787 Iustin Pop
    txt += ("%s (%s:%s)" % (path, major_string, minor_string))
996 19708787 Iustin Pop
    if dtype in (constants.LD_DRBD8, ):
997 19708787 Iustin Pop
      if syncp is not None:
998 19708787 Iustin Pop
        sync_text = "*RECOVERING* %5.2f%%," % syncp
999 19708787 Iustin Pop
        if estt:
1000 e2736e40 Guido Trotter
          sync_text += " ETA %ss" % compat.TryToRoman(estt, convert=roman)
1001 9db6dbce Iustin Pop
        else:
1002 19708787 Iustin Pop
          sync_text += " ETA unknown"
1003 19708787 Iustin Pop
      else:
1004 19708787 Iustin Pop
        sync_text = "in sync"
1005 19708787 Iustin Pop
      if degr:
1006 19708787 Iustin Pop
        degr_text = "*DEGRADED*"
1007 19708787 Iustin Pop
      else:
1008 19708787 Iustin Pop
        degr_text = "ok"
1009 f208978a Michael Hanselmann
      if ldisk_status == constants.LDS_FAULTY:
1010 19708787 Iustin Pop
        ldisk_text = " *MISSING DISK*"
1011 f208978a Michael Hanselmann
      elif ldisk_status == constants.LDS_UNKNOWN:
1012 f208978a Michael Hanselmann
        ldisk_text = " *UNCERTAIN STATE*"
1013 19708787 Iustin Pop
      else:
1014 19708787 Iustin Pop
        ldisk_text = ""
1015 19708787 Iustin Pop
      txt += (" %s, status %s%s" % (sync_text, degr_text, ldisk_text))
1016 19708787 Iustin Pop
    elif dtype == constants.LD_LV:
1017 f208978a Michael Hanselmann
      if ldisk_status == constants.LDS_FAULTY:
1018 19708787 Iustin Pop
        ldisk_text = " *FAILED* (failed drive?)"
1019 19708787 Iustin Pop
      else:
1020 19708787 Iustin Pop
        ldisk_text = ""
1021 19708787 Iustin Pop
      txt += ldisk_text
1022 19708787 Iustin Pop
    return txt
1023 19708787 Iustin Pop
1024 19708787 Iustin Pop
  # the header
1025 19708787 Iustin Pop
  if top_level:
1026 19708787 Iustin Pop
    if dev["iv_name"] is not None:
1027 19708787 Iustin Pop
      txt = dev["iv_name"]
1028 19708787 Iustin Pop
    else:
1029 e2736e40 Guido Trotter
      txt = "disk %s" % compat.TryToRoman(idx, convert=roman)
1030 a8083063 Iustin Pop
  else:
1031 e2736e40 Guido Trotter
    txt = "child %s" % compat.TryToRoman(idx, convert=roman)
1032 c98162a7 Iustin Pop
  if isinstance(dev["size"], int):
1033 c98162a7 Iustin Pop
    nice_size = utils.FormatUnit(dev["size"], "h")
1034 c98162a7 Iustin Pop
  else:
1035 c98162a7 Iustin Pop
    nice_size = dev["size"]
1036 c98162a7 Iustin Pop
  d1 = ["- %s: %s, size %s" % (txt, dev["dev_type"], nice_size)]
1037 19708787 Iustin Pop
  data = []
1038 19708787 Iustin Pop
  if top_level:
1039 19708787 Iustin Pop
    data.append(("access mode", dev["mode"]))
1040 a8083063 Iustin Pop
  if dev["logical_id"] is not None:
1041 19708787 Iustin Pop
    try:
1042 e2736e40 Guido Trotter
      l_id = _FormatLogicalID(dev["dev_type"], dev["logical_id"], roman)
1043 19708787 Iustin Pop
    except ValueError:
1044 19708787 Iustin Pop
      l_id = [str(dev["logical_id"])]
1045 19708787 Iustin Pop
    if len(l_id) == 1:
1046 19708787 Iustin Pop
      data.append(("logical_id", l_id[0]))
1047 19708787 Iustin Pop
    else:
1048 19708787 Iustin Pop
      data.extend(l_id)
1049 a8083063 Iustin Pop
  elif dev["physical_id"] is not None:
1050 19708787 Iustin Pop
    data.append("physical_id:")
1051 19708787 Iustin Pop
    data.append([dev["physical_id"]])
1052 57821cac Iustin Pop
  if not static:
1053 19708787 Iustin Pop
    data.append(("on primary", helper(dev["dev_type"], dev["pstatus"])))
1054 57821cac Iustin Pop
  if dev["sstatus"] and not static:
1055 19708787 Iustin Pop
    data.append(("on secondary", helper(dev["dev_type"], dev["sstatus"])))
1056 a8083063 Iustin Pop
1057 a8083063 Iustin Pop
  if dev["children"]:
1058 19708787 Iustin Pop
    data.append("child devices:")
1059 19708787 Iustin Pop
    for c_idx, child in enumerate(dev["children"]):
1060 e2736e40 Guido Trotter
      data.append(_FormatBlockDevInfo(c_idx, False, child, static, roman))
1061 19708787 Iustin Pop
  d1.append(data)
1062 19708787 Iustin Pop
  return d1
1063 a8083063 Iustin Pop
1064 a8083063 Iustin Pop
1065 19708787 Iustin Pop
def _FormatList(buf, data, indent_level):
1066 19708787 Iustin Pop
  """Formats a list of data at a given indent level.
1067 19708787 Iustin Pop

1068 19708787 Iustin Pop
  If the element of the list is:
1069 19708787 Iustin Pop
    - a string, it is simply formatted as is
1070 19708787 Iustin Pop
    - a tuple, it will be split into key, value and the all the
1071 19708787 Iustin Pop
      values in a list will be aligned all at the same start column
1072 19708787 Iustin Pop
    - a list, will be recursively formatted
1073 19708787 Iustin Pop

1074 19708787 Iustin Pop
  @type buf: StringIO
1075 19708787 Iustin Pop
  @param buf: the buffer into which we write the output
1076 19708787 Iustin Pop
  @param data: the list to format
1077 19708787 Iustin Pop
  @type indent_level: int
1078 19708787 Iustin Pop
  @param indent_level: the indent level to format at
1079 19708787 Iustin Pop

1080 19708787 Iustin Pop
  """
1081 19708787 Iustin Pop
  max_tlen = max([len(elem[0]) for elem in data
1082 19708787 Iustin Pop
                 if isinstance(elem, tuple)] or [0])
1083 19708787 Iustin Pop
  for elem in data:
1084 19708787 Iustin Pop
    if isinstance(elem, basestring):
1085 19708787 Iustin Pop
      buf.write("%*s%s\n" % (2*indent_level, "", elem))
1086 19708787 Iustin Pop
    elif isinstance(elem, tuple):
1087 19708787 Iustin Pop
      key, value = elem
1088 19708787 Iustin Pop
      spacer = "%*s" % (max_tlen - len(key), "")
1089 19708787 Iustin Pop
      buf.write("%*s%s:%s %s\n" % (2*indent_level, "", key, spacer, value))
1090 19708787 Iustin Pop
    elif isinstance(elem, list):
1091 19708787 Iustin Pop
      _FormatList(buf, elem, indent_level+1)
1092 19708787 Iustin Pop
1093 98825740 Michael Hanselmann
1094 a8083063 Iustin Pop
def ShowInstanceConfig(opts, args):
1095 a8083063 Iustin Pop
  """Compute instance run-time status.
1096 a8083063 Iustin Pop

1097 7232c04c Iustin Pop
  @param opts: the command line options selected by the user
1098 7232c04c Iustin Pop
  @type args: list
1099 7232c04c Iustin Pop
  @param args: either an empty list, and then we query all
1100 7232c04c Iustin Pop
      instances, or should contain a list of instance names
1101 7232c04c Iustin Pop
  @rtype: int
1102 7232c04c Iustin Pop
  @return: the desired exit code
1103 7232c04c Iustin Pop

1104 a8083063 Iustin Pop
  """
1105 220cde0b Guido Trotter
  if not args and not opts.show_all:
1106 220cde0b Guido Trotter
    ToStderr("No instance selected."
1107 220cde0b Guido Trotter
             " Please pass in --all if you want to query all instances.\n"
1108 220cde0b Guido Trotter
             "Note that this can take a long time on a big cluster.")
1109 220cde0b Guido Trotter
    return 1
1110 220cde0b Guido Trotter
  elif args and opts.show_all:
1111 220cde0b Guido Trotter
    ToStderr("Cannot use --all if you specify instance names.")
1112 220cde0b Guido Trotter
    return 1
1113 220cde0b Guido Trotter
1114 a8083063 Iustin Pop
  retcode = 0
1115 dc28c4e4 Iustin Pop
  op = opcodes.OpInstanceQueryData(instances=args, static=opts.static)
1116 400ca2f7 Iustin Pop
  result = SubmitOpCode(op, opts=opts)
1117 a8083063 Iustin Pop
  if not result:
1118 3a24c527 Iustin Pop
    ToStdout("No instances.")
1119 a8083063 Iustin Pop
    return 1
1120 a8083063 Iustin Pop
1121 a8083063 Iustin Pop
  buf = StringIO()
1122 a8083063 Iustin Pop
  retcode = 0
1123 a8083063 Iustin Pop
  for instance_name in result:
1124 a8083063 Iustin Pop
    instance = result[instance_name]
1125 a8083063 Iustin Pop
    buf.write("Instance name: %s\n" % instance["name"])
1126 033d58b0 Iustin Pop
    buf.write("UUID: %s\n" % instance["uuid"])
1127 e2736e40 Guido Trotter
    buf.write("Serial number: %s\n" %
1128 e2736e40 Guido Trotter
              compat.TryToRoman(instance["serial_no"],
1129 e2736e40 Guido Trotter
                                convert=opts.roman_integers))
1130 90f72445 Iustin Pop
    buf.write("Creation time: %s\n" % utils.FormatTime(instance["ctime"]))
1131 90f72445 Iustin Pop
    buf.write("Modification time: %s\n" % utils.FormatTime(instance["mtime"]))
1132 57821cac Iustin Pop
    buf.write("State: configured to be %s" % instance["config_state"])
1133 57821cac Iustin Pop
    if not opts.static:
1134 57821cac Iustin Pop
      buf.write(", actual state is %s" % instance["run_state"])
1135 57821cac Iustin Pop
    buf.write("\n")
1136 57821cac Iustin Pop
    ##buf.write("Considered for memory checks in cluster verify: %s\n" %
1137 57821cac Iustin Pop
    ##          instance["auto_balance"])
1138 a8083063 Iustin Pop
    buf.write("  Nodes:\n")
1139 a8083063 Iustin Pop
    buf.write("    - primary: %s\n" % instance["pnode"])
1140 1f864b60 Iustin Pop
    buf.write("    - secondaries: %s\n" % utils.CommaJoin(instance["snodes"]))
1141 a8083063 Iustin Pop
    buf.write("  Operating system: %s\n" % instance["os"])
1142 acd19189 René Nussbaumer
    FormatParameterDict(buf, instance["os_instance"], instance["os_actual"],
1143 acd19189 René Nussbaumer
                        level=2)
1144 a8340917 Iustin Pop
    if instance.has_key("network_port"):
1145 e2736e40 Guido Trotter
      buf.write("  Allocated network port: %s\n" %
1146 e2736e40 Guido Trotter
                compat.TryToRoman(instance["network_port"],
1147 e2736e40 Guido Trotter
                                  convert=opts.roman_integers))
1148 24838135 Iustin Pop
    buf.write("  Hypervisor: %s\n" % instance["hypervisor"])
1149 dfff41f8 Guido Trotter
1150 dfff41f8 Guido Trotter
    # custom VNC console information
1151 dfff41f8 Guido Trotter
    vnc_bind_address = instance["hv_actual"].get(constants.HV_VNC_BIND_ADDRESS,
1152 dfff41f8 Guido Trotter
                                                 None)
1153 dfff41f8 Guido Trotter
    if vnc_bind_address:
1154 dfff41f8 Guido Trotter
      port = instance["network_port"]
1155 dfff41f8 Guido Trotter
      display = int(port) - constants.VNC_BASE_PORT
1156 9769bb78 Manuel Franceschini
      if display > 0 and vnc_bind_address == constants.IP4_ADDRESS_ANY:
1157 dfff41f8 Guido Trotter
        vnc_console_port = "%s:%s (display %s)" % (instance["pnode"],
1158 dfff41f8 Guido Trotter
                                                   port,
1159 dfff41f8 Guido Trotter
                                                   display)
1160 8b312c1d Manuel Franceschini
      elif display > 0 and netutils.IP4Address.IsValid(vnc_bind_address):
1161 dfff41f8 Guido Trotter
        vnc_console_port = ("%s:%s (node %s) (display %s)" %
1162 dfff41f8 Guido Trotter
                             (vnc_bind_address, port,
1163 dfff41f8 Guido Trotter
                              instance["pnode"], display))
1164 a8340917 Iustin Pop
      else:
1165 dfff41f8 Guido Trotter
        # vnc bind address is a file
1166 dfff41f8 Guido Trotter
        vnc_console_port = "%s:%s" % (instance["pnode"],
1167 dfff41f8 Guido Trotter
                                      vnc_bind_address)
1168 24838135 Iustin Pop
      buf.write("    - console connection: vnc to %s\n" % vnc_console_port)
1169 24838135 Iustin Pop
1170 acd19189 René Nussbaumer
    FormatParameterDict(buf, instance["hv_instance"], instance["hv_actual"],
1171 acd19189 René Nussbaumer
                        level=2)
1172 a8083063 Iustin Pop
    buf.write("  Hardware:\n")
1173 e2736e40 Guido Trotter
    buf.write("    - VCPUs: %s\n" %
1174 e2736e40 Guido Trotter
              compat.TryToRoman(instance["be_actual"][constants.BE_VCPUS],
1175 e2736e40 Guido Trotter
                                convert=opts.roman_integers))
1176 e2736e40 Guido Trotter
    buf.write("    - memory: %sMiB\n" %
1177 e2736e40 Guido Trotter
              compat.TryToRoman(instance["be_actual"][constants.BE_MEMORY],
1178 e2736e40 Guido Trotter
                                convert=opts.roman_integers))
1179 d2acfe27 Iustin Pop
    buf.write("    - NICs:\n")
1180 14ea9302 Guido Trotter
    for idx, (ip, mac, mode, link) in enumerate(instance["nics"]):
1181 0b13832c Guido Trotter
      buf.write("      - nic/%d: MAC: %s, IP: %s, mode: %s, link: %s\n" %
1182 0b13832c Guido Trotter
                (idx, mac, ip, mode, link))
1183 b577dac4 Michael Hanselmann
    buf.write("  Disk template: %s\n" % instance["disk_template"])
1184 19708787 Iustin Pop
    buf.write("  Disks:\n")
1185 a8083063 Iustin Pop
1186 19708787 Iustin Pop
    for idx, device in enumerate(instance["disks"]):
1187 e2736e40 Guido Trotter
      _FormatList(buf, _FormatBlockDevInfo(idx, True, device, opts.static,
1188 e2736e40 Guido Trotter
                  opts.roman_integers), 2)
1189 a8083063 Iustin Pop
1190 3a24c527 Iustin Pop
  ToStdout(buf.getvalue().rstrip('\n'))
1191 a8083063 Iustin Pop
  return retcode
1192 a8083063 Iustin Pop
1193 a8083063 Iustin Pop
1194 7767bbf5 Manuel Franceschini
def SetInstanceParams(opts, args):
1195 a8083063 Iustin Pop
  """Modifies an instance.
1196 a8083063 Iustin Pop

1197 a8083063 Iustin Pop
  All parameters take effect only at the next restart of the instance.
1198 a8083063 Iustin Pop

1199 7232c04c Iustin Pop
  @param opts: the command line options selected by the user
1200 7232c04c Iustin Pop
  @type args: list
1201 7232c04c Iustin Pop
  @param args: should contain only one element, the instance name
1202 7232c04c Iustin Pop
  @rtype: int
1203 7232c04c Iustin Pop
  @return: the desired exit code
1204 a8083063 Iustin Pop

1205 a8083063 Iustin Pop
  """
1206 e29e9550 Iustin Pop
  if not (opts.nics or opts.disks or opts.disk_template or
1207 1052d622 Iustin Pop
          opts.hvparams or opts.beparams or opts.os or opts.osparams):
1208 3a24c527 Iustin Pop
    ToStderr("Please give at least one of the parameters.")
1209 a8083063 Iustin Pop
    return 1
1210 a8083063 Iustin Pop
1211 467ae11e Guido Trotter
  for param in opts.beparams:
1212 e9d622bc Guido Trotter
    if isinstance(opts.beparams[param], basestring):
1213 e9d622bc Guido Trotter
      if opts.beparams[param].lower() == "default":
1214 e9d622bc Guido Trotter
        opts.beparams[param] = constants.VALUE_DEFAULT
1215 a5728081 Guido Trotter
1216 a5728081 Guido Trotter
  utils.ForceDictType(opts.beparams, constants.BES_PARAMETER_TYPES,
1217 a5728081 Guido Trotter
                      allowed_values=[constants.VALUE_DEFAULT])
1218 467ae11e Guido Trotter
1219 48f212d7 Iustin Pop
  for param in opts.hvparams:
1220 48f212d7 Iustin Pop
    if isinstance(opts.hvparams[param], basestring):
1221 48f212d7 Iustin Pop
      if opts.hvparams[param].lower() == "default":
1222 48f212d7 Iustin Pop
        opts.hvparams[param] = constants.VALUE_DEFAULT
1223 a5728081 Guido Trotter
1224 48f212d7 Iustin Pop
  utils.ForceDictType(opts.hvparams, constants.HVS_PARAMETER_TYPES,
1225 a5728081 Guido Trotter
                      allowed_values=[constants.VALUE_DEFAULT])
1226 61be6ba4 Iustin Pop
1227 24991749 Iustin Pop
  for idx, (nic_op, nic_dict) in enumerate(opts.nics):
1228 24991749 Iustin Pop
    try:
1229 24991749 Iustin Pop
      nic_op = int(nic_op)
1230 24991749 Iustin Pop
      opts.nics[idx] = (nic_op, nic_dict)
1231 691744c4 Iustin Pop
    except (TypeError, ValueError):
1232 24991749 Iustin Pop
      pass
1233 24991749 Iustin Pop
1234 24991749 Iustin Pop
  for idx, (disk_op, disk_dict) in enumerate(opts.disks):
1235 24991749 Iustin Pop
    try:
1236 24991749 Iustin Pop
      disk_op = int(disk_op)
1237 24991749 Iustin Pop
      opts.disks[idx] = (disk_op, disk_dict)
1238 691744c4 Iustin Pop
    except (TypeError, ValueError):
1239 24991749 Iustin Pop
      pass
1240 24991749 Iustin Pop
    if disk_op == constants.DDM_ADD:
1241 24991749 Iustin Pop
      if 'size' not in disk_dict:
1242 debac808 Iustin Pop
        raise errors.OpPrereqError("Missing required parameter 'size'",
1243 debac808 Iustin Pop
                                   errors.ECODE_INVAL)
1244 24991749 Iustin Pop
      disk_dict['size'] = utils.ParseUnit(disk_dict['size'])
1245 24991749 Iustin Pop
1246 e29e9550 Iustin Pop
  if (opts.disk_template and
1247 e29e9550 Iustin Pop
      opts.disk_template in constants.DTS_NET_MIRROR and
1248 e29e9550 Iustin Pop
      not opts.node):
1249 e29e9550 Iustin Pop
    ToStderr("Changing the disk template to a mirrored one requires"
1250 e29e9550 Iustin Pop
             " specifying a secondary node")
1251 e29e9550 Iustin Pop
    return 1
1252 e29e9550 Iustin Pop
1253 9a3cc7ae Iustin Pop
  op = opcodes.OpInstanceSetParams(instance_name=args[0],
1254 24991749 Iustin Pop
                                   nics=opts.nics,
1255 24991749 Iustin Pop
                                   disks=opts.disks,
1256 e29e9550 Iustin Pop
                                   disk_template=opts.disk_template,
1257 e29e9550 Iustin Pop
                                   remote_node=opts.node,
1258 48f212d7 Iustin Pop
                                   hvparams=opts.hvparams,
1259 338e51e8 Iustin Pop
                                   beparams=opts.beparams,
1260 96b39bcc Iustin Pop
                                   os_name=opts.os,
1261 1052d622 Iustin Pop
                                   osparams=opts.osparams,
1262 96b39bcc Iustin Pop
                                   force_variant=opts.force_variant,
1263 4300c4b6 Guido Trotter
                                   force=opts.force)
1264 31a853d2 Iustin Pop
1265 6340bb0a Iustin Pop
  # even if here we process the result, we allow submit only
1266 6340bb0a Iustin Pop
  result = SubmitOrSend(op, opts)
1267 a8083063 Iustin Pop
1268 a8083063 Iustin Pop
  if result:
1269 3a24c527 Iustin Pop
    ToStdout("Modified instance %s", args[0])
1270 a8083063 Iustin Pop
    for param, data in result:
1271 3a24c527 Iustin Pop
      ToStdout(" - %-5s -> %s", param, data)
1272 e29e9550 Iustin Pop
    ToStdout("Please don't forget that most parameters take effect"
1273 3a24c527 Iustin Pop
             " only at the next start of the instance.")
1274 a8083063 Iustin Pop
  return 0
1275 a8083063 Iustin Pop
1276 a8083063 Iustin Pop
1277 312ac745 Iustin Pop
# multi-instance selection options
1278 c38c44ad Michael Hanselmann
m_force_multi = cli_option("--force-multiple", dest="force_multi",
1279 c38c44ad Michael Hanselmann
                           help="Do not ask for confirmation when more than"
1280 c38c44ad Michael Hanselmann
                           " one instance is affected",
1281 c38c44ad Michael Hanselmann
                           action="store_true", default=False)
1282 804a1e8e Iustin Pop
1283 c38c44ad Michael Hanselmann
m_pri_node_opt = cli_option("--primary", dest="multi_mode",
1284 c38c44ad Michael Hanselmann
                            help="Filter by nodes (primary only)",
1285 c38c44ad Michael Hanselmann
                            const=_SHUTDOWN_NODES_PRI, action="store_const")
1286 312ac745 Iustin Pop
1287 c38c44ad Michael Hanselmann
m_sec_node_opt = cli_option("--secondary", dest="multi_mode",
1288 c38c44ad Michael Hanselmann
                            help="Filter by nodes (secondary only)",
1289 c38c44ad Michael Hanselmann
                            const=_SHUTDOWN_NODES_SEC, action="store_const")
1290 312ac745 Iustin Pop
1291 c38c44ad Michael Hanselmann
m_node_opt = cli_option("--node", dest="multi_mode",
1292 c38c44ad Michael Hanselmann
                        help="Filter by nodes (primary and secondary)",
1293 c38c44ad Michael Hanselmann
                        const=_SHUTDOWN_NODES_BOTH, action="store_const")
1294 312ac745 Iustin Pop
1295 c38c44ad Michael Hanselmann
m_clust_opt = cli_option("--all", dest="multi_mode",
1296 c38c44ad Michael Hanselmann
                         help="Select all instances in the cluster",
1297 c38c44ad Michael Hanselmann
                         const=_SHUTDOWN_CLUSTER, action="store_const")
1298 312ac745 Iustin Pop
1299 c38c44ad Michael Hanselmann
m_inst_opt = cli_option("--instance", dest="multi_mode",
1300 c38c44ad Michael Hanselmann
                        help="Filter by instance name [default]",
1301 c38c44ad Michael Hanselmann
                        const=_SHUTDOWN_INSTANCES, action="store_const")
1302 312ac745 Iustin Pop
1303 39dfd93e René Nussbaumer
m_node_tags_opt = cli_option("--node-tags", dest="multi_mode",
1304 39dfd93e René Nussbaumer
                             help="Filter by node tag",
1305 39dfd93e René Nussbaumer
                             const=_SHUTDOWN_NODES_BOTH_BY_TAGS,
1306 39dfd93e René Nussbaumer
                             action="store_const")
1307 39dfd93e René Nussbaumer
1308 39dfd93e René Nussbaumer
m_pri_node_tags_opt = cli_option("--pri-node-tags", dest="multi_mode",
1309 39dfd93e René Nussbaumer
                                 help="Filter by primary node tag",
1310 39dfd93e René Nussbaumer
                                 const=_SHUTDOWN_NODES_PRI_BY_TAGS,
1311 39dfd93e René Nussbaumer
                                 action="store_const")
1312 39dfd93e René Nussbaumer
1313 39dfd93e René Nussbaumer
m_sec_node_tags_opt = cli_option("--sec-node-tags", dest="multi_mode",
1314 39dfd93e René Nussbaumer
                                 help="Filter by secondary node tag",
1315 39dfd93e René Nussbaumer
                                 const=_SHUTDOWN_NODES_SEC_BY_TAGS,
1316 39dfd93e René Nussbaumer
                                 action="store_const")
1317 39dfd93e René Nussbaumer
1318 39dfd93e René Nussbaumer
m_inst_tags_opt = cli_option("--tags", dest="multi_mode",
1319 39dfd93e René Nussbaumer
                             help="Filter by instance tag",
1320 39dfd93e René Nussbaumer
                             const=_SHUTDOWN_INSTANCES_BY_TAGS,
1321 39dfd93e René Nussbaumer
                             action="store_const")
1322 312ac745 Iustin Pop
1323 a8083063 Iustin Pop
# this is defined separately due to readability only
1324 a8083063 Iustin Pop
add_opts = [
1325 064c21f8 Iustin Pop
  NOSTART_OPT,
1326 064c21f8 Iustin Pop
  OS_OPT,
1327 06073e85 Guido Trotter
  FORCE_VARIANT_OPT,
1328 25a8792c Iustin Pop
  NO_INSTALL_OPT,
1329 a8083063 Iustin Pop
  ]
1330 a8083063 Iustin Pop
1331 a8083063 Iustin Pop
commands = {
1332 6ea815cf Iustin Pop
  'add': (
1333 eb28ecf6 Guido Trotter
    AddInstance, [ArgHost(min=1, max=1)], COMMON_CREATE_OPTS + add_opts,
1334 6ea815cf Iustin Pop
    "[...] -t disk-type -n node[:secondary-node] -o os-type <name>",
1335 6ea815cf Iustin Pop
    "Creates and adds a new instance to the cluster"),
1336 6ea815cf Iustin Pop
  'batch-create': (
1337 aa06f8c6 Michael Hanselmann
    BatchCreate, [ArgFile(min=1, max=1)], [DRY_RUN_OPT, PRIORITY_OPT],
1338 6ea815cf Iustin Pop
    "<instances.json>",
1339 6ea815cf Iustin Pop
    "Create a bunch of instances based on specs in the file."),
1340 6ea815cf Iustin Pop
  'console': (
1341 6ea815cf Iustin Pop
    ConnectToInstanceConsole, ARGS_ONE_INSTANCE,
1342 aa06f8c6 Michael Hanselmann
    [SHOWCMD_OPT, PRIORITY_OPT],
1343 6ea815cf Iustin Pop
    "[--show-cmd] <instance>", "Opens a console on the specified instance"),
1344 6ea815cf Iustin Pop
  'failover': (
1345 6ea815cf Iustin Pop
    FailoverInstance, ARGS_ONE_INSTANCE,
1346 db5a8a2d Iustin Pop
    [FORCE_OPT, IGNORE_CONSIST_OPT, SUBMIT_OPT, SHUTDOWN_TIMEOUT_OPT,
1347 aa06f8c6 Michael Hanselmann
     DRY_RUN_OPT, PRIORITY_OPT],
1348 6ea815cf Iustin Pop
    "[-f] <instance>", "Stops the instance and starts it on the backup node,"
1349 6ea815cf Iustin Pop
    " using the remote mirror (only for instances of type drbd)"),
1350 6ea815cf Iustin Pop
  'migrate': (
1351 6ea815cf Iustin Pop
    MigrateInstance, ARGS_ONE_INSTANCE,
1352 aa06f8c6 Michael Hanselmann
    [FORCE_OPT, NONLIVE_OPT, MIGRATION_MODE_OPT, CLEANUP_OPT, DRY_RUN_OPT,
1353 aa06f8c6 Michael Hanselmann
     PRIORITY_OPT],
1354 6ea815cf Iustin Pop
    "[-f] <instance>", "Migrate instance to its secondary node"
1355 6ea815cf Iustin Pop
    " (only for instances of type drbd)"),
1356 6ea815cf Iustin Pop
  'move': (
1357 6ea815cf Iustin Pop
    MoveInstance, ARGS_ONE_INSTANCE,
1358 db5a8a2d Iustin Pop
    [FORCE_OPT, SUBMIT_OPT, SINGLE_NODE_OPT, SHUTDOWN_TIMEOUT_OPT,
1359 aa06f8c6 Michael Hanselmann
     DRY_RUN_OPT, PRIORITY_OPT],
1360 6ea815cf Iustin Pop
    "[-f] <instance>", "Move instance to an arbitrary node"
1361 6ea815cf Iustin Pop
    " (only for instances of type file and lv)"),
1362 6ea815cf Iustin Pop
  'info': (
1363 6ea815cf Iustin Pop
    ShowInstanceConfig, ARGS_MANY_INSTANCES,
1364 aa06f8c6 Michael Hanselmann
    [STATIC_OPT, ALL_OPT, ROMAN_OPT, PRIORITY_OPT],
1365 6ea815cf Iustin Pop
    "[-s] {--all | <instance>...}",
1366 6ea815cf Iustin Pop
    "Show information on the specified instance(s)"),
1367 6ea815cf Iustin Pop
  'list': (
1368 6ea815cf Iustin Pop
    ListInstances, ARGS_MANY_INSTANCES,
1369 f0b1bafe Iustin Pop
    [NOHDR_OPT, SEP_OPT, USEUNITS_OPT, FIELDS_OPT, VERBOSE_OPT],
1370 6ea815cf Iustin Pop
    "[<instance>...]",
1371 b82c5ff5 Michael Hanselmann
    "Lists the instances and their status. The available fields can be shown"
1372 b82c5ff5 Michael Hanselmann
    " using the \"list-fields\" command (see the man page for details)."
1373 b82c5ff5 Michael Hanselmann
    " The default field list is (in order): %s." %
1374 b82c5ff5 Michael Hanselmann
    utils.CommaJoin(_LIST_DEF_FIELDS),
1375 6ea815cf Iustin Pop
    ),
1376 b82c5ff5 Michael Hanselmann
  "list-fields": (
1377 b82c5ff5 Michael Hanselmann
    ListInstanceFields, [ArgUnknown()],
1378 b82c5ff5 Michael Hanselmann
    [NOHDR_OPT, SEP_OPT],
1379 b82c5ff5 Michael Hanselmann
    "[fields...]",
1380 b82c5ff5 Michael Hanselmann
    "Lists all available fields for instances"),
1381 6ea815cf Iustin Pop
  'reinstall': (
1382 3e54ace7 Iustin Pop
    ReinstallInstance, [ArgInstance()],
1383 06073e85 Guido Trotter
    [FORCE_OPT, OS_OPT, FORCE_VARIANT_OPT, m_force_multi, m_node_opt,
1384 39dfd93e René Nussbaumer
     m_pri_node_opt, m_sec_node_opt, m_clust_opt, m_inst_opt, m_node_tags_opt,
1385 39dfd93e René Nussbaumer
     m_pri_node_tags_opt, m_sec_node_tags_opt, m_inst_tags_opt, SELECT_OS_OPT,
1386 8d8c4eff Michael Hanselmann
     SUBMIT_OPT, DRY_RUN_OPT, PRIORITY_OPT, OSPARAMS_OPT],
1387 6ea815cf Iustin Pop
    "[-f] <instance>", "Reinstall a stopped instance"),
1388 6ea815cf Iustin Pop
  'remove': (
1389 6ea815cf Iustin Pop
    RemoveInstance, ARGS_ONE_INSTANCE,
1390 db5a8a2d Iustin Pop
    [FORCE_OPT, SHUTDOWN_TIMEOUT_OPT, IGNORE_FAILURES_OPT, SUBMIT_OPT,
1391 aa06f8c6 Michael Hanselmann
     DRY_RUN_OPT, PRIORITY_OPT],
1392 6ea815cf Iustin Pop
    "[-f] <instance>", "Shuts down the instance and removes it"),
1393 6ea815cf Iustin Pop
  'rename': (
1394 6ea815cf Iustin Pop
    RenameInstance,
1395 6ea815cf Iustin Pop
    [ArgInstance(min=1, max=1), ArgHost(min=1, max=1)],
1396 aa06f8c6 Michael Hanselmann
    [NOIPCHECK_OPT, NONAMECHECK_OPT, SUBMIT_OPT, DRY_RUN_OPT, PRIORITY_OPT],
1397 6ea815cf Iustin Pop
    "<instance> <new_name>", "Rename the instance"),
1398 6ea815cf Iustin Pop
  'replace-disks': (
1399 6ea815cf Iustin Pop
    ReplaceDisks, ARGS_ONE_INSTANCE,
1400 7ea7bcf6 Iustin Pop
    [AUTO_REPLACE_OPT, DISKIDX_OPT, IALLOCATOR_OPT, EARLY_RELEASE_OPT,
1401 db5a8a2d Iustin Pop
     NEW_SECONDARY_OPT, ON_PRIMARY_OPT, ON_SECONDARY_OPT, SUBMIT_OPT,
1402 aa06f8c6 Michael Hanselmann
     DRY_RUN_OPT, PRIORITY_OPT],
1403 6ea815cf Iustin Pop
    "[-s|-p|-n NODE|-I NAME] <instance>",
1404 6ea815cf Iustin Pop
    "Replaces all disks for the instance"),
1405 6ea815cf Iustin Pop
  'modify': (
1406 6ea815cf Iustin Pop
    SetInstanceParams, ARGS_ONE_INSTANCE,
1407 e29e9550 Iustin Pop
    [BACKEND_OPT, DISK_OPT, FORCE_OPT, HVOPTS_OPT, NET_OPT, SUBMIT_OPT,
1408 1052d622 Iustin Pop
     DISK_TEMPLATE_OPT, SINGLE_NODE_OPT, OS_OPT, FORCE_VARIANT_OPT,
1409 aa06f8c6 Michael Hanselmann
     OSPARAMS_OPT, DRY_RUN_OPT, PRIORITY_OPT],
1410 6ea815cf Iustin Pop
    "<instance>", "Alters the parameters of an instance"),
1411 6ea815cf Iustin Pop
  'shutdown': (
1412 1c5945b6 Iustin Pop
    GenericManyOps("shutdown", _ShutdownInstance), [ArgInstance()],
1413 064c21f8 Iustin Pop
    [m_node_opt, m_pri_node_opt, m_sec_node_opt, m_clust_opt,
1414 39dfd93e René Nussbaumer
     m_node_tags_opt, m_pri_node_tags_opt, m_sec_node_tags_opt,
1415 db5a8a2d Iustin Pop
     m_inst_tags_opt, m_inst_opt, m_force_multi, TIMEOUT_OPT, SUBMIT_OPT,
1416 b44bd844 Michael Hanselmann
     DRY_RUN_OPT, PRIORITY_OPT, IGNORE_OFFLINE_OPT],
1417 6ea815cf Iustin Pop
    "<instance>", "Stops an instance"),
1418 6ea815cf Iustin Pop
  'startup': (
1419 1c5945b6 Iustin Pop
    GenericManyOps("startup", _StartupInstance), [ArgInstance()],
1420 39dfd93e René Nussbaumer
    [FORCE_OPT, m_force_multi, m_node_opt, m_pri_node_opt, m_sec_node_opt,
1421 39dfd93e René Nussbaumer
     m_node_tags_opt, m_pri_node_tags_opt, m_sec_node_tags_opt,
1422 39dfd93e René Nussbaumer
     m_inst_tags_opt, m_clust_opt, m_inst_opt, SUBMIT_OPT, HVOPTS_OPT,
1423 b44bd844 Michael Hanselmann
     BACKEND_OPT, DRY_RUN_OPT, PRIORITY_OPT, IGNORE_OFFLINE_OPT],
1424 6ea815cf Iustin Pop
    "<instance>", "Starts an instance"),
1425 6ea815cf Iustin Pop
  'reboot': (
1426 1c5945b6 Iustin Pop
    GenericManyOps("reboot", _RebootInstance), [ArgInstance()],
1427 064c21f8 Iustin Pop
    [m_force_multi, REBOOT_TYPE_OPT, IGNORE_SECONDARIES_OPT, m_node_opt,
1428 17c3f802 Guido Trotter
     m_pri_node_opt, m_sec_node_opt, m_clust_opt, m_inst_opt, SUBMIT_OPT,
1429 39dfd93e René Nussbaumer
     m_node_tags_opt, m_pri_node_tags_opt, m_sec_node_tags_opt,
1430 aa06f8c6 Michael Hanselmann
     m_inst_tags_opt, SHUTDOWN_TIMEOUT_OPT, DRY_RUN_OPT, PRIORITY_OPT],
1431 6ea815cf Iustin Pop
    "<instance>", "Reboots an instance"),
1432 6ea815cf Iustin Pop
  'activate-disks': (
1433 db5a8a2d Iustin Pop
    ActivateDisks, ARGS_ONE_INSTANCE,
1434 aa06f8c6 Michael Hanselmann
    [SUBMIT_OPT, IGNORE_SIZE_OPT, PRIORITY_OPT],
1435 6ea815cf Iustin Pop
    "<instance>", "Activate an instance's disks"),
1436 6ea815cf Iustin Pop
  'deactivate-disks': (
1437 aa06f8c6 Michael Hanselmann
    DeactivateDisks, ARGS_ONE_INSTANCE,
1438 c9c41373 Iustin Pop
    [FORCE_OPT, SUBMIT_OPT, DRY_RUN_OPT, PRIORITY_OPT],
1439 c9c41373 Iustin Pop
    "[-f] <instance>", "Deactivate an instance's disks"),
1440 6ea815cf Iustin Pop
  'recreate-disks': (
1441 aa06f8c6 Michael Hanselmann
    RecreateDisks, ARGS_ONE_INSTANCE,
1442 aa06f8c6 Michael Hanselmann
    [SUBMIT_OPT, DISKIDX_OPT, DRY_RUN_OPT, PRIORITY_OPT],
1443 6ea815cf Iustin Pop
    "<instance>", "Recreate an instance's disks"),
1444 6ea815cf Iustin Pop
  'grow-disk': (
1445 6ea815cf Iustin Pop
    GrowDisk,
1446 6ea815cf Iustin Pop
    [ArgInstance(min=1, max=1), ArgUnknown(min=1, max=1),
1447 6ea815cf Iustin Pop
     ArgUnknown(min=1, max=1)],
1448 aa06f8c6 Michael Hanselmann
    [SUBMIT_OPT, NWSYNC_OPT, DRY_RUN_OPT, PRIORITY_OPT],
1449 6ea815cf Iustin Pop
    "<instance> <disk> <size>", "Grow an instance's disk"),
1450 6ea815cf Iustin Pop
  'list-tags': (
1451 aa06f8c6 Michael Hanselmann
    ListTags, ARGS_ONE_INSTANCE, [PRIORITY_OPT],
1452 6ea815cf Iustin Pop
    "<instance_name>", "List the tags of the given instance"),
1453 6ea815cf Iustin Pop
  'add-tags': (
1454 6ea815cf Iustin Pop
    AddTags, [ArgInstance(min=1, max=1), ArgUnknown()],
1455 aa06f8c6 Michael Hanselmann
    [TAG_SRC_OPT, PRIORITY_OPT],
1456 6ea815cf Iustin Pop
    "<instance_name> tag...", "Add tags to the given instance"),
1457 6ea815cf Iustin Pop
  'remove-tags': (
1458 6ea815cf Iustin Pop
    RemoveTags, [ArgInstance(min=1, max=1), ArgUnknown()],
1459 aa06f8c6 Michael Hanselmann
    [TAG_SRC_OPT, PRIORITY_OPT],
1460 6ea815cf Iustin Pop
    "<instance_name> tag...", "Remove tags from given instance"),
1461 a8083063 Iustin Pop
  }
1462 a8083063 Iustin Pop
1463 7232c04c Iustin Pop
#: dictionary with aliases for commands
1464 dbfd89dd Guido Trotter
aliases = {
1465 536fda25 Guido Trotter
  'start': 'startup',
1466 536fda25 Guido Trotter
  'stop': 'shutdown',
1467 dbfd89dd Guido Trotter
  }
1468 dbfd89dd Guido Trotter
1469 a8005e17 Michael Hanselmann
1470 e792102d Michael Hanselmann
def Main():
1471 e792102d Michael Hanselmann
  return GenericMain(commands, aliases=aliases,
1472 e792102d Michael Hanselmann
                     override={"tag_type": constants.TAG_INSTANCE})