Statistics
| Branch: | Tag: | Revision:

root / lib / client / gnt_instance.py @ a59d5fa1

History | View | Annotate | Download (56.5 kB)

1 e792102d Michael Hanselmann
#
2 a8083063 Iustin Pop
#
3 a8083063 Iustin Pop
4 ef8270dc Iustin Pop
# Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012 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 b459a848 Andrea Spadaccini
# pylint: disable=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 83d4ba5e René Nussbaumer
import copy
29 312ac745 Iustin Pop
import itertools
30 0d0e9090 René Nussbaumer
import simplejson
31 25ce3ec4 Michael Hanselmann
import logging
32 a8083063 Iustin Pop
from cStringIO import StringIO
33 a8083063 Iustin Pop
34 a8083063 Iustin Pop
from ganeti.cli import *
35 a8083063 Iustin Pop
from ganeti import opcodes
36 a8083063 Iustin Pop
from ganeti import constants
37 e2736e40 Guido Trotter
from ganeti import compat
38 a8083063 Iustin Pop
from ganeti import utils
39 312ac745 Iustin Pop
from ganeti import errors
40 a744b676 Manuel Franceschini
from ganeti import netutils
41 25ce3ec4 Michael Hanselmann
from ganeti import ssh
42 25ce3ec4 Michael Hanselmann
from ganeti import objects
43 735e1318 Michael Hanselmann
from ganeti import ht
44 312ac745 Iustin Pop
45 312ac745 Iustin Pop
46 c20efaa8 Michael Hanselmann
_EXPAND_CLUSTER = "cluster"
47 c20efaa8 Michael Hanselmann
_EXPAND_NODES_BOTH = "nodes"
48 c20efaa8 Michael Hanselmann
_EXPAND_NODES_PRI = "nodes-pri"
49 c20efaa8 Michael Hanselmann
_EXPAND_NODES_SEC = "nodes-sec"
50 c20efaa8 Michael Hanselmann
_EXPAND_NODES_BOTH_BY_TAGS = "nodes-by-tags"
51 c20efaa8 Michael Hanselmann
_EXPAND_NODES_PRI_BY_TAGS = "nodes-pri-by-tags"
52 c20efaa8 Michael Hanselmann
_EXPAND_NODES_SEC_BY_TAGS = "nodes-sec-by-tags"
53 c20efaa8 Michael Hanselmann
_EXPAND_INSTANCES = "instances"
54 c20efaa8 Michael Hanselmann
_EXPAND_INSTANCES_BY_TAGS = "instances-by-tags"
55 c20efaa8 Michael Hanselmann
56 b8028dcf Michael Hanselmann
_EXPAND_NODES_TAGS_MODES = compat.UniqueFrozenset([
57 c20efaa8 Michael Hanselmann
  _EXPAND_NODES_BOTH_BY_TAGS,
58 c20efaa8 Michael Hanselmann
  _EXPAND_NODES_PRI_BY_TAGS,
59 c20efaa8 Michael Hanselmann
  _EXPAND_NODES_SEC_BY_TAGS,
60 c20efaa8 Michael Hanselmann
  ])
61 312ac745 Iustin Pop
62 7232c04c Iustin Pop
#: default list of options for L{ListInstances}
63 48c4dfa8 Iustin Pop
_LIST_DEF_FIELDS = [
64 e69d05fd Iustin Pop
  "name", "hypervisor", "os", "pnode", "status", "oper_ram",
65 48c4dfa8 Iustin Pop
  ]
66 48c4dfa8 Iustin Pop
67 a71f835e Michael Hanselmann
_MISSING = object()
68 b8028dcf Michael Hanselmann
_ENV_OVERRIDE = compat.UniqueFrozenset(["list"])
69 ef9fa5b9 René Nussbaumer
70 b0a8e8c2 René Nussbaumer
_INST_DATA_VAL = ht.TListOf(ht.TDict)
71 b0a8e8c2 René Nussbaumer
72 ef9fa5b9 René Nussbaumer
73 479636a3 Iustin Pop
def _ExpandMultiNames(mode, names, client=None):
74 312ac745 Iustin Pop
  """Expand the given names using the passed mode.
75 312ac745 Iustin Pop

76 c20efaa8 Michael Hanselmann
  For _EXPAND_CLUSTER, all instances will be returned. For
77 c20efaa8 Michael Hanselmann
  _EXPAND_NODES_PRI/SEC, all instances having those nodes as
78 c20efaa8 Michael Hanselmann
  primary/secondary will be returned. For _EXPAND_NODES_BOTH, all
79 312ac745 Iustin Pop
  instances having those nodes as either primary or secondary will be
80 c20efaa8 Michael Hanselmann
  returned. For _EXPAND_INSTANCES, the given instances will be
81 312ac745 Iustin Pop
  returned.
82 312ac745 Iustin Pop

83 c20efaa8 Michael Hanselmann
  @param mode: one of L{_EXPAND_CLUSTER}, L{_EXPAND_NODES_BOTH},
84 c20efaa8 Michael Hanselmann
      L{_EXPAND_NODES_PRI}, L{_EXPAND_NODES_SEC} or
85 c20efaa8 Michael Hanselmann
      L{_EXPAND_INSTANCES}
86 7232c04c Iustin Pop
  @param names: a list of names; for cluster, it must be empty,
87 7232c04c Iustin Pop
      and for node and instance it must be a list of valid item
88 7232c04c Iustin Pop
      names (short names are valid as usual, e.g. node1 instead of
89 7232c04c Iustin Pop
      node1.example.com)
90 7232c04c Iustin Pop
  @rtype: list
91 7232c04c Iustin Pop
  @return: the list of names after the expansion
92 7232c04c Iustin Pop
  @raise errors.ProgrammerError: for unknown selection type
93 7232c04c Iustin Pop
  @raise errors.OpPrereqError: for invalid input parameters
94 7232c04c Iustin Pop

95 312ac745 Iustin Pop
  """
96 b459a848 Andrea Spadaccini
  # pylint: disable=W0142
97 39dfd93e René Nussbaumer
98 479636a3 Iustin Pop
  if client is None:
99 479636a3 Iustin Pop
    client = GetClient()
100 c20efaa8 Michael Hanselmann
  if mode == _EXPAND_CLUSTER:
101 312ac745 Iustin Pop
    if names:
102 debac808 Iustin Pop
      raise errors.OpPrereqError("Cluster filter mode takes no arguments",
103 debac808 Iustin Pop
                                 errors.ECODE_INVAL)
104 ec79568d Iustin Pop
    idata = client.QueryInstances([], ["name"], False)
105 312ac745 Iustin Pop
    inames = [row[0] for row in idata]
106 312ac745 Iustin Pop
107 c20efaa8 Michael Hanselmann
  elif (mode in _EXPAND_NODES_TAGS_MODES or
108 c20efaa8 Michael Hanselmann
        mode in (_EXPAND_NODES_BOTH, _EXPAND_NODES_PRI, _EXPAND_NODES_SEC)):
109 c20efaa8 Michael Hanselmann
    if mode in _EXPAND_NODES_TAGS_MODES:
110 39dfd93e René Nussbaumer
      if not names:
111 39dfd93e René Nussbaumer
        raise errors.OpPrereqError("No node tags passed", errors.ECODE_INVAL)
112 39dfd93e René Nussbaumer
      ndata = client.QueryNodes([], ["name", "pinst_list",
113 39dfd93e René Nussbaumer
                                     "sinst_list", "tags"], False)
114 39dfd93e René Nussbaumer
      ndata = [row for row in ndata if set(row[3]).intersection(names)]
115 39dfd93e René Nussbaumer
    else:
116 39dfd93e René Nussbaumer
      if not names:
117 39dfd93e René Nussbaumer
        raise errors.OpPrereqError("No node names passed", errors.ECODE_INVAL)
118 39dfd93e René Nussbaumer
      ndata = client.QueryNodes(names, ["name", "pinst_list", "sinst_list"],
119 5ae4945a Iustin Pop
                                False)
120 39dfd93e René Nussbaumer
121 312ac745 Iustin Pop
    ipri = [row[1] for row in ndata]
122 312ac745 Iustin Pop
    pri_names = list(itertools.chain(*ipri))
123 312ac745 Iustin Pop
    isec = [row[2] for row in ndata]
124 312ac745 Iustin Pop
    sec_names = list(itertools.chain(*isec))
125 c20efaa8 Michael Hanselmann
    if mode in (_EXPAND_NODES_BOTH, _EXPAND_NODES_BOTH_BY_TAGS):
126 312ac745 Iustin Pop
      inames = pri_names + sec_names
127 c20efaa8 Michael Hanselmann
    elif mode in (_EXPAND_NODES_PRI, _EXPAND_NODES_PRI_BY_TAGS):
128 312ac745 Iustin Pop
      inames = pri_names
129 c20efaa8 Michael Hanselmann
    elif mode in (_EXPAND_NODES_SEC, _EXPAND_NODES_SEC_BY_TAGS):
130 312ac745 Iustin Pop
      inames = sec_names
131 312ac745 Iustin Pop
    else:
132 312ac745 Iustin Pop
      raise errors.ProgrammerError("Unhandled shutdown type")
133 c20efaa8 Michael Hanselmann
  elif mode == _EXPAND_INSTANCES:
134 312ac745 Iustin Pop
    if not names:
135 debac808 Iustin Pop
      raise errors.OpPrereqError("No instance names passed",
136 debac808 Iustin Pop
                                 errors.ECODE_INVAL)
137 ec79568d Iustin Pop
    idata = client.QueryInstances(names, ["name"], False)
138 312ac745 Iustin Pop
    inames = [row[0] for row in idata]
139 c20efaa8 Michael Hanselmann
  elif mode == _EXPAND_INSTANCES_BY_TAGS:
140 39dfd93e René Nussbaumer
    if not names:
141 39dfd93e René Nussbaumer
      raise errors.OpPrereqError("No instance tags passed",
142 39dfd93e René Nussbaumer
                                 errors.ECODE_INVAL)
143 39dfd93e René Nussbaumer
    idata = client.QueryInstances([], ["name", "tags"], False)
144 39dfd93e René Nussbaumer
    inames = [row[0] for row in idata if set(row[1]).intersection(names)]
145 312ac745 Iustin Pop
  else:
146 debac808 Iustin Pop
    raise errors.OpPrereqError("Unknown mode '%s'" % mode, errors.ECODE_INVAL)
147 312ac745 Iustin Pop
148 312ac745 Iustin Pop
  return inames
149 a8083063 Iustin Pop
150 a8083063 Iustin Pop
151 a76f0c4a Iustin Pop
def _EnsureInstancesExist(client, names):
152 a76f0c4a Iustin Pop
  """Check for and ensure the given instance names exist.
153 a76f0c4a Iustin Pop

154 a76f0c4a Iustin Pop
  This function will raise an OpPrereqError in case they don't
155 a76f0c4a Iustin Pop
  exist. Otherwise it will exit cleanly.
156 a76f0c4a Iustin Pop

157 f2fd87d7 Iustin Pop
  @type client: L{ganeti.luxi.Client}
158 a76f0c4a Iustin Pop
  @param client: the client to use for the query
159 a76f0c4a Iustin Pop
  @type names: list
160 a76f0c4a Iustin Pop
  @param names: the list of instance names to query
161 a76f0c4a Iustin Pop
  @raise errors.OpPrereqError: in case any instance is missing
162 a76f0c4a Iustin Pop

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

176 1c5945b6 Iustin Pop
  The will return a wrapper that processes the options and arguments
177 1c5945b6 Iustin Pop
  given, and uses the passed function to build the opcode needed for
178 1c5945b6 Iustin Pop
  the specific operation. Thus all the generic loop/confirmation code
179 1c5945b6 Iustin Pop
  is abstracted into this function.
180 1c5945b6 Iustin Pop

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

210 7232c04c Iustin Pop
  @param opts: the command line options selected by the user
211 7232c04c Iustin Pop
  @type args: list
212 7232c04c Iustin Pop
  @param args: should be an empty list
213 7232c04c Iustin Pop
  @rtype: int
214 7232c04c Iustin Pop
  @return: the desired exit code
215 7232c04c Iustin Pop

216 a8083063 Iustin Pop
  """
217 a4ebd726 Michael Hanselmann
  selected_fields = ParseFields(opts.output, _LIST_DEF_FIELDS)
218 a8083063 Iustin Pop
219 b82c5ff5 Michael Hanselmann
  fmtoverride = dict.fromkeys(["tags", "disk.sizes", "nic.macs", "nic.ips",
220 b82c5ff5 Michael Hanselmann
                               "nic.modes", "nic.links", "nic.bridges",
221 d4117a72 Apollon Oikonomopoulos
                               "nic.networks",
222 fab9573b Michael Hanselmann
                               "snodes", "snodes.group", "snodes.group.uuid"],
223 b82c5ff5 Michael Hanselmann
                              (lambda value: ",".join(str(item)
224 b82c5ff5 Michael Hanselmann
                                                      for item in value),
225 b82c5ff5 Michael Hanselmann
                               False))
226 a8083063 Iustin Pop
227 b82c5ff5 Michael Hanselmann
  return GenericList(constants.QR_INSTANCE, selected_fields, args, opts.units,
228 b82c5ff5 Michael Hanselmann
                     opts.separator, not opts.no_headers,
229 87e87959 Michael Hanselmann
                     format_override=fmtoverride, verbose=opts.verbose,
230 87e87959 Michael Hanselmann
                     force_filter=opts.force_filter)
231 b82c5ff5 Michael Hanselmann
232 b82c5ff5 Michael Hanselmann
233 b82c5ff5 Michael Hanselmann
def ListInstanceFields(opts, args):
234 b82c5ff5 Michael Hanselmann
  """List instance fields.
235 b82c5ff5 Michael Hanselmann

236 b82c5ff5 Michael Hanselmann
  @param opts: the command line options selected by the user
237 b82c5ff5 Michael Hanselmann
  @type args: list
238 b82c5ff5 Michael Hanselmann
  @param args: fields to list, or empty for all
239 b82c5ff5 Michael Hanselmann
  @rtype: int
240 b82c5ff5 Michael Hanselmann
  @return: the desired exit code
241 b82c5ff5 Michael Hanselmann

242 b82c5ff5 Michael Hanselmann
  """
243 b82c5ff5 Michael Hanselmann
  return GenericListFields(constants.QR_INSTANCE, args, opts.separator,
244 b82c5ff5 Michael Hanselmann
                           not opts.no_headers)
245 a8083063 Iustin Pop
246 a8083063 Iustin Pop
247 a8083063 Iustin Pop
def AddInstance(opts, args):
248 a8083063 Iustin Pop
  """Add an instance to the cluster.
249 a8083063 Iustin Pop

250 d77490c5 Iustin Pop
  This is just a wrapper over GenericInstanceCreate.
251 a8083063 Iustin Pop

252 a8083063 Iustin Pop
  """
253 d77490c5 Iustin Pop
  return GenericInstanceCreate(constants.INSTANCE_CREATE, opts, args)
254 a8083063 Iustin Pop
255 a8083063 Iustin Pop
256 0d0e9090 René Nussbaumer
def BatchCreate(opts, args):
257 7232c04c Iustin Pop
  """Create instances using a definition file.
258 7232c04c Iustin Pop

259 b0a8e8c2 René Nussbaumer
  This function reads a json file with L{opcodes.OpInstanceCreate}
260 b0a8e8c2 René Nussbaumer
  serialisations.
261 7232c04c Iustin Pop

262 7232c04c Iustin Pop
  @param opts: the command line options selected by the user
263 7232c04c Iustin Pop
  @type args: list
264 7232c04c Iustin Pop
  @param args: should contain one element, the json filename
265 7232c04c Iustin Pop
  @rtype: int
266 7232c04c Iustin Pop
  @return: the desired exit code
267 0d0e9090 René Nussbaumer

268 0d0e9090 René Nussbaumer
  """
269 b0a8e8c2 René Nussbaumer
  (json_filename,) = args
270 b0a8e8c2 René Nussbaumer
  cl = GetClient()
271 0d0e9090 René Nussbaumer
272 0d0e9090 René Nussbaumer
  try:
273 13998ef2 Michael Hanselmann
    instance_data = simplejson.loads(utils.ReadFile(json_filename))
274 b459a848 Andrea Spadaccini
  except Exception, err: # pylint: disable=W0703
275 4082e6f9 Iustin Pop
    ToStderr("Can't parse the instance definition file: %s" % str(err))
276 4082e6f9 Iustin Pop
    return 1
277 0d0e9090 René Nussbaumer
278 b0a8e8c2 René Nussbaumer
  if not _INST_DATA_VAL(instance_data):
279 b0a8e8c2 René Nussbaumer
    ToStderr("The instance definition file is not %s" % _INST_DATA_VAL)
280 fe7c59d5 Guido Trotter
    return 1
281 fe7c59d5 Guido Trotter
282 b0a8e8c2 René Nussbaumer
  instances = []
283 b0a8e8c2 René Nussbaumer
  possible_params = set(opcodes.OpInstanceCreate.GetAllSlots())
284 b0a8e8c2 René Nussbaumer
  for (idx, inst) in enumerate(instance_data):
285 b0a8e8c2 René Nussbaumer
    unknown = set(inst.keys()) - possible_params
286 d4dd4b74 Iustin Pop
287 b0a8e8c2 René Nussbaumer
    if unknown:
288 b0a8e8c2 René Nussbaumer
      # TODO: Suggest closest match for more user friendly experience
289 3779121c René Nussbaumer
      raise errors.OpPrereqError("Unknown fields in definition %s: %s" %
290 3779121c René Nussbaumer
                                 (idx, utils.CommaJoin(unknown)),
291 3779121c René Nussbaumer
                                 errors.ECODE_INVAL)
292 0d0e9090 René Nussbaumer
293 3779121c René Nussbaumer
    op = opcodes.OpInstanceCreate(**inst) # pylint: disable=W0142
294 b0a8e8c2 René Nussbaumer
    op.Validate(False)
295 b0a8e8c2 René Nussbaumer
    instances.append(op)
296 0d0e9090 René Nussbaumer
297 b0a8e8c2 René Nussbaumer
  op = opcodes.OpInstanceMultiAlloc(iallocator=opts.iallocator,
298 b0a8e8c2 René Nussbaumer
                                    instances=instances)
299 b0a8e8c2 René Nussbaumer
  result = SubmitOrSend(op, opts, cl=cl)
300 0d0e9090 René Nussbaumer
301 b0a8e8c2 René Nussbaumer
  # Keep track of submitted jobs
302 b0a8e8c2 René Nussbaumer
  jex = JobExecutor(cl=cl, opts=opts)
303 b0a8e8c2 René Nussbaumer
304 b0a8e8c2 René Nussbaumer
  for (status, job_id) in result[constants.JOB_IDS_KEY]:
305 b0a8e8c2 René Nussbaumer
    jex.AddJobId(None, status, job_id)
306 b0a8e8c2 René Nussbaumer
307 b0a8e8c2 René Nussbaumer
  results = jex.GetResults()
308 b0a8e8c2 René Nussbaumer
  bad_cnt = len([row for row in results if not row[0]])
309 b0a8e8c2 René Nussbaumer
  if bad_cnt == 0:
310 b0a8e8c2 René Nussbaumer
    ToStdout("All instances created successfully.")
311 b0a8e8c2 René Nussbaumer
    rcode = constants.EXIT_SUCCESS
312 b0a8e8c2 René Nussbaumer
  else:
313 b0a8e8c2 René Nussbaumer
    ToStdout("There were %s errors during the creation.", bad_cnt)
314 b0a8e8c2 René Nussbaumer
    rcode = constants.EXIT_FAILURE
315 b0a8e8c2 René Nussbaumer
316 b0a8e8c2 René Nussbaumer
  return rcode
317 0d0e9090 René Nussbaumer
318 0d0e9090 René Nussbaumer
319 fe7b0351 Michael Hanselmann
def ReinstallInstance(opts, args):
320 fe7b0351 Michael Hanselmann
  """Reinstall an instance.
321 fe7b0351 Michael Hanselmann

322 7232c04c Iustin Pop
  @param opts: the command line options selected by the user
323 7232c04c Iustin Pop
  @type args: list
324 7232c04c Iustin Pop
  @param args: should contain only one element, the name of the
325 7232c04c Iustin Pop
      instance to be reinstalled
326 7232c04c Iustin Pop
  @rtype: int
327 7232c04c Iustin Pop
  @return: the desired exit code
328 fe7b0351 Michael Hanselmann

329 fe7b0351 Michael Hanselmann
  """
330 55efe6da Iustin Pop
  # first, compute the desired name list
331 55efe6da Iustin Pop
  if opts.multi_mode is None:
332 c20efaa8 Michael Hanselmann
    opts.multi_mode = _EXPAND_INSTANCES
333 55efe6da Iustin Pop
334 55efe6da Iustin Pop
  inames = _ExpandMultiNames(opts.multi_mode, args)
335 55efe6da Iustin Pop
  if not inames:
336 debac808 Iustin Pop
    raise errors.OpPrereqError("Selection filter does not match any instances",
337 debac808 Iustin Pop
                               errors.ECODE_INVAL)
338 fe7b0351 Michael Hanselmann
339 55efe6da Iustin Pop
  # second, if requested, ask for an OS
340 20e23543 Alexander Schreiber
  if opts.select_os is True:
341 da2d02e7 Iustin Pop
    op = opcodes.OpOsDiagnose(output_fields=["name", "variants"], names=[])
342 400ca2f7 Iustin Pop
    result = SubmitOpCode(op, opts=opts)
343 20e23543 Alexander Schreiber
344 20e23543 Alexander Schreiber
    if not result:
345 3a24c527 Iustin Pop
      ToStdout("Can't get the OS list")
346 20e23543 Alexander Schreiber
      return 1
347 20e23543 Alexander Schreiber
348 3a24c527 Iustin Pop
    ToStdout("Available OS templates:")
349 20e23543 Alexander Schreiber
    number = 0
350 20e23543 Alexander Schreiber
    choices = []
351 d22dfef7 Iustin Pop
    for (name, variants) in result:
352 d22dfef7 Iustin Pop
      for entry in CalculateOSNames(name, variants):
353 d22dfef7 Iustin Pop
        ToStdout("%3s: %s", number, entry)
354 d22dfef7 Iustin Pop
        choices.append(("%s" % number, entry, entry))
355 d22dfef7 Iustin Pop
        number += 1
356 20e23543 Alexander Schreiber
357 d0c8c01d Iustin Pop
    choices.append(("x", "exit", "Exit gnt-instance reinstall"))
358 949bdabe Iustin Pop
    selected = AskUser("Enter OS template number (or x to abort):",
359 20e23543 Alexander Schreiber
                       choices)
360 20e23543 Alexander Schreiber
361 d0c8c01d Iustin Pop
    if selected == "exit":
362 55efe6da Iustin Pop
      ToStderr("User aborted reinstall, exiting")
363 20e23543 Alexander Schreiber
      return 1
364 20e23543 Alexander Schreiber
365 2f79bd34 Iustin Pop
    os_name = selected
366 f86426f5 Iustin Pop
    os_msg = "change the OS to '%s'" % selected
367 20e23543 Alexander Schreiber
  else:
368 2f79bd34 Iustin Pop
    os_name = opts.os
369 f86426f5 Iustin Pop
    if opts.os is not None:
370 f86426f5 Iustin Pop
      os_msg = "change the OS to '%s'" % os_name
371 f86426f5 Iustin Pop
    else:
372 f86426f5 Iustin Pop
      os_msg = "keep the same OS"
373 20e23543 Alexander Schreiber
374 297ddce9 Iustin Pop
  # third, get confirmation: multi-reinstall requires --force-multi,
375 297ddce9 Iustin Pop
  # single-reinstall either --force or --force-multi (--force-multi is
376 297ddce9 Iustin Pop
  # a stronger --force)
377 c20efaa8 Michael Hanselmann
  multi_on = opts.multi_mode != _EXPAND_INSTANCES or len(inames) > 1
378 55efe6da Iustin Pop
  if multi_on:
379 f86426f5 Iustin Pop
    warn_msg = ("Note: this will remove *all* data for the"
380 f86426f5 Iustin Pop
                " below instances! It will %s.\n" % os_msg)
381 297ddce9 Iustin Pop
    if not (opts.force_multi or
382 25bd815c René Nussbaumer
            ConfirmOperation(inames, "instances", "reinstall", extra=warn_msg)):
383 fe7b0351 Michael Hanselmann
      return 1
384 55efe6da Iustin Pop
  else:
385 297ddce9 Iustin Pop
    if not (opts.force or opts.force_multi):
386 f86426f5 Iustin Pop
      usertext = ("This will reinstall the instance '%s' (and %s) which"
387 f86426f5 Iustin Pop
                  " removes all data. Continue?") % (inames[0], os_msg)
388 55efe6da Iustin Pop
      if not AskUser(usertext):
389 55efe6da Iustin Pop
        return 1
390 55efe6da Iustin Pop
391 cb573a31 Iustin Pop
  jex = JobExecutor(verbose=multi_on, opts=opts)
392 55efe6da Iustin Pop
  for instance_name in inames:
393 5073fd8f Iustin Pop
    op = opcodes.OpInstanceReinstall(instance_name=instance_name,
394 06073e85 Guido Trotter
                                     os_type=os_name,
395 8d8c4eff Michael Hanselmann
                                     force_variant=opts.force_variant,
396 8d8c4eff Michael Hanselmann
                                     osparams=opts.osparams)
397 55efe6da Iustin Pop
    jex.QueueJob(instance_name, op)
398 fe7b0351 Michael Hanselmann
399 64be07b1 Michael Hanselmann
  results = jex.WaitOrShow(not opts.submit_only)
400 64be07b1 Michael Hanselmann
401 64be07b1 Michael Hanselmann
  if compat.all(map(compat.fst, results)):
402 64be07b1 Michael Hanselmann
    return constants.EXIT_SUCCESS
403 64be07b1 Michael Hanselmann
  else:
404 64be07b1 Michael Hanselmann
    return constants.EXIT_FAILURE
405 fe7b0351 Michael Hanselmann
406 fe7b0351 Michael Hanselmann
407 a8083063 Iustin Pop
def RemoveInstance(opts, args):
408 a8083063 Iustin Pop
  """Remove an instance.
409 a8083063 Iustin Pop

410 7232c04c Iustin Pop
  @param opts: the command line options selected by the user
411 7232c04c Iustin Pop
  @type args: list
412 7232c04c Iustin Pop
  @param args: should contain only one element, the name of
413 7232c04c Iustin Pop
      the instance to be removed
414 7232c04c Iustin Pop
  @rtype: int
415 7232c04c Iustin Pop
  @return: the desired exit code
416 a8083063 Iustin Pop

417 a8083063 Iustin Pop
  """
418 a8083063 Iustin Pop
  instance_name = args[0]
419 a8083063 Iustin Pop
  force = opts.force
420 a76f0c4a Iustin Pop
  cl = GetClient()
421 a8083063 Iustin Pop
422 a8083063 Iustin Pop
  if not force:
423 a76f0c4a Iustin Pop
    _EnsureInstancesExist(cl, [instance_name])
424 a76f0c4a Iustin Pop
425 a8083063 Iustin Pop
    usertext = ("This will remove the volumes of the instance %s"
426 a8083063 Iustin Pop
                " (including mirrors), thus removing all the data"
427 a8083063 Iustin Pop
                " of the instance. Continue?") % instance_name
428 47988778 Iustin Pop
    if not AskUser(usertext):
429 a8083063 Iustin Pop
      return 1
430 a8083063 Iustin Pop
431 3cd2d4b1 Iustin Pop
  op = opcodes.OpInstanceRemove(instance_name=instance_name,
432 17c3f802 Guido Trotter
                                ignore_failures=opts.ignore_failures,
433 4d98c565 Guido Trotter
                                shutdown_timeout=opts.shutdown_timeout)
434 a76f0c4a Iustin Pop
  SubmitOrSend(op, opts, cl=cl)
435 a8083063 Iustin Pop
  return 0
436 a8083063 Iustin Pop
437 a8083063 Iustin Pop
438 decd5f45 Iustin Pop
def RenameInstance(opts, args):
439 4ab0b9e3 Guido Trotter
  """Rename an instance.
440 decd5f45 Iustin Pop

441 7232c04c Iustin Pop
  @param opts: the command line options selected by the user
442 7232c04c Iustin Pop
  @type args: list
443 7232c04c Iustin Pop
  @param args: should contain two elements, the old and the
444 7232c04c Iustin Pop
      new instance names
445 7232c04c Iustin Pop
  @rtype: int
446 7232c04c Iustin Pop
  @return: the desired exit code
447 decd5f45 Iustin Pop

448 decd5f45 Iustin Pop
  """
449 90ed09b0 René Nussbaumer
  if not opts.name_check:
450 1b6dddc8 René Nussbaumer
    if not AskUser("As you disabled the check of the DNS entry, please verify"
451 1b6dddc8 René Nussbaumer
                   " that '%s' is a FQDN. Continue?" % args[1]):
452 1b6dddc8 René Nussbaumer
      return 1
453 1b6dddc8 René Nussbaumer
454 5659e2e2 Iustin Pop
  op = opcodes.OpInstanceRename(instance_name=args[0],
455 decd5f45 Iustin Pop
                                new_name=args[1],
456 3fe11ba3 Manuel Franceschini
                                ip_check=opts.ip_check,
457 3fe11ba3 Manuel Franceschini
                                name_check=opts.name_check)
458 6a016df9 Michael Hanselmann
  result = SubmitOrSend(op, opts)
459 6a016df9 Michael Hanselmann
460 48418fea Iustin Pop
  if result:
461 48418fea Iustin Pop
    ToStdout("Instance '%s' renamed to '%s'", args[0], result)
462 6a016df9 Michael Hanselmann
463 decd5f45 Iustin Pop
  return 0
464 decd5f45 Iustin Pop
465 decd5f45 Iustin Pop
466 a8083063 Iustin Pop
def ActivateDisks(opts, args):
467 a8083063 Iustin Pop
  """Activate an instance's disks.
468 a8083063 Iustin Pop

469 a8083063 Iustin Pop
  This serves two purposes:
470 7232c04c Iustin Pop
    - it allows (as long as the instance is not running)
471 7232c04c Iustin Pop
      mounting the disks and modifying them from the node
472 a8083063 Iustin Pop
    - it repairs inactive secondary drbds
473 a8083063 Iustin Pop

474 7232c04c Iustin Pop
  @param opts: the command line options selected by the user
475 7232c04c Iustin Pop
  @type args: list
476 7232c04c Iustin Pop
  @param args: should contain only one element, the instance name
477 7232c04c Iustin Pop
  @rtype: int
478 7232c04c Iustin Pop
  @return: the desired exit code
479 7232c04c Iustin Pop

480 a8083063 Iustin Pop
  """
481 a8083063 Iustin Pop
  instance_name = args[0]
482 83f5d475 Iustin Pop
  op = opcodes.OpInstanceActivateDisks(instance_name=instance_name,
483 f30d8165 Iustin Pop
                                       ignore_size=opts.ignore_size,
484 f30d8165 Iustin Pop
                                       wait_for_sync=opts.wait_for_sync)
485 6340bb0a Iustin Pop
  disks_info = SubmitOrSend(op, opts)
486 a8083063 Iustin Pop
  for host, iname, nname in disks_info:
487 3a24c527 Iustin Pop
    ToStdout("%s:%s:%s", host, iname, nname)
488 a8083063 Iustin Pop
  return 0
489 a8083063 Iustin Pop
490 a8083063 Iustin Pop
491 a8083063 Iustin Pop
def DeactivateDisks(opts, args):
492 bd315bfa Iustin Pop
  """Deactivate an instance's disks.
493 a8083063 Iustin Pop

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

497 7232c04c Iustin Pop
  @param opts: the command line options selected by the user
498 7232c04c Iustin Pop
  @type args: list
499 7232c04c Iustin Pop
  @param args: should contain only one element, the instance name
500 7232c04c Iustin Pop
  @rtype: int
501 7232c04c Iustin Pop
  @return: the desired exit code
502 7232c04c Iustin Pop

503 a8083063 Iustin Pop
  """
504 a8083063 Iustin Pop
  instance_name = args[0]
505 c9c41373 Iustin Pop
  op = opcodes.OpInstanceDeactivateDisks(instance_name=instance_name,
506 c9c41373 Iustin Pop
                                         force=opts.force)
507 6340bb0a Iustin Pop
  SubmitOrSend(op, opts)
508 a8083063 Iustin Pop
  return 0
509 a8083063 Iustin Pop
510 a8083063 Iustin Pop
511 bd315bfa Iustin Pop
def RecreateDisks(opts, args):
512 bd315bfa Iustin Pop
  """Recreate an instance's disks.
513 bd315bfa Iustin Pop

514 bd315bfa Iustin Pop
  @param opts: the command line options selected by the user
515 bd315bfa Iustin Pop
  @type args: list
516 bd315bfa Iustin Pop
  @param args: should contain only one element, the instance name
517 bd315bfa Iustin Pop
  @rtype: int
518 bd315bfa Iustin Pop
  @return: the desired exit code
519 bd315bfa Iustin Pop

520 bd315bfa Iustin Pop
  """
521 bd315bfa Iustin Pop
  instance_name = args[0]
522 735e1318 Michael Hanselmann
523 735e1318 Michael Hanselmann
  disks = []
524 735e1318 Michael Hanselmann
525 bd315bfa Iustin Pop
  if opts.disks:
526 735e1318 Michael Hanselmann
    for didx, ddict in opts.disks:
527 735e1318 Michael Hanselmann
      didx = int(didx)
528 735e1318 Michael Hanselmann
529 735e1318 Michael Hanselmann
      if not ht.TDict(ddict):
530 735e1318 Michael Hanselmann
        msg = "Invalid disk/%d value: expected dict, got %s" % (didx, ddict)
531 2cfbc784 Iustin Pop
        raise errors.OpPrereqError(msg, errors.ECODE_INVAL)
532 735e1318 Michael Hanselmann
533 735e1318 Michael Hanselmann
      if constants.IDISK_SIZE in ddict:
534 735e1318 Michael Hanselmann
        try:
535 735e1318 Michael Hanselmann
          ddict[constants.IDISK_SIZE] = \
536 735e1318 Michael Hanselmann
            utils.ParseUnit(ddict[constants.IDISK_SIZE])
537 735e1318 Michael Hanselmann
        except ValueError, err:
538 735e1318 Michael Hanselmann
          raise errors.OpPrereqError("Invalid disk size for disk %d: %s" %
539 2cfbc784 Iustin Pop
                                     (didx, err), errors.ECODE_INVAL)
540 735e1318 Michael Hanselmann
541 735e1318 Michael Hanselmann
      disks.append((didx, ddict))
542 735e1318 Michael Hanselmann
543 735e1318 Michael Hanselmann
    # TODO: Verify modifyable parameters (already done in
544 735e1318 Michael Hanselmann
    # LUInstanceRecreateDisks, but it'd be nice to have in the client)
545 bd315bfa Iustin Pop
546 c8a96ae7 Iustin Pop
  if opts.node:
547 38db4e7c Adam Ingrassia
    if opts.iallocator:
548 38db4e7c Adam Ingrassia
      msg = "At most one of either --nodes or --iallocator can be passed"
549 38db4e7c Adam Ingrassia
      raise errors.OpPrereqError(msg, errors.ECODE_INVAL)
550 c8a96ae7 Iustin Pop
    pnode, snode = SplitNodeOption(opts.node)
551 c8a96ae7 Iustin Pop
    nodes = [pnode]
552 c8a96ae7 Iustin Pop
    if snode is not None:
553 c8a96ae7 Iustin Pop
      nodes.append(snode)
554 c8a96ae7 Iustin Pop
  else:
555 c8a96ae7 Iustin Pop
    nodes = []
556 c8a96ae7 Iustin Pop
557 6b273e78 Iustin Pop
  op = opcodes.OpInstanceRecreateDisks(instance_name=instance_name,
558 38db4e7c Adam Ingrassia
                                       disks=disks, nodes=nodes,
559 38db4e7c Adam Ingrassia
                                       iallocator=opts.iallocator)
560 bd315bfa Iustin Pop
  SubmitOrSend(op, opts)
561 735e1318 Michael Hanselmann
562 bd315bfa Iustin Pop
  return 0
563 bd315bfa Iustin Pop
564 bd315bfa Iustin Pop
565 c6e911bc Iustin Pop
def GrowDisk(opts, args):
566 7232c04c Iustin Pop
  """Grow an instance's disks.
567 c6e911bc Iustin Pop

568 7232c04c Iustin Pop
  @param opts: the command line options selected by the user
569 7232c04c Iustin Pop
  @type args: list
570 30a83755 Guido Trotter
  @param args: should contain three elements, the target instance name,
571 30a83755 Guido Trotter
      the target disk id, and the target growth
572 7232c04c Iustin Pop
  @rtype: int
573 7232c04c Iustin Pop
  @return: the desired exit code
574 c6e911bc Iustin Pop

575 c6e911bc Iustin Pop
  """
576 c6e911bc Iustin Pop
  instance = args[0]
577 c6e911bc Iustin Pop
  disk = args[1]
578 ad24e046 Iustin Pop
  try:
579 ad24e046 Iustin Pop
    disk = int(disk)
580 691744c4 Iustin Pop
  except (TypeError, ValueError), err:
581 debac808 Iustin Pop
    raise errors.OpPrereqError("Invalid disk index: %s" % str(err),
582 debac808 Iustin Pop
                               errors.ECODE_INVAL)
583 c8bde61e Iustin Pop
  try:
584 c8bde61e Iustin Pop
    amount = utils.ParseUnit(args[2])
585 c8bde61e Iustin Pop
  except errors.UnitParseError:
586 c8bde61e Iustin Pop
    raise errors.OpPrereqError("Can't parse the given amount '%s'" % args[2],
587 c8bde61e Iustin Pop
                               errors.ECODE_INVAL)
588 60472d29 Iustin Pop
  op = opcodes.OpInstanceGrowDisk(instance_name=instance,
589 60472d29 Iustin Pop
                                  disk=disk, amount=amount,
590 ef8270dc Iustin Pop
                                  wait_for_sync=opts.wait_for_sync,
591 ef8270dc Iustin Pop
                                  absolute=opts.absolute)
592 6340bb0a Iustin Pop
  SubmitOrSend(op, opts)
593 c6e911bc Iustin Pop
  return 0
594 c6e911bc Iustin Pop
595 c6e911bc Iustin Pop
596 1c5945b6 Iustin Pop
def _StartupInstance(name, opts):
597 7232c04c Iustin Pop
  """Startup instances.
598 a8083063 Iustin Pop

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

602 1c5945b6 Iustin Pop
  @param name: the name of the instance to act on
603 7232c04c Iustin Pop
  @param opts: the command line options selected by the user
604 1c5945b6 Iustin Pop
  @return: the opcode needed for the operation
605 a8083063 Iustin Pop

606 a8083063 Iustin Pop
  """
607 c873d91c Iustin Pop
  op = opcodes.OpInstanceStartup(instance_name=name,
608 b44bd844 Michael Hanselmann
                                 force=opts.force,
609 885a0fc4 Iustin Pop
                                 ignore_offline_nodes=opts.ignore_offline,
610 323f9095 Stephen Shirley
                                 no_remember=opts.no_remember,
611 323f9095 Stephen Shirley
                                 startup_paused=opts.startup_paused)
612 1c5945b6 Iustin Pop
  # do not add these parameters to the opcode unless they're defined
613 1c5945b6 Iustin Pop
  if opts.hvparams:
614 1c5945b6 Iustin Pop
    op.hvparams = opts.hvparams
615 1c5945b6 Iustin Pop
  if opts.beparams:
616 1c5945b6 Iustin Pop
    op.beparams = opts.beparams
617 1c5945b6 Iustin Pop
  return op
618 a8083063 Iustin Pop
619 7c0d6283 Michael Hanselmann
620 1c5945b6 Iustin Pop
def _RebootInstance(name, opts):
621 7232c04c Iustin Pop
  """Reboot instance(s).
622 7232c04c Iustin Pop

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

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

630 579d4337 Alexander Schreiber
  """
631 90ab1a95 Iustin Pop
  return opcodes.OpInstanceReboot(instance_name=name,
632 579d4337 Alexander Schreiber
                                  reboot_type=opts.reboot_type,
633 17c3f802 Guido Trotter
                                  ignore_secondaries=opts.ignore_secondaries,
634 a59d5fa1 Michele Tartara
                                  shutdown_timeout=opts.shutdown_timeout,
635 a59d5fa1 Michele Tartara
                                  reason=(constants.INSTANCE_REASON_SOURCE_CLI,
636 a59d5fa1 Michele Tartara
                                          opts.reason))
637 a8083063 Iustin Pop
638 7c0d6283 Michael Hanselmann
639 1c5945b6 Iustin Pop
def _ShutdownInstance(name, opts):
640 a8083063 Iustin Pop
  """Shutdown an instance.
641 a8083063 Iustin Pop

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

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

649 a8083063 Iustin Pop
  """
650 ee3e37a7 Iustin Pop
  return opcodes.OpInstanceShutdown(instance_name=name,
651 0d57ce24 Guido Trotter
                                    force=opts.force,
652 b44bd844 Michael Hanselmann
                                    timeout=opts.timeout,
653 885a0fc4 Iustin Pop
                                    ignore_offline_nodes=opts.ignore_offline,
654 885a0fc4 Iustin Pop
                                    no_remember=opts.no_remember)
655 a8083063 Iustin Pop
656 a8083063 Iustin Pop
657 a8083063 Iustin Pop
def ReplaceDisks(opts, args):
658 a8083063 Iustin Pop
  """Replace the disks of an instance
659 a8083063 Iustin Pop

660 7232c04c Iustin Pop
  @param opts: the command line options selected by the user
661 7232c04c Iustin Pop
  @type args: list
662 7232c04c Iustin Pop
  @param args: should contain only one element, the instance name
663 7232c04c Iustin Pop
  @rtype: int
664 7232c04c Iustin Pop
  @return: the desired exit code
665 a8083063 Iustin Pop

666 a8083063 Iustin Pop
  """
667 a14db5ff Iustin Pop
  new_2ndary = opts.dst_node
668 b6e82a65 Iustin Pop
  iallocator = opts.iallocator
669 a9e0c397 Iustin Pop
  if opts.disks is None:
670 54155f52 Iustin Pop
    disks = []
671 a9e0c397 Iustin Pop
  else:
672 54155f52 Iustin Pop
    try:
673 54155f52 Iustin Pop
      disks = [int(i) for i in opts.disks.split(",")]
674 691744c4 Iustin Pop
    except (TypeError, ValueError), err:
675 debac808 Iustin Pop
      raise errors.OpPrereqError("Invalid disk index passed: %s" % str(err),
676 debac808 Iustin Pop
                                 errors.ECODE_INVAL)
677 05d47e33 Michael Hanselmann
  cnt = [opts.on_primary, opts.on_secondary, opts.auto,
678 7e9366f7 Iustin Pop
         new_2ndary is not None, iallocator is not None].count(True)
679 7e9366f7 Iustin Pop
  if cnt != 1:
680 d8d838cb Michael Hanselmann
    raise errors.OpPrereqError("One and only one of the -p, -s, -a, -n and -I"
681 debac808 Iustin Pop
                               " options must be passed", errors.ECODE_INVAL)
682 7e9366f7 Iustin Pop
  elif opts.on_primary:
683 a9e0c397 Iustin Pop
    mode = constants.REPLACE_DISK_PRI
684 7e9366f7 Iustin Pop
  elif opts.on_secondary:
685 a9e0c397 Iustin Pop
    mode = constants.REPLACE_DISK_SEC
686 05d47e33 Michael Hanselmann
  elif opts.auto:
687 05d47e33 Michael Hanselmann
    mode = constants.REPLACE_DISK_AUTO
688 05d47e33 Michael Hanselmann
    if disks:
689 05d47e33 Michael Hanselmann
      raise errors.OpPrereqError("Cannot specify disks when using automatic"
690 debac808 Iustin Pop
                                 " mode", errors.ECODE_INVAL)
691 7e9366f7 Iustin Pop
  elif new_2ndary is not None or iallocator is not None:
692 7e9366f7 Iustin Pop
    # replace secondary
693 7e9366f7 Iustin Pop
    mode = constants.REPLACE_DISK_CHG
694 a9e0c397 Iustin Pop
695 668f755d Iustin Pop
  op = opcodes.OpInstanceReplaceDisks(instance_name=args[0], disks=disks,
696 668f755d Iustin Pop
                                      remote_node=new_2ndary, mode=mode,
697 668f755d Iustin Pop
                                      iallocator=iallocator,
698 893e8f49 René Nussbaumer
                                      early_release=opts.early_release,
699 893e8f49 René Nussbaumer
                                      ignore_ipolicy=opts.ignore_ipolicy)
700 6340bb0a Iustin Pop
  SubmitOrSend(op, opts)
701 a8083063 Iustin Pop
  return 0
702 a8083063 Iustin Pop
703 a8083063 Iustin Pop
704 a8083063 Iustin Pop
def FailoverInstance(opts, args):
705 a8083063 Iustin Pop
  """Failover an instance.
706 a8083063 Iustin Pop

707 a8083063 Iustin Pop
  The failover is done by shutting it down on its present node and
708 a8083063 Iustin Pop
  starting it on the secondary.
709 a8083063 Iustin Pop

710 7232c04c Iustin Pop
  @param opts: the command line options selected by the user
711 7232c04c Iustin Pop
  @type args: list
712 7232c04c Iustin Pop
  @param args: should contain only one element, the instance name
713 7232c04c Iustin Pop
  @rtype: int
714 7232c04c Iustin Pop
  @return: the desired exit code
715 a8083063 Iustin Pop

716 a8083063 Iustin Pop
  """
717 a76f0c4a Iustin Pop
  cl = GetClient()
718 80de0e3f Iustin Pop
  instance_name = args[0]
719 80de0e3f Iustin Pop
  force = opts.force
720 1b7761fd Apollon Oikonomopoulos
  iallocator = opts.iallocator
721 1b7761fd Apollon Oikonomopoulos
  target_node = opts.dst_node
722 1b7761fd Apollon Oikonomopoulos
723 1b7761fd Apollon Oikonomopoulos
  if iallocator and target_node:
724 1b7761fd Apollon Oikonomopoulos
    raise errors.OpPrereqError("Specify either an iallocator (-I), or a target"
725 1b7761fd Apollon Oikonomopoulos
                               " node (-n) but not both", errors.ECODE_INVAL)
726 a8083063 Iustin Pop
727 80de0e3f Iustin Pop
  if not force:
728 a76f0c4a Iustin Pop
    _EnsureInstancesExist(cl, [instance_name])
729 a76f0c4a Iustin Pop
730 80de0e3f Iustin Pop
    usertext = ("Failover will happen to image %s."
731 80de0e3f Iustin Pop
                " This requires a shutdown of the instance. Continue?" %
732 80de0e3f Iustin Pop
                (instance_name,))
733 80de0e3f Iustin Pop
    if not AskUser(usertext):
734 80de0e3f Iustin Pop
      return 1
735 a8083063 Iustin Pop
736 019dbee1 Iustin Pop
  op = opcodes.OpInstanceFailover(instance_name=instance_name,
737 17c3f802 Guido Trotter
                                  ignore_consistency=opts.ignore_consistency,
738 1b7761fd Apollon Oikonomopoulos
                                  shutdown_timeout=opts.shutdown_timeout,
739 1b7761fd Apollon Oikonomopoulos
                                  iallocator=iallocator,
740 b6aaf437 René Nussbaumer
                                  target_node=target_node,
741 b6aaf437 René Nussbaumer
                                  ignore_ipolicy=opts.ignore_ipolicy)
742 a76f0c4a Iustin Pop
  SubmitOrSend(op, opts, cl=cl)
743 80de0e3f Iustin Pop
  return 0
744 a8083063 Iustin Pop
745 a8083063 Iustin Pop
746 53c776b5 Iustin Pop
def MigrateInstance(opts, args):
747 53c776b5 Iustin Pop
  """Migrate an instance.
748 53c776b5 Iustin Pop

749 53c776b5 Iustin Pop
  The migrate is done without shutdown.
750 53c776b5 Iustin Pop

751 2f907a8c Iustin Pop
  @param opts: the command line options selected by the user
752 2f907a8c Iustin Pop
  @type args: list
753 2f907a8c Iustin Pop
  @param args: should contain only one element, the instance name
754 2f907a8c Iustin Pop
  @rtype: int
755 2f907a8c Iustin Pop
  @return: the desired exit code
756 53c776b5 Iustin Pop

757 53c776b5 Iustin Pop
  """
758 a76f0c4a Iustin Pop
  cl = GetClient()
759 53c776b5 Iustin Pop
  instance_name = args[0]
760 53c776b5 Iustin Pop
  force = opts.force
761 1b7761fd Apollon Oikonomopoulos
  iallocator = opts.iallocator
762 1b7761fd Apollon Oikonomopoulos
  target_node = opts.dst_node
763 1b7761fd Apollon Oikonomopoulos
764 1b7761fd Apollon Oikonomopoulos
  if iallocator and target_node:
765 1b7761fd Apollon Oikonomopoulos
    raise errors.OpPrereqError("Specify either an iallocator (-I), or a target"
766 1b7761fd Apollon Oikonomopoulos
                               " node (-n) but not both", errors.ECODE_INVAL)
767 53c776b5 Iustin Pop
768 53c776b5 Iustin Pop
  if not force:
769 a76f0c4a Iustin Pop
    _EnsureInstancesExist(cl, [instance_name])
770 a76f0c4a Iustin Pop
771 53c776b5 Iustin Pop
    if opts.cleanup:
772 53c776b5 Iustin Pop
      usertext = ("Instance %s will be recovered from a failed migration."
773 53c776b5 Iustin Pop
                  " Note that the migration procedure (including cleanup)" %
774 53c776b5 Iustin Pop
                  (instance_name,))
775 53c776b5 Iustin Pop
    else:
776 53c776b5 Iustin Pop
      usertext = ("Instance %s will be migrated. Note that migration" %
777 53c776b5 Iustin Pop
                  (instance_name,))
778 cf29cfb6 Iustin Pop
    usertext += (" might impact the instance if anything goes wrong"
779 cf29cfb6 Iustin Pop
                 " (e.g. due to bugs in the hypervisor). Continue?")
780 53c776b5 Iustin Pop
    if not AskUser(usertext):
781 53c776b5 Iustin Pop
      return 1
782 53c776b5 Iustin Pop
783 e71b9ef4 Iustin Pop
  # this should be removed once --non-live is deprecated
784 783a6c0b Iustin Pop
  if not opts.live and opts.migration_mode is not None:
785 e71b9ef4 Iustin Pop
    raise errors.OpPrereqError("Only one of the --non-live and "
786 783a6c0b Iustin Pop
                               "--migration-mode options can be passed",
787 e71b9ef4 Iustin Pop
                               errors.ECODE_INVAL)
788 e71b9ef4 Iustin Pop
  if not opts.live: # --non-live passed
789 8c35561f Iustin Pop
    mode = constants.HT_MIGRATION_NONLIVE
790 e71b9ef4 Iustin Pop
  else:
791 8c35561f Iustin Pop
    mode = opts.migration_mode
792 e71b9ef4 Iustin Pop
793 75c866c2 Iustin Pop
  op = opcodes.OpInstanceMigrate(instance_name=instance_name, mode=mode,
794 1b7761fd Apollon Oikonomopoulos
                                 cleanup=opts.cleanup, iallocator=iallocator,
795 e9c487be René Nussbaumer
                                 target_node=target_node,
796 3ed23330 René Nussbaumer
                                 allow_failover=opts.allow_failover,
797 8c0b16f6 Guido Trotter
                                 allow_runtime_changes=opts.allow_runtime_chgs,
798 3ed23330 René Nussbaumer
                                 ignore_ipolicy=opts.ignore_ipolicy)
799 f70bb622 Michael Hanselmann
  SubmitOrSend(op, cl=cl, opts=opts)
800 53c776b5 Iustin Pop
  return 0
801 53c776b5 Iustin Pop
802 53c776b5 Iustin Pop
803 fbf5a861 Iustin Pop
def MoveInstance(opts, args):
804 fbf5a861 Iustin Pop
  """Move an instance.
805 fbf5a861 Iustin Pop

806 fbf5a861 Iustin Pop
  @param opts: the command line options selected by the user
807 fbf5a861 Iustin Pop
  @type args: list
808 fbf5a861 Iustin Pop
  @param args: should contain only one element, the instance name
809 fbf5a861 Iustin Pop
  @rtype: int
810 fbf5a861 Iustin Pop
  @return: the desired exit code
811 fbf5a861 Iustin Pop

812 fbf5a861 Iustin Pop
  """
813 fbf5a861 Iustin Pop
  cl = GetClient()
814 fbf5a861 Iustin Pop
  instance_name = args[0]
815 fbf5a861 Iustin Pop
  force = opts.force
816 fbf5a861 Iustin Pop
817 fbf5a861 Iustin Pop
  if not force:
818 fbf5a861 Iustin Pop
    usertext = ("Instance %s will be moved."
819 fbf5a861 Iustin Pop
                " This requires a shutdown of the instance. Continue?" %
820 fbf5a861 Iustin Pop
                (instance_name,))
821 fbf5a861 Iustin Pop
    if not AskUser(usertext):
822 fbf5a861 Iustin Pop
      return 1
823 fbf5a861 Iustin Pop
824 0091b480 Iustin Pop
  op = opcodes.OpInstanceMove(instance_name=instance_name,
825 17c3f802 Guido Trotter
                              target_node=opts.node,
826 bb851c63 Iustin Pop
                              shutdown_timeout=opts.shutdown_timeout,
827 92cf62e3 René Nussbaumer
                              ignore_consistency=opts.ignore_consistency,
828 92cf62e3 René Nussbaumer
                              ignore_ipolicy=opts.ignore_ipolicy)
829 fbf5a861 Iustin Pop
  SubmitOrSend(op, opts, cl=cl)
830 fbf5a861 Iustin Pop
  return 0
831 fbf5a861 Iustin Pop
832 fbf5a861 Iustin Pop
833 a8083063 Iustin Pop
def ConnectToInstanceConsole(opts, args):
834 a8083063 Iustin Pop
  """Connect to the console of an instance.
835 a8083063 Iustin Pop

836 7232c04c Iustin Pop
  @param opts: the command line options selected by the user
837 7232c04c Iustin Pop
  @type args: list
838 7232c04c Iustin Pop
  @param args: should contain only one element, the instance name
839 7232c04c Iustin Pop
  @rtype: int
840 7232c04c Iustin Pop
  @return: the desired exit code
841 a8083063 Iustin Pop

842 a8083063 Iustin Pop
  """
843 a8083063 Iustin Pop
  instance_name = args[0]
844 a8083063 Iustin Pop
845 25ce3ec4 Michael Hanselmann
  cl = GetClient()
846 25ce3ec4 Michael Hanselmann
  try:
847 25ce3ec4 Michael Hanselmann
    cluster_name = cl.QueryConfigValues(["cluster_name"])[0]
848 d6f46b6a Michael Hanselmann
    ((console_data, oper_state), ) = \
849 d6f46b6a Michael Hanselmann
      cl.QueryInstances([instance_name], ["console", "oper_state"], False)
850 25ce3ec4 Michael Hanselmann
  finally:
851 25ce3ec4 Michael Hanselmann
    # Ensure client connection is closed while external commands are run
852 25ce3ec4 Michael Hanselmann
    cl.Close()
853 25ce3ec4 Michael Hanselmann
854 25ce3ec4 Michael Hanselmann
  del cl
855 25ce3ec4 Michael Hanselmann
856 d6f46b6a Michael Hanselmann
  if not console_data:
857 d6f46b6a Michael Hanselmann
    if oper_state:
858 d6f46b6a Michael Hanselmann
      # Instance is running
859 d6f46b6a Michael Hanselmann
      raise errors.OpExecError("Console information for instance %s is"
860 d6f46b6a Michael Hanselmann
                               " unavailable" % instance_name)
861 d6f46b6a Michael Hanselmann
    else:
862 d6f46b6a Michael Hanselmann
      raise errors.OpExecError("Instance %s is not running, can't get console" %
863 d6f46b6a Michael Hanselmann
                               instance_name)
864 d6f46b6a Michael Hanselmann
865 25ce3ec4 Michael Hanselmann
  return _DoConsole(objects.InstanceConsole.FromDict(console_data),
866 25ce3ec4 Michael Hanselmann
                    opts.show_command, cluster_name)
867 25ce3ec4 Michael Hanselmann
868 25ce3ec4 Michael Hanselmann
869 25ce3ec4 Michael Hanselmann
def _DoConsole(console, show_command, cluster_name, feedback_fn=ToStdout,
870 25ce3ec4 Michael Hanselmann
               _runcmd_fn=utils.RunCmd):
871 cc0dec7b Iustin Pop
  """Acts based on the result of L{opcodes.OpInstanceConsole}.
872 25ce3ec4 Michael Hanselmann

873 25ce3ec4 Michael Hanselmann
  @type console: L{objects.InstanceConsole}
874 25ce3ec4 Michael Hanselmann
  @param console: Console object
875 25ce3ec4 Michael Hanselmann
  @type show_command: bool
876 25ce3ec4 Michael Hanselmann
  @param show_command: Whether to just display commands
877 25ce3ec4 Michael Hanselmann
  @type cluster_name: string
878 25ce3ec4 Michael Hanselmann
  @param cluster_name: Cluster name as retrieved from master daemon
879 25ce3ec4 Michael Hanselmann

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

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

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

950 19708787 Iustin Pop
  @type idx: int
951 19708787 Iustin Pop
  @param idx: the index of the current disk
952 19708787 Iustin Pop
  @type top_level: boolean
953 19708787 Iustin Pop
  @param top_level: if this a top-level disk?
954 7232c04c Iustin Pop
  @type dev: dict
955 7232c04c Iustin Pop
  @param dev: dictionary with disk information
956 e2736e40 Guido Trotter
  @type roman: boolean
957 e2736e40 Guido Trotter
  @param roman: whether to try to use roman integers
958 19708787 Iustin Pop
  @return: a list of either strings, tuples or lists
959 19708787 Iustin Pop
      (which should be formatted at a higher indent level)
960 7232c04c Iustin Pop

961 a8083063 Iustin Pop
  """
962 19708787 Iustin Pop
  def helper(dtype, status):
963 7232c04c Iustin Pop
    """Format one line for physical device status.
964 7232c04c Iustin Pop

965 7232c04c Iustin Pop
    @type dtype: str
966 7232c04c Iustin Pop
    @param dtype: a constant from the L{constants.LDS_BLOCK} set
967 7232c04c Iustin Pop
    @type status: tuple
968 7232c04c Iustin Pop
    @param status: a tuple as returned from L{backend.FindBlockDevice}
969 19708787 Iustin Pop
    @return: the string representing the status
970 7232c04c Iustin Pop

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

1061 19708787 Iustin Pop
  If the element of the list is:
1062 19708787 Iustin Pop
    - a string, it is simply formatted as is
1063 19708787 Iustin Pop
    - a tuple, it will be split into key, value and the all the
1064 19708787 Iustin Pop
      values in a list will be aligned all at the same start column
1065 19708787 Iustin Pop
    - a list, will be recursively formatted
1066 19708787 Iustin Pop

1067 19708787 Iustin Pop
  @type buf: StringIO
1068 19708787 Iustin Pop
  @param buf: the buffer into which we write the output
1069 19708787 Iustin Pop
  @param data: the list to format
1070 19708787 Iustin Pop
  @type indent_level: int
1071 19708787 Iustin Pop
  @param indent_level: the indent level to format at
1072 19708787 Iustin Pop

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

1090 7232c04c Iustin Pop
  @param opts: the command line options selected by the user
1091 7232c04c Iustin Pop
  @type args: list
1092 7232c04c Iustin Pop
  @param args: either an empty list, and then we query all
1093 7232c04c Iustin Pop
      instances, or should contain a list of instance names
1094 7232c04c Iustin Pop
  @rtype: int
1095 7232c04c Iustin Pop
  @return: the desired exit code
1096 7232c04c Iustin Pop

1097 a8083063 Iustin Pop
  """
1098 220cde0b Guido Trotter
  if not args and not opts.show_all:
1099 220cde0b Guido Trotter
    ToStderr("No instance selected."
1100 220cde0b Guido Trotter
             " Please pass in --all if you want to query all instances.\n"
1101 220cde0b Guido Trotter
             "Note that this can take a long time on a big cluster.")
1102 220cde0b Guido Trotter
    return 1
1103 220cde0b Guido Trotter
  elif args and opts.show_all:
1104 220cde0b Guido Trotter
    ToStderr("Cannot use --all if you specify instance names.")
1105 220cde0b Guido Trotter
    return 1
1106 220cde0b Guido Trotter
1107 a8083063 Iustin Pop
  retcode = 0
1108 5c097318 Iustin Pop
  op = opcodes.OpInstanceQueryData(instances=args, static=opts.static,
1109 5c097318 Iustin Pop
                                   use_locking=not opts.static)
1110 400ca2f7 Iustin Pop
  result = SubmitOpCode(op, opts=opts)
1111 a8083063 Iustin Pop
  if not result:
1112 3a24c527 Iustin Pop
    ToStdout("No instances.")
1113 a8083063 Iustin Pop
    return 1
1114 a8083063 Iustin Pop
1115 a8083063 Iustin Pop
  buf = StringIO()
1116 a8083063 Iustin Pop
  retcode = 0
1117 a8083063 Iustin Pop
  for instance_name in result:
1118 a8083063 Iustin Pop
    instance = result[instance_name]
1119 a8083063 Iustin Pop
    buf.write("Instance name: %s\n" % instance["name"])
1120 033d58b0 Iustin Pop
    buf.write("UUID: %s\n" % instance["uuid"])
1121 e2736e40 Guido Trotter
    buf.write("Serial number: %s\n" %
1122 e2736e40 Guido Trotter
              compat.TryToRoman(instance["serial_no"],
1123 e2736e40 Guido Trotter
                                convert=opts.roman_integers))
1124 90f72445 Iustin Pop
    buf.write("Creation time: %s\n" % utils.FormatTime(instance["ctime"]))
1125 90f72445 Iustin Pop
    buf.write("Modification time: %s\n" % utils.FormatTime(instance["mtime"]))
1126 57821cac Iustin Pop
    buf.write("State: configured to be %s" % instance["config_state"])
1127 f965260c Michael Hanselmann
    if instance["run_state"]:
1128 57821cac Iustin Pop
      buf.write(", actual state is %s" % instance["run_state"])
1129 57821cac Iustin Pop
    buf.write("\n")
1130 57821cac Iustin Pop
    ##buf.write("Considered for memory checks in cluster verify: %s\n" %
1131 57821cac Iustin Pop
    ##          instance["auto_balance"])
1132 a8083063 Iustin Pop
    buf.write("  Nodes:\n")
1133 a8083063 Iustin Pop
    buf.write("    - primary: %s\n" % instance["pnode"])
1134 080fbeea Michael Hanselmann
    buf.write("      group: %s (UUID %s)\n" %
1135 080fbeea Michael Hanselmann
              (instance["pnode_group_name"], instance["pnode_group_uuid"]))
1136 080fbeea Michael Hanselmann
    buf.write("    - secondaries: %s\n" %
1137 080fbeea Michael Hanselmann
              utils.CommaJoin("%s (group %s, group UUID %s)" %
1138 080fbeea Michael Hanselmann
                                (name, group_name, group_uuid)
1139 080fbeea Michael Hanselmann
                              for (name, group_name, group_uuid) in
1140 080fbeea Michael Hanselmann
                                zip(instance["snodes"],
1141 080fbeea Michael Hanselmann
                                    instance["snodes_group_names"],
1142 080fbeea Michael Hanselmann
                                    instance["snodes_group_uuids"])))
1143 a8083063 Iustin Pop
    buf.write("  Operating system: %s\n" % instance["os"])
1144 acd19189 René Nussbaumer
    FormatParameterDict(buf, instance["os_instance"], instance["os_actual"],
1145 acd19189 René Nussbaumer
                        level=2)
1146 e687ec01 Michael Hanselmann
    if "network_port" in instance:
1147 e2736e40 Guido Trotter
      buf.write("  Allocated network port: %s\n" %
1148 e2736e40 Guido Trotter
                compat.TryToRoman(instance["network_port"],
1149 e2736e40 Guido Trotter
                                  convert=opts.roman_integers))
1150 24838135 Iustin Pop
    buf.write("  Hypervisor: %s\n" % instance["hypervisor"])
1151 dfff41f8 Guido Trotter
1152 dfff41f8 Guido Trotter
    # custom VNC console information
1153 dfff41f8 Guido Trotter
    vnc_bind_address = instance["hv_actual"].get(constants.HV_VNC_BIND_ADDRESS,
1154 dfff41f8 Guido Trotter
                                                 None)
1155 dfff41f8 Guido Trotter
    if vnc_bind_address:
1156 dfff41f8 Guido Trotter
      port = instance["network_port"]
1157 dfff41f8 Guido Trotter
      display = int(port) - constants.VNC_BASE_PORT
1158 9769bb78 Manuel Franceschini
      if display > 0 and vnc_bind_address == constants.IP4_ADDRESS_ANY:
1159 dfff41f8 Guido Trotter
        vnc_console_port = "%s:%s (display %s)" % (instance["pnode"],
1160 dfff41f8 Guido Trotter
                                                   port,
1161 dfff41f8 Guido Trotter
                                                   display)
1162 8b312c1d Manuel Franceschini
      elif display > 0 and netutils.IP4Address.IsValid(vnc_bind_address):
1163 dfff41f8 Guido Trotter
        vnc_console_port = ("%s:%s (node %s) (display %s)" %
1164 dfff41f8 Guido Trotter
                             (vnc_bind_address, port,
1165 dfff41f8 Guido Trotter
                              instance["pnode"], display))
1166 a8340917 Iustin Pop
      else:
1167 dfff41f8 Guido Trotter
        # vnc bind address is a file
1168 dfff41f8 Guido Trotter
        vnc_console_port = "%s:%s" % (instance["pnode"],
1169 dfff41f8 Guido Trotter
                                      vnc_bind_address)
1170 24838135 Iustin Pop
      buf.write("    - console connection: vnc to %s\n" % vnc_console_port)
1171 24838135 Iustin Pop
1172 acd19189 René Nussbaumer
    FormatParameterDict(buf, instance["hv_instance"], instance["hv_actual"],
1173 acd19189 René Nussbaumer
                        level=2)
1174 a8083063 Iustin Pop
    buf.write("  Hardware:\n")
1175 b5ef2316 Guido Trotter
    # deprecated "memory" value, kept for one version for compatibility
1176 b5ef2316 Guido Trotter
    # TODO(ganeti 2.7) remove.
1177 83d4ba5e René Nussbaumer
    be_actual = copy.deepcopy(instance["be_actual"])
1178 83d4ba5e René Nussbaumer
    be_actual["memory"] = be_actual[constants.BE_MAXMEM]
1179 83d4ba5e René Nussbaumer
    FormatParameterDict(buf, instance["be_instance"], be_actual, level=2)
1180 83d4ba5e René Nussbaumer
    # TODO(ganeti 2.7) rework the NICs as well
1181 d2acfe27 Iustin Pop
    buf.write("    - NICs:\n")
1182 cbe4a0a5 Dimitris Aragiorgis
    for idx, (ip, mac, mode, link, network, _) in enumerate(instance["nics"]):
1183 d4117a72 Apollon Oikonomopoulos
      buf.write("      - nic/%d: MAC: %s, IP: %s,"
1184 d4117a72 Apollon Oikonomopoulos
                " mode: %s, link: %s, network: %s\n" %
1185 d4117a72 Apollon Oikonomopoulos
                (idx, mac, ip, mode, link, network))
1186 b577dac4 Michael Hanselmann
    buf.write("  Disk template: %s\n" % instance["disk_template"])
1187 19708787 Iustin Pop
    buf.write("  Disks:\n")
1188 a8083063 Iustin Pop
1189 19708787 Iustin Pop
    for idx, device in enumerate(instance["disks"]):
1190 f965260c Michael Hanselmann
      _FormatList(buf, _FormatBlockDevInfo(idx, True, device,
1191 e2736e40 Guido Trotter
                  opts.roman_integers), 2)
1192 a8083063 Iustin Pop
1193 d0c8c01d Iustin Pop
  ToStdout(buf.getvalue().rstrip("\n"))
1194 a8083063 Iustin Pop
  return retcode
1195 a8083063 Iustin Pop
1196 a8083063 Iustin Pop
1197 a71f835e Michael Hanselmann
def _ConvertNicDiskModifications(mods):
1198 a71f835e Michael Hanselmann
  """Converts NIC/disk modifications from CLI to opcode.
1199 a71f835e Michael Hanselmann

1200 a71f835e Michael Hanselmann
  When L{opcodes.OpInstanceSetParams} was changed to support adding/removing
1201 a71f835e Michael Hanselmann
  disks at arbitrary indices, its parameter format changed. This function
1202 a71f835e Michael Hanselmann
  converts legacy requests (e.g. "--net add" or "--disk add:size=4G") to the
1203 a71f835e Michael Hanselmann
  newer format and adds support for new-style requests (e.g. "--new 4:add").
1204 a71f835e Michael Hanselmann

1205 a71f835e Michael Hanselmann
  @type mods: list of tuples
1206 a71f835e Michael Hanselmann
  @param mods: Modifications as given by command line parser
1207 a71f835e Michael Hanselmann
  @rtype: list of tuples
1208 a71f835e Michael Hanselmann
  @return: Modifications as understood by L{opcodes.OpInstanceSetParams}
1209 a71f835e Michael Hanselmann

1210 a71f835e Michael Hanselmann
  """
1211 a71f835e Michael Hanselmann
  result = []
1212 a71f835e Michael Hanselmann
1213 a71f835e Michael Hanselmann
  for (idx, params) in mods:
1214 a71f835e Michael Hanselmann
    if idx == constants.DDM_ADD:
1215 a71f835e Michael Hanselmann
      # Add item as last item (legacy interface)
1216 a71f835e Michael Hanselmann
      action = constants.DDM_ADD
1217 a71f835e Michael Hanselmann
      idxno = -1
1218 a71f835e Michael Hanselmann
    elif idx == constants.DDM_REMOVE:
1219 a71f835e Michael Hanselmann
      # Remove last item (legacy interface)
1220 a71f835e Michael Hanselmann
      action = constants.DDM_REMOVE
1221 a71f835e Michael Hanselmann
      idxno = -1
1222 a71f835e Michael Hanselmann
    else:
1223 a71f835e Michael Hanselmann
      # Modifications and adding/removing at arbitrary indices
1224 a71f835e Michael Hanselmann
      try:
1225 a71f835e Michael Hanselmann
        idxno = int(idx)
1226 a71f835e Michael Hanselmann
      except (TypeError, ValueError):
1227 a71f835e Michael Hanselmann
        raise errors.OpPrereqError("Non-numeric index '%s'" % idx,
1228 a71f835e Michael Hanselmann
                                   errors.ECODE_INVAL)
1229 a71f835e Michael Hanselmann
1230 a71f835e Michael Hanselmann
      add = params.pop(constants.DDM_ADD, _MISSING)
1231 a71f835e Michael Hanselmann
      remove = params.pop(constants.DDM_REMOVE, _MISSING)
1232 f0d22861 Constantinos Venetsanopoulos
      modify = params.pop(constants.DDM_MODIFY, _MISSING)
1233 f0d22861 Constantinos Venetsanopoulos
1234 f0d22861 Constantinos Venetsanopoulos
      if modify is _MISSING:
1235 f0d22861 Constantinos Venetsanopoulos
        if not (add is _MISSING or remove is _MISSING):
1236 f0d22861 Constantinos Venetsanopoulos
          raise errors.OpPrereqError("Cannot add and remove at the same time",
1237 f0d22861 Constantinos Venetsanopoulos
                                     errors.ECODE_INVAL)
1238 f0d22861 Constantinos Venetsanopoulos
        elif add is not _MISSING:
1239 f0d22861 Constantinos Venetsanopoulos
          action = constants.DDM_ADD
1240 f0d22861 Constantinos Venetsanopoulos
        elif remove is not _MISSING:
1241 f0d22861 Constantinos Venetsanopoulos
          action = constants.DDM_REMOVE
1242 f0d22861 Constantinos Venetsanopoulos
        else:
1243 f0d22861 Constantinos Venetsanopoulos
          action = constants.DDM_MODIFY
1244 a71f835e Michael Hanselmann
1245 7a70541e Michael Hanselmann
      elif add is _MISSING and remove is _MISSING:
1246 7a70541e Michael Hanselmann
        action = constants.DDM_MODIFY
1247 a71f835e Michael Hanselmann
      else:
1248 7a70541e Michael Hanselmann
        raise errors.OpPrereqError("Cannot modify and add/remove at the"
1249 7a70541e Michael Hanselmann
                                   " same time", errors.ECODE_INVAL)
1250 a71f835e Michael Hanselmann
1251 a71f835e Michael Hanselmann
      assert not (constants.DDMS_VALUES_WITH_MODIFY & set(params.keys()))
1252 a71f835e Michael Hanselmann
1253 a71f835e Michael Hanselmann
    if action == constants.DDM_REMOVE and params:
1254 a71f835e Michael Hanselmann
      raise errors.OpPrereqError("Not accepting parameters on removal",
1255 a71f835e Michael Hanselmann
                                 errors.ECODE_INVAL)
1256 a71f835e Michael Hanselmann
1257 a71f835e Michael Hanselmann
    result.append((action, idxno, params))
1258 a71f835e Michael Hanselmann
1259 a71f835e Michael Hanselmann
  return result
1260 a71f835e Michael Hanselmann
1261 a71f835e Michael Hanselmann
1262 a71f835e Michael Hanselmann
def _ParseDiskSizes(mods):
1263 a71f835e Michael Hanselmann
  """Parses disk sizes in parameters.
1264 a71f835e Michael Hanselmann

1265 a71f835e Michael Hanselmann
  """
1266 a71f835e Michael Hanselmann
  for (action, _, params) in mods:
1267 a71f835e Michael Hanselmann
    if params and constants.IDISK_SIZE in params:
1268 a71f835e Michael Hanselmann
      params[constants.IDISK_SIZE] = \
1269 a71f835e Michael Hanselmann
        utils.ParseUnit(params[constants.IDISK_SIZE])
1270 a71f835e Michael Hanselmann
    elif action == constants.DDM_ADD:
1271 a71f835e Michael Hanselmann
      raise errors.OpPrereqError("Missing required parameter 'size'",
1272 a71f835e Michael Hanselmann
                                 errors.ECODE_INVAL)
1273 a71f835e Michael Hanselmann
1274 a71f835e Michael Hanselmann
  return mods
1275 a71f835e Michael Hanselmann
1276 a71f835e Michael Hanselmann
1277 7767bbf5 Manuel Franceschini
def SetInstanceParams(opts, args):
1278 a8083063 Iustin Pop
  """Modifies an instance.
1279 a8083063 Iustin Pop

1280 a8083063 Iustin Pop
  All parameters take effect only at the next restart of the instance.
1281 a8083063 Iustin Pop

1282 7232c04c Iustin Pop
  @param opts: the command line options selected by the user
1283 7232c04c Iustin Pop
  @type args: list
1284 7232c04c Iustin Pop
  @param args: should contain only one element, the instance name
1285 7232c04c Iustin Pop
  @rtype: int
1286 7232c04c Iustin Pop
  @return: the desired exit code
1287 a8083063 Iustin Pop

1288 a8083063 Iustin Pop
  """
1289 e29e9550 Iustin Pop
  if not (opts.nics or opts.disks or opts.disk_template or
1290 57de31c0 Agata Murawska
          opts.hvparams or opts.beparams or opts.os or opts.osparams or
1291 2c0af7da Guido Trotter
          opts.offline_inst or opts.online_inst or opts.runtime_mem):
1292 3a24c527 Iustin Pop
    ToStderr("Please give at least one of the parameters.")
1293 a8083063 Iustin Pop
    return 1
1294 a8083063 Iustin Pop
1295 467ae11e Guido Trotter
  for param in opts.beparams:
1296 e9d622bc Guido Trotter
    if isinstance(opts.beparams[param], basestring):
1297 e9d622bc Guido Trotter
      if opts.beparams[param].lower() == "default":
1298 e9d622bc Guido Trotter
        opts.beparams[param] = constants.VALUE_DEFAULT
1299 a5728081 Guido Trotter
1300 b2e233a5 Guido Trotter
  utils.ForceDictType(opts.beparams, constants.BES_PARAMETER_COMPAT,
1301 a5728081 Guido Trotter
                      allowed_values=[constants.VALUE_DEFAULT])
1302 467ae11e Guido Trotter
1303 48f212d7 Iustin Pop
  for param in opts.hvparams:
1304 48f212d7 Iustin Pop
    if isinstance(opts.hvparams[param], basestring):
1305 48f212d7 Iustin Pop
      if opts.hvparams[param].lower() == "default":
1306 48f212d7 Iustin Pop
        opts.hvparams[param] = constants.VALUE_DEFAULT
1307 a5728081 Guido Trotter
1308 48f212d7 Iustin Pop
  utils.ForceDictType(opts.hvparams, constants.HVS_PARAMETER_TYPES,
1309 a5728081 Guido Trotter
                      allowed_values=[constants.VALUE_DEFAULT])
1310 61be6ba4 Iustin Pop
1311 a71f835e Michael Hanselmann
  nics = _ConvertNicDiskModifications(opts.nics)
1312 a71f835e Michael Hanselmann
  disks = _ParseDiskSizes(_ConvertNicDiskModifications(opts.disks))
1313 24991749 Iustin Pop
1314 e29e9550 Iustin Pop
  if (opts.disk_template and
1315 3429a076 Apollon Oikonomopoulos
      opts.disk_template in constants.DTS_INT_MIRROR and
1316 e29e9550 Iustin Pop
      not opts.node):
1317 e29e9550 Iustin Pop
    ToStderr("Changing the disk template to a mirrored one requires"
1318 e29e9550 Iustin Pop
             " specifying a secondary node")
1319 e29e9550 Iustin Pop
    return 1
1320 e29e9550 Iustin Pop
1321 3016bc1f Michael Hanselmann
  if opts.offline_inst:
1322 3016bc1f Michael Hanselmann
    offline = True
1323 3016bc1f Michael Hanselmann
  elif opts.online_inst:
1324 3016bc1f Michael Hanselmann
    offline = False
1325 3016bc1f Michael Hanselmann
  else:
1326 3016bc1f Michael Hanselmann
    offline = None
1327 3016bc1f Michael Hanselmann
1328 9a3cc7ae Iustin Pop
  op = opcodes.OpInstanceSetParams(instance_name=args[0],
1329 a71f835e Michael Hanselmann
                                   nics=nics,
1330 a71f835e Michael Hanselmann
                                   disks=disks,
1331 e29e9550 Iustin Pop
                                   disk_template=opts.disk_template,
1332 e29e9550 Iustin Pop
                                   remote_node=opts.node,
1333 48f212d7 Iustin Pop
                                   hvparams=opts.hvparams,
1334 338e51e8 Iustin Pop
                                   beparams=opts.beparams,
1335 2c0af7da Guido Trotter
                                   runtime_mem=opts.runtime_mem,
1336 96b39bcc Iustin Pop
                                   os_name=opts.os,
1337 1052d622 Iustin Pop
                                   osparams=opts.osparams,
1338 96b39bcc Iustin Pop
                                   force_variant=opts.force_variant,
1339 456798ab Iustin Pop
                                   force=opts.force,
1340 57de31c0 Agata Murawska
                                   wait_for_sync=opts.wait_for_sync,
1341 3016bc1f Michael Hanselmann
                                   offline=offline,
1342 9c784fb3 Dimitris Aragiorgis
                                   conflicts_check=opts.conflicts_check,
1343 1559e1e7 René Nussbaumer
                                   ignore_ipolicy=opts.ignore_ipolicy)
1344 31a853d2 Iustin Pop
1345 6340bb0a Iustin Pop
  # even if here we process the result, we allow submit only
1346 6340bb0a Iustin Pop
  result = SubmitOrSend(op, opts)
1347 a8083063 Iustin Pop
1348 a8083063 Iustin Pop
  if result:
1349 3a24c527 Iustin Pop
    ToStdout("Modified instance %s", args[0])
1350 a8083063 Iustin Pop
    for param, data in result:
1351 3a24c527 Iustin Pop
      ToStdout(" - %-5s -> %s", param, data)
1352 e29e9550 Iustin Pop
    ToStdout("Please don't forget that most parameters take effect"
1353 d976957d Iustin Pop
             " only at the next (re)start of the instance initiated by"
1354 d976957d Iustin Pop
             " ganeti; restarting from within the instance will"
1355 d976957d Iustin Pop
             " not be enough.")
1356 a8083063 Iustin Pop
  return 0
1357 a8083063 Iustin Pop
1358 a8083063 Iustin Pop
1359 bd2a5569 Michael Hanselmann
def ChangeGroup(opts, args):
1360 bd2a5569 Michael Hanselmann
  """Moves an instance to another group.
1361 bd2a5569 Michael Hanselmann

1362 bd2a5569 Michael Hanselmann
  """
1363 bd2a5569 Michael Hanselmann
  (instance_name, ) = args
1364 bd2a5569 Michael Hanselmann
1365 bd2a5569 Michael Hanselmann
  cl = GetClient()
1366 bd2a5569 Michael Hanselmann
1367 bd2a5569 Michael Hanselmann
  op = opcodes.OpInstanceChangeGroup(instance_name=instance_name,
1368 bd2a5569 Michael Hanselmann
                                     iallocator=opts.iallocator,
1369 bd2a5569 Michael Hanselmann
                                     target_groups=opts.to,
1370 bd2a5569 Michael Hanselmann
                                     early_release=opts.early_release)
1371 f70bb622 Michael Hanselmann
  result = SubmitOrSend(op, opts, cl=cl)
1372 bd2a5569 Michael Hanselmann
1373 bd2a5569 Michael Hanselmann
  # Keep track of submitted jobs
1374 bd2a5569 Michael Hanselmann
  jex = JobExecutor(cl=cl, opts=opts)
1375 bd2a5569 Michael Hanselmann
1376 bd2a5569 Michael Hanselmann
  for (status, job_id) in result[constants.JOB_IDS_KEY]:
1377 bd2a5569 Michael Hanselmann
    jex.AddJobId(None, status, job_id)
1378 bd2a5569 Michael Hanselmann
1379 bd2a5569 Michael Hanselmann
  results = jex.GetResults()
1380 bd2a5569 Michael Hanselmann
  bad_cnt = len([row for row in results if not row[0]])
1381 bd2a5569 Michael Hanselmann
  if bad_cnt == 0:
1382 bd2a5569 Michael Hanselmann
    ToStdout("Instance '%s' changed group successfully.", instance_name)
1383 bd2a5569 Michael Hanselmann
    rcode = constants.EXIT_SUCCESS
1384 bd2a5569 Michael Hanselmann
  else:
1385 bd2a5569 Michael Hanselmann
    ToStdout("There were %s errors while changing group of instance '%s'.",
1386 bd2a5569 Michael Hanselmann
             bad_cnt, instance_name)
1387 bd2a5569 Michael Hanselmann
    rcode = constants.EXIT_FAILURE
1388 bd2a5569 Michael Hanselmann
1389 bd2a5569 Michael Hanselmann
  return rcode
1390 bd2a5569 Michael Hanselmann
1391 bd2a5569 Michael Hanselmann
1392 312ac745 Iustin Pop
# multi-instance selection options
1393 c38c44ad Michael Hanselmann
m_force_multi = cli_option("--force-multiple", dest="force_multi",
1394 c38c44ad Michael Hanselmann
                           help="Do not ask for confirmation when more than"
1395 c38c44ad Michael Hanselmann
                           " one instance is affected",
1396 c38c44ad Michael Hanselmann
                           action="store_true", default=False)
1397 804a1e8e Iustin Pop
1398 c38c44ad Michael Hanselmann
m_pri_node_opt = cli_option("--primary", dest="multi_mode",
1399 c38c44ad Michael Hanselmann
                            help="Filter by nodes (primary only)",
1400 c20efaa8 Michael Hanselmann
                            const=_EXPAND_NODES_PRI, action="store_const")
1401 312ac745 Iustin Pop
1402 c38c44ad Michael Hanselmann
m_sec_node_opt = cli_option("--secondary", dest="multi_mode",
1403 c38c44ad Michael Hanselmann
                            help="Filter by nodes (secondary only)",
1404 c20efaa8 Michael Hanselmann
                            const=_EXPAND_NODES_SEC, action="store_const")
1405 312ac745 Iustin Pop
1406 c38c44ad Michael Hanselmann
m_node_opt = cli_option("--node", dest="multi_mode",
1407 c38c44ad Michael Hanselmann
                        help="Filter by nodes (primary and secondary)",
1408 c20efaa8 Michael Hanselmann
                        const=_EXPAND_NODES_BOTH, action="store_const")
1409 312ac745 Iustin Pop
1410 c38c44ad Michael Hanselmann
m_clust_opt = cli_option("--all", dest="multi_mode",
1411 c38c44ad Michael Hanselmann
                         help="Select all instances in the cluster",
1412 c20efaa8 Michael Hanselmann
                         const=_EXPAND_CLUSTER, action="store_const")
1413 312ac745 Iustin Pop
1414 c38c44ad Michael Hanselmann
m_inst_opt = cli_option("--instance", dest="multi_mode",
1415 c38c44ad Michael Hanselmann
                        help="Filter by instance name [default]",
1416 c20efaa8 Michael Hanselmann
                        const=_EXPAND_INSTANCES, action="store_const")
1417 312ac745 Iustin Pop
1418 39dfd93e René Nussbaumer
m_node_tags_opt = cli_option("--node-tags", dest="multi_mode",
1419 39dfd93e René Nussbaumer
                             help="Filter by node tag",
1420 c20efaa8 Michael Hanselmann
                             const=_EXPAND_NODES_BOTH_BY_TAGS,
1421 39dfd93e René Nussbaumer
                             action="store_const")
1422 39dfd93e René Nussbaumer
1423 39dfd93e René Nussbaumer
m_pri_node_tags_opt = cli_option("--pri-node-tags", dest="multi_mode",
1424 39dfd93e René Nussbaumer
                                 help="Filter by primary node tag",
1425 c20efaa8 Michael Hanselmann
                                 const=_EXPAND_NODES_PRI_BY_TAGS,
1426 39dfd93e René Nussbaumer
                                 action="store_const")
1427 39dfd93e René Nussbaumer
1428 39dfd93e René Nussbaumer
m_sec_node_tags_opt = cli_option("--sec-node-tags", dest="multi_mode",
1429 39dfd93e René Nussbaumer
                                 help="Filter by secondary node tag",
1430 c20efaa8 Michael Hanselmann
                                 const=_EXPAND_NODES_SEC_BY_TAGS,
1431 39dfd93e René Nussbaumer
                                 action="store_const")
1432 39dfd93e René Nussbaumer
1433 39dfd93e René Nussbaumer
m_inst_tags_opt = cli_option("--tags", dest="multi_mode",
1434 39dfd93e René Nussbaumer
                             help="Filter by instance tag",
1435 c20efaa8 Michael Hanselmann
                             const=_EXPAND_INSTANCES_BY_TAGS,
1436 39dfd93e René Nussbaumer
                             action="store_const")
1437 312ac745 Iustin Pop
1438 a8083063 Iustin Pop
# this is defined separately due to readability only
1439 a8083063 Iustin Pop
add_opts = [
1440 064c21f8 Iustin Pop
  NOSTART_OPT,
1441 064c21f8 Iustin Pop
  OS_OPT,
1442 06073e85 Guido Trotter
  FORCE_VARIANT_OPT,
1443 25a8792c Iustin Pop
  NO_INSTALL_OPT,
1444 10889e0c René Nussbaumer
  IGNORE_IPOLICY_OPT,
1445 a8083063 Iustin Pop
  ]
1446 a8083063 Iustin Pop
1447 a8083063 Iustin Pop
commands = {
1448 d0c8c01d Iustin Pop
  "add": (
1449 eb28ecf6 Guido Trotter
    AddInstance, [ArgHost(min=1, max=1)], COMMON_CREATE_OPTS + add_opts,
1450 6ea815cf Iustin Pop
    "[...] -t disk-type -n node[:secondary-node] -o os-type <name>",
1451 6ea815cf Iustin Pop
    "Creates and adds a new instance to the cluster"),
1452 d0c8c01d Iustin Pop
  "batch-create": (
1453 b0a8e8c2 René Nussbaumer
    BatchCreate, [ArgFile(min=1, max=1)],
1454 b0a8e8c2 René Nussbaumer
    [DRY_RUN_OPT, PRIORITY_OPT, IALLOCATOR_OPT, SUBMIT_OPT],
1455 6ea815cf Iustin Pop
    "<instances.json>",
1456 6ea815cf Iustin Pop
    "Create a bunch of instances based on specs in the file."),
1457 d0c8c01d Iustin Pop
  "console": (
1458 6ea815cf Iustin Pop
    ConnectToInstanceConsole, ARGS_ONE_INSTANCE,
1459 aa06f8c6 Michael Hanselmann
    [SHOWCMD_OPT, PRIORITY_OPT],
1460 6ea815cf Iustin Pop
    "[--show-cmd] <instance>", "Opens a console on the specified instance"),
1461 d0c8c01d Iustin Pop
  "failover": (
1462 6ea815cf Iustin Pop
    FailoverInstance, ARGS_ONE_INSTANCE,
1463 db5a8a2d Iustin Pop
    [FORCE_OPT, IGNORE_CONSIST_OPT, SUBMIT_OPT, SHUTDOWN_TIMEOUT_OPT,
1464 b6aaf437 René Nussbaumer
     DRY_RUN_OPT, PRIORITY_OPT, DST_NODE_OPT, IALLOCATOR_OPT,
1465 b6aaf437 René Nussbaumer
     IGNORE_IPOLICY_OPT],
1466 a6a3efe4 Iustin Pop
    "[-f] <instance>", "Stops the instance, changes its primary node and"
1467 a6a3efe4 Iustin Pop
    " (if it was originally running) starts it on the new node"
1468 a6a3efe4 Iustin Pop
    " (the secondary for mirrored instances or any node"
1469 a6a3efe4 Iustin Pop
    " for shared storage)."),
1470 d0c8c01d Iustin Pop
  "migrate": (
1471 6ea815cf Iustin Pop
    MigrateInstance, ARGS_ONE_INSTANCE,
1472 aa06f8c6 Michael Hanselmann
    [FORCE_OPT, NONLIVE_OPT, MIGRATION_MODE_OPT, CLEANUP_OPT, DRY_RUN_OPT,
1473 3ed23330 René Nussbaumer
     PRIORITY_OPT, DST_NODE_OPT, IALLOCATOR_OPT, ALLOW_FAILOVER_OPT,
1474 f70bb622 Michael Hanselmann
     IGNORE_IPOLICY_OPT, NORUNTIME_CHGS_OPT, SUBMIT_OPT],
1475 6ea815cf Iustin Pop
    "[-f] <instance>", "Migrate instance to its secondary node"
1476 1b7761fd Apollon Oikonomopoulos
    " (only for mirrored instances)"),
1477 d0c8c01d Iustin Pop
  "move": (
1478 6ea815cf Iustin Pop
    MoveInstance, ARGS_ONE_INSTANCE,
1479 db5a8a2d Iustin Pop
    [FORCE_OPT, SUBMIT_OPT, SINGLE_NODE_OPT, SHUTDOWN_TIMEOUT_OPT,
1480 92cf62e3 René Nussbaumer
     DRY_RUN_OPT, PRIORITY_OPT, IGNORE_CONSIST_OPT, IGNORE_IPOLICY_OPT],
1481 6ea815cf Iustin Pop
    "[-f] <instance>", "Move instance to an arbitrary node"
1482 6ea815cf Iustin Pop
    " (only for instances of type file and lv)"),
1483 d0c8c01d Iustin Pop
  "info": (
1484 6ea815cf Iustin Pop
    ShowInstanceConfig, ARGS_MANY_INSTANCES,
1485 aa06f8c6 Michael Hanselmann
    [STATIC_OPT, ALL_OPT, ROMAN_OPT, PRIORITY_OPT],
1486 6ea815cf Iustin Pop
    "[-s] {--all | <instance>...}",
1487 6ea815cf Iustin Pop
    "Show information on the specified instance(s)"),
1488 d0c8c01d Iustin Pop
  "list": (
1489 6ea815cf Iustin Pop
    ListInstances, ARGS_MANY_INSTANCES,
1490 87e87959 Michael Hanselmann
    [NOHDR_OPT, SEP_OPT, USEUNITS_OPT, FIELDS_OPT, VERBOSE_OPT,
1491 87e87959 Michael Hanselmann
     FORCE_FILTER_OPT],
1492 6ea815cf Iustin Pop
    "[<instance>...]",
1493 b82c5ff5 Michael Hanselmann
    "Lists the instances and their status. The available fields can be shown"
1494 b82c5ff5 Michael Hanselmann
    " using the \"list-fields\" command (see the man page for details)."
1495 b82c5ff5 Michael Hanselmann
    " The default field list is (in order): %s." %
1496 b82c5ff5 Michael Hanselmann
    utils.CommaJoin(_LIST_DEF_FIELDS),
1497 6ea815cf Iustin Pop
    ),
1498 b82c5ff5 Michael Hanselmann
  "list-fields": (
1499 b82c5ff5 Michael Hanselmann
    ListInstanceFields, [ArgUnknown()],
1500 b82c5ff5 Michael Hanselmann
    [NOHDR_OPT, SEP_OPT],
1501 b82c5ff5 Michael Hanselmann
    "[fields...]",
1502 b82c5ff5 Michael Hanselmann
    "Lists all available fields for instances"),
1503 d0c8c01d Iustin Pop
  "reinstall": (
1504 3e54ace7 Iustin Pop
    ReinstallInstance, [ArgInstance()],
1505 06073e85 Guido Trotter
    [FORCE_OPT, OS_OPT, FORCE_VARIANT_OPT, m_force_multi, m_node_opt,
1506 39dfd93e René Nussbaumer
     m_pri_node_opt, m_sec_node_opt, m_clust_opt, m_inst_opt, m_node_tags_opt,
1507 39dfd93e René Nussbaumer
     m_pri_node_tags_opt, m_sec_node_tags_opt, m_inst_tags_opt, SELECT_OS_OPT,
1508 8d8c4eff Michael Hanselmann
     SUBMIT_OPT, DRY_RUN_OPT, PRIORITY_OPT, OSPARAMS_OPT],
1509 6ea815cf Iustin Pop
    "[-f] <instance>", "Reinstall a stopped instance"),
1510 d0c8c01d Iustin Pop
  "remove": (
1511 6ea815cf Iustin Pop
    RemoveInstance, ARGS_ONE_INSTANCE,
1512 db5a8a2d Iustin Pop
    [FORCE_OPT, SHUTDOWN_TIMEOUT_OPT, IGNORE_FAILURES_OPT, SUBMIT_OPT,
1513 aa06f8c6 Michael Hanselmann
     DRY_RUN_OPT, PRIORITY_OPT],
1514 6ea815cf Iustin Pop
    "[-f] <instance>", "Shuts down the instance and removes it"),
1515 d0c8c01d Iustin Pop
  "rename": (
1516 6ea815cf Iustin Pop
    RenameInstance,
1517 6ea815cf Iustin Pop
    [ArgInstance(min=1, max=1), ArgHost(min=1, max=1)],
1518 aa06f8c6 Michael Hanselmann
    [NOIPCHECK_OPT, NONAMECHECK_OPT, SUBMIT_OPT, DRY_RUN_OPT, PRIORITY_OPT],
1519 6ea815cf Iustin Pop
    "<instance> <new_name>", "Rename the instance"),
1520 d0c8c01d Iustin Pop
  "replace-disks": (
1521 6ea815cf Iustin Pop
    ReplaceDisks, ARGS_ONE_INSTANCE,
1522 7ea7bcf6 Iustin Pop
    [AUTO_REPLACE_OPT, DISKIDX_OPT, IALLOCATOR_OPT, EARLY_RELEASE_OPT,
1523 db5a8a2d Iustin Pop
     NEW_SECONDARY_OPT, ON_PRIMARY_OPT, ON_SECONDARY_OPT, SUBMIT_OPT,
1524 893e8f49 René Nussbaumer
     DRY_RUN_OPT, PRIORITY_OPT, IGNORE_IPOLICY_OPT],
1525 50c1e351 Bernardo Dal Seno
    "[-s|-p|-a|-n NODE|-I NAME] <instance>",
1526 50c1e351 Bernardo Dal Seno
    "Replaces disks for the instance"),
1527 d0c8c01d Iustin Pop
  "modify": (
1528 6ea815cf Iustin Pop
    SetInstanceParams, ARGS_ONE_INSTANCE,
1529 e29e9550 Iustin Pop
    [BACKEND_OPT, DISK_OPT, FORCE_OPT, HVOPTS_OPT, NET_OPT, SUBMIT_OPT,
1530 1052d622 Iustin Pop
     DISK_TEMPLATE_OPT, SINGLE_NODE_OPT, OS_OPT, FORCE_VARIANT_OPT,
1531 57de31c0 Agata Murawska
     OSPARAMS_OPT, DRY_RUN_OPT, PRIORITY_OPT, NWSYNC_OPT, OFFLINE_INST_OPT,
1532 9c784fb3 Dimitris Aragiorgis
     ONLINE_INST_OPT, IGNORE_IPOLICY_OPT, RUNTIME_MEM_OPT,
1533 9c784fb3 Dimitris Aragiorgis
     NOCONFLICTSCHECK_OPT],
1534 6ea815cf Iustin Pop
    "<instance>", "Alters the parameters of an instance"),
1535 d0c8c01d Iustin Pop
  "shutdown": (
1536 1c5945b6 Iustin Pop
    GenericManyOps("shutdown", _ShutdownInstance), [ArgInstance()],
1537 0d57ce24 Guido Trotter
    [FORCE_OPT, m_node_opt, m_pri_node_opt, m_sec_node_opt, m_clust_opt,
1538 39dfd93e René Nussbaumer
     m_node_tags_opt, m_pri_node_tags_opt, m_sec_node_tags_opt,
1539 db5a8a2d Iustin Pop
     m_inst_tags_opt, m_inst_opt, m_force_multi, TIMEOUT_OPT, SUBMIT_OPT,
1540 885a0fc4 Iustin Pop
     DRY_RUN_OPT, PRIORITY_OPT, IGNORE_OFFLINE_OPT, NO_REMEMBER_OPT],
1541 6ea815cf Iustin Pop
    "<instance>", "Stops an instance"),
1542 d0c8c01d Iustin Pop
  "startup": (
1543 1c5945b6 Iustin Pop
    GenericManyOps("startup", _StartupInstance), [ArgInstance()],
1544 39dfd93e René Nussbaumer
    [FORCE_OPT, m_force_multi, m_node_opt, m_pri_node_opt, m_sec_node_opt,
1545 39dfd93e René Nussbaumer
     m_node_tags_opt, m_pri_node_tags_opt, m_sec_node_tags_opt,
1546 39dfd93e René Nussbaumer
     m_inst_tags_opt, m_clust_opt, m_inst_opt, SUBMIT_OPT, HVOPTS_OPT,
1547 885a0fc4 Iustin Pop
     BACKEND_OPT, DRY_RUN_OPT, PRIORITY_OPT, IGNORE_OFFLINE_OPT,
1548 323f9095 Stephen Shirley
     NO_REMEMBER_OPT, STARTUP_PAUSED_OPT],
1549 6ea815cf Iustin Pop
    "<instance>", "Starts an instance"),
1550 d0c8c01d Iustin Pop
  "reboot": (
1551 1c5945b6 Iustin Pop
    GenericManyOps("reboot", _RebootInstance), [ArgInstance()],
1552 064c21f8 Iustin Pop
    [m_force_multi, REBOOT_TYPE_OPT, IGNORE_SECONDARIES_OPT, m_node_opt,
1553 17c3f802 Guido Trotter
     m_pri_node_opt, m_sec_node_opt, m_clust_opt, m_inst_opt, SUBMIT_OPT,
1554 39dfd93e René Nussbaumer
     m_node_tags_opt, m_pri_node_tags_opt, m_sec_node_tags_opt,
1555 aa06f8c6 Michael Hanselmann
     m_inst_tags_opt, SHUTDOWN_TIMEOUT_OPT, DRY_RUN_OPT, PRIORITY_OPT],
1556 6ea815cf Iustin Pop
    "<instance>", "Reboots an instance"),
1557 d0c8c01d Iustin Pop
  "activate-disks": (
1558 db5a8a2d Iustin Pop
    ActivateDisks, ARGS_ONE_INSTANCE,
1559 f30d8165 Iustin Pop
    [SUBMIT_OPT, IGNORE_SIZE_OPT, PRIORITY_OPT, WFSYNC_OPT],
1560 6ea815cf Iustin Pop
    "<instance>", "Activate an instance's disks"),
1561 d0c8c01d Iustin Pop
  "deactivate-disks": (
1562 aa06f8c6 Michael Hanselmann
    DeactivateDisks, ARGS_ONE_INSTANCE,
1563 c9c41373 Iustin Pop
    [FORCE_OPT, SUBMIT_OPT, DRY_RUN_OPT, PRIORITY_OPT],
1564 c9c41373 Iustin Pop
    "[-f] <instance>", "Deactivate an instance's disks"),
1565 d0c8c01d Iustin Pop
  "recreate-disks": (
1566 aa06f8c6 Michael Hanselmann
    RecreateDisks, ARGS_ONE_INSTANCE,
1567 38db4e7c Adam Ingrassia
    [SUBMIT_OPT, DISK_OPT, NODE_PLACEMENT_OPT, DRY_RUN_OPT, PRIORITY_OPT,
1568 38db4e7c Adam Ingrassia
     IALLOCATOR_OPT],
1569 6ea815cf Iustin Pop
    "<instance>", "Recreate an instance's disks"),
1570 d0c8c01d Iustin Pop
  "grow-disk": (
1571 6ea815cf Iustin Pop
    GrowDisk,
1572 6ea815cf Iustin Pop
    [ArgInstance(min=1, max=1), ArgUnknown(min=1, max=1),
1573 6ea815cf Iustin Pop
     ArgUnknown(min=1, max=1)],
1574 ef8270dc Iustin Pop
    [SUBMIT_OPT, NWSYNC_OPT, DRY_RUN_OPT, PRIORITY_OPT, ABSOLUTE_OPT],
1575 6ea815cf Iustin Pop
    "<instance> <disk> <size>", "Grow an instance's disk"),
1576 bd2a5569 Michael Hanselmann
  "change-group": (
1577 bd2a5569 Michael Hanselmann
    ChangeGroup, ARGS_ONE_INSTANCE,
1578 f70bb622 Michael Hanselmann
    [TO_GROUP_OPT, IALLOCATOR_OPT, EARLY_RELEASE_OPT, PRIORITY_OPT, SUBMIT_OPT],
1579 bd2a5569 Michael Hanselmann
    "[-I <iallocator>] [--to <group>]", "Change group of instance"),
1580 d0c8c01d Iustin Pop
  "list-tags": (
1581 6bc3ed14 Michael Hanselmann
    ListTags, ARGS_ONE_INSTANCE, [],
1582 6ea815cf Iustin Pop
    "<instance_name>", "List the tags of the given instance"),
1583 d0c8c01d Iustin Pop
  "add-tags": (
1584 6ea815cf Iustin Pop
    AddTags, [ArgInstance(min=1, max=1), ArgUnknown()],
1585 6bc3ed14 Michael Hanselmann
    [TAG_SRC_OPT, PRIORITY_OPT, SUBMIT_OPT],
1586 6ea815cf Iustin Pop
    "<instance_name> tag...", "Add tags to the given instance"),
1587 d0c8c01d Iustin Pop
  "remove-tags": (
1588 6ea815cf Iustin Pop
    RemoveTags, [ArgInstance(min=1, max=1), ArgUnknown()],
1589 6bc3ed14 Michael Hanselmann
    [TAG_SRC_OPT, PRIORITY_OPT, SUBMIT_OPT],
1590 6ea815cf Iustin Pop
    "<instance_name> tag...", "Remove tags from given instance"),
1591 a8083063 Iustin Pop
  }
1592 a8083063 Iustin Pop
1593 7232c04c Iustin Pop
#: dictionary with aliases for commands
1594 dbfd89dd Guido Trotter
aliases = {
1595 d0c8c01d Iustin Pop
  "start": "startup",
1596 d0c8c01d Iustin Pop
  "stop": "shutdown",
1597 96897af7 Alexander Schreiber
  "show": "info",
1598 dbfd89dd Guido Trotter
  }
1599 dbfd89dd Guido Trotter
1600 a8005e17 Michael Hanselmann
1601 e792102d Michael Hanselmann
def Main():
1602 e792102d Michael Hanselmann
  return GenericMain(commands, aliases=aliases,
1603 ef9fa5b9 René Nussbaumer
                     override={"tag_type": constants.TAG_INSTANCE},
1604 ef9fa5b9 René Nussbaumer
                     env_override=_ENV_OVERRIDE)