Statistics
| Branch: | Tag: | Revision:

root / lib / client / gnt_instance.py @ d027b72b

History | View | Annotate | Download (57.5 kB)

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

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

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

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

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

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

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

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

180 1c5945b6 Iustin Pop
  """
181 1c5945b6 Iustin Pop
  def realfn(opts, args):
182 1c5945b6 Iustin Pop
    if opts.multi_mode is None:
183 c20efaa8 Michael Hanselmann
      opts.multi_mode = _EXPAND_INSTANCES
184 1c5945b6 Iustin Pop
    cl = GetClient()
185 981224e9 Helga Velroyen
    qcl = GetClient(query=True)
186 981224e9 Helga Velroyen
    inames = _ExpandMultiNames(opts.multi_mode, args, client=qcl)
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 e96c0a5c Hrvoje Ribicic
  cl = GetClient(query=True)
228 e96c0a5c Hrvoje Ribicic
229 b82c5ff5 Michael Hanselmann
  return GenericList(constants.QR_INSTANCE, selected_fields, args, opts.units,
230 b82c5ff5 Michael Hanselmann
                     opts.separator, not opts.no_headers,
231 87e87959 Michael Hanselmann
                     format_override=fmtoverride, verbose=opts.verbose,
232 e96c0a5c Hrvoje Ribicic
                     force_filter=opts.force_filter, cl=cl)
233 b82c5ff5 Michael Hanselmann
234 b82c5ff5 Michael Hanselmann
235 b82c5ff5 Michael Hanselmann
def ListInstanceFields(opts, args):
236 b82c5ff5 Michael Hanselmann
  """List instance fields.
237 b82c5ff5 Michael Hanselmann

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

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

252 002764e8 Jose A. Lopes
  This is just a wrapper over L{GenericInstanceCreate}.
253 a8083063 Iustin Pop

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

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

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

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

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

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

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

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

446 7232c04c Iustin Pop
  @param opts: the command line options selected by the user
447 7232c04c Iustin Pop
  @type args: list
448 7232c04c Iustin Pop
  @param args: should contain two elements, the old and the
449 7232c04c Iustin Pop
      new instance names
450 7232c04c Iustin Pop
  @rtype: int
451 7232c04c Iustin Pop
  @return: the desired exit code
452 decd5f45 Iustin Pop

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

474 a8083063 Iustin Pop
  This serves two purposes:
475 7232c04c Iustin Pop
    - it allows (as long as the instance is not running)
476 7232c04c Iustin Pop
      mounting the disks and modifying them from the node
477 a8083063 Iustin Pop
    - it repairs inactive secondary drbds
478 a8083063 Iustin Pop

479 7232c04c Iustin Pop
  @param opts: the command line options selected by the user
480 7232c04c Iustin Pop
  @type args: list
481 7232c04c Iustin Pop
  @param args: should contain only one element, the instance name
482 7232c04c Iustin Pop
  @rtype: int
483 7232c04c Iustin Pop
  @return: the desired exit code
484 7232c04c Iustin Pop

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

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

502 7232c04c Iustin Pop
  @param opts: the command line options selected by the user
503 7232c04c Iustin Pop
  @type args: list
504 7232c04c Iustin Pop
  @param args: should contain only one element, the instance name
505 7232c04c Iustin Pop
  @rtype: int
506 7232c04c Iustin Pop
  @return: the desired exit code
507 7232c04c Iustin Pop

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

519 bd315bfa Iustin Pop
  @param opts: the command line options selected by the user
520 bd315bfa Iustin Pop
  @type args: list
521 bd315bfa Iustin Pop
  @param args: should contain only one element, the instance name
522 bd315bfa Iustin Pop
  @rtype: int
523 bd315bfa Iustin Pop
  @return: the desired exit code
524 bd315bfa Iustin Pop

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

581 7232c04c Iustin Pop
  @param opts: the command line options selected by the user
582 7232c04c Iustin Pop
  @type args: list
583 30a83755 Guido Trotter
  @param args: should contain three elements, the target instance name,
584 30a83755 Guido Trotter
      the target disk id, and the target growth
585 7232c04c Iustin Pop
  @rtype: int
586 7232c04c Iustin Pop
  @return: the desired exit code
587 c6e911bc Iustin Pop

588 c6e911bc Iustin Pop
  """
589 c6e911bc Iustin Pop
  instance = args[0]
590 c6e911bc Iustin Pop
  disk = args[1]
591 ad24e046 Iustin Pop
  try:
592 ad24e046 Iustin Pop
    disk = int(disk)
593 691744c4 Iustin Pop
  except (TypeError, ValueError), err:
594 debac808 Iustin Pop
    raise errors.OpPrereqError("Invalid disk index: %s" % str(err),
595 debac808 Iustin Pop
                               errors.ECODE_INVAL)
596 c8bde61e Iustin Pop
  try:
597 c8bde61e Iustin Pop
    amount = utils.ParseUnit(args[2])
598 c8bde61e Iustin Pop
  except errors.UnitParseError:
599 c8bde61e Iustin Pop
    raise errors.OpPrereqError("Can't parse the given amount '%s'" % args[2],
600 c8bde61e Iustin Pop
                               errors.ECODE_INVAL)
601 60472d29 Iustin Pop
  op = opcodes.OpInstanceGrowDisk(instance_name=instance,
602 60472d29 Iustin Pop
                                  disk=disk, amount=amount,
603 ef8270dc Iustin Pop
                                  wait_for_sync=opts.wait_for_sync,
604 ef8270dc Iustin Pop
                                  absolute=opts.absolute)
605 6340bb0a Iustin Pop
  SubmitOrSend(op, opts)
606 c6e911bc Iustin Pop
  return 0
607 c6e911bc Iustin Pop
608 c6e911bc Iustin Pop
609 1c5945b6 Iustin Pop
def _StartupInstance(name, opts):
610 7232c04c Iustin Pop
  """Startup instances.
611 a8083063 Iustin Pop

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

615 1c5945b6 Iustin Pop
  @param name: the name of the instance to act on
616 7232c04c Iustin Pop
  @param opts: the command line options selected by the user
617 1c5945b6 Iustin Pop
  @return: the opcode needed for the operation
618 a8083063 Iustin Pop

619 a8083063 Iustin Pop
  """
620 c873d91c Iustin Pop
  op = opcodes.OpInstanceStartup(instance_name=name,
621 b44bd844 Michael Hanselmann
                                 force=opts.force,
622 885a0fc4 Iustin Pop
                                 ignore_offline_nodes=opts.ignore_offline,
623 323f9095 Stephen Shirley
                                 no_remember=opts.no_remember,
624 323f9095 Stephen Shirley
                                 startup_paused=opts.startup_paused)
625 1c5945b6 Iustin Pop
  # do not add these parameters to the opcode unless they're defined
626 1c5945b6 Iustin Pop
  if opts.hvparams:
627 1c5945b6 Iustin Pop
    op.hvparams = opts.hvparams
628 1c5945b6 Iustin Pop
  if opts.beparams:
629 1c5945b6 Iustin Pop
    op.beparams = opts.beparams
630 1c5945b6 Iustin Pop
  return op
631 a8083063 Iustin Pop
632 7c0d6283 Michael Hanselmann
633 1c5945b6 Iustin Pop
def _RebootInstance(name, opts):
634 7232c04c Iustin Pop
  """Reboot instance(s).
635 7232c04c Iustin Pop

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

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

643 579d4337 Alexander Schreiber
  """
644 90ab1a95 Iustin Pop
  return opcodes.OpInstanceReboot(instance_name=name,
645 579d4337 Alexander Schreiber
                                  reboot_type=opts.reboot_type,
646 17c3f802 Guido Trotter
                                  ignore_secondaries=opts.ignore_secondaries,
647 aa922d64 Michele Tartara
                                  shutdown_timeout=opts.shutdown_timeout)
648 a8083063 Iustin Pop
649 7c0d6283 Michael Hanselmann
650 1c5945b6 Iustin Pop
def _ShutdownInstance(name, opts):
651 a8083063 Iustin Pop
  """Shutdown an instance.
652 a8083063 Iustin Pop

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

656 1c5945b6 Iustin Pop
  @param name: the name of the instance to act on
657 7232c04c Iustin Pop
  @param opts: the command line options selected by the user
658 1c5945b6 Iustin Pop
  @return: the opcode needed for the operation
659 a8083063 Iustin Pop

660 a8083063 Iustin Pop
  """
661 ee3e37a7 Iustin Pop
  return opcodes.OpInstanceShutdown(instance_name=name,
662 0d57ce24 Guido Trotter
                                    force=opts.force,
663 b44bd844 Michael Hanselmann
                                    timeout=opts.timeout,
664 885a0fc4 Iustin Pop
                                    ignore_offline_nodes=opts.ignore_offline,
665 885a0fc4 Iustin Pop
                                    no_remember=opts.no_remember)
666 a8083063 Iustin Pop
667 a8083063 Iustin Pop
668 a8083063 Iustin Pop
def ReplaceDisks(opts, args):
669 a8083063 Iustin Pop
  """Replace the disks of an instance
670 a8083063 Iustin Pop

671 7232c04c Iustin Pop
  @param opts: the command line options selected by the user
672 7232c04c Iustin Pop
  @type args: list
673 7232c04c Iustin Pop
  @param args: should contain only one element, the instance name
674 7232c04c Iustin Pop
  @rtype: int
675 7232c04c Iustin Pop
  @return: the desired exit code
676 a8083063 Iustin Pop

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

718 a8083063 Iustin Pop
  The failover is done by shutting it down on its present node and
719 a8083063 Iustin Pop
  starting it on the secondary.
720 a8083063 Iustin Pop

721 7232c04c Iustin Pop
  @param opts: the command line options selected by the user
722 7232c04c Iustin Pop
  @type args: list
723 7232c04c Iustin Pop
  @param args: should contain only one element, the instance name
724 7232c04c Iustin Pop
  @rtype: int
725 7232c04c Iustin Pop
  @return: the desired exit code
726 a8083063 Iustin Pop

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

760 53c776b5 Iustin Pop
  The migrate is done without shutdown.
761 53c776b5 Iustin Pop

762 2f907a8c Iustin Pop
  @param opts: the command line options selected by the user
763 2f907a8c Iustin Pop
  @type args: list
764 2f907a8c Iustin Pop
  @param args: should contain only one element, the instance name
765 2f907a8c Iustin Pop
  @rtype: int
766 2f907a8c Iustin Pop
  @return: the desired exit code
767 53c776b5 Iustin Pop

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

817 fbf5a861 Iustin Pop
  @param opts: the command line options selected by the user
818 fbf5a861 Iustin Pop
  @type args: list
819 fbf5a861 Iustin Pop
  @param args: should contain only one element, the instance name
820 fbf5a861 Iustin Pop
  @rtype: int
821 fbf5a861 Iustin Pop
  @return: the desired exit code
822 fbf5a861 Iustin Pop

823 fbf5a861 Iustin Pop
  """
824 fbf5a861 Iustin Pop
  cl = GetClient()
825 fbf5a861 Iustin Pop
  instance_name = args[0]
826 fbf5a861 Iustin Pop
  force = opts.force
827 fbf5a861 Iustin Pop
828 fbf5a861 Iustin Pop
  if not force:
829 fbf5a861 Iustin Pop
    usertext = ("Instance %s will be moved."
830 fbf5a861 Iustin Pop
                " This requires a shutdown of the instance. Continue?" %
831 fbf5a861 Iustin Pop
                (instance_name,))
832 fbf5a861 Iustin Pop
    if not AskUser(usertext):
833 fbf5a861 Iustin Pop
      return 1
834 fbf5a861 Iustin Pop
835 0091b480 Iustin Pop
  op = opcodes.OpInstanceMove(instance_name=instance_name,
836 17c3f802 Guido Trotter
                              target_node=opts.node,
837 94ab995a Thomas Thrainer
                              compress=opts.compress,
838 bb851c63 Iustin Pop
                              shutdown_timeout=opts.shutdown_timeout,
839 92cf62e3 René Nussbaumer
                              ignore_consistency=opts.ignore_consistency,
840 92cf62e3 René Nussbaumer
                              ignore_ipolicy=opts.ignore_ipolicy)
841 fbf5a861 Iustin Pop
  SubmitOrSend(op, opts, cl=cl)
842 fbf5a861 Iustin Pop
  return 0
843 fbf5a861 Iustin Pop
844 fbf5a861 Iustin Pop
845 a8083063 Iustin Pop
def ConnectToInstanceConsole(opts, args):
846 a8083063 Iustin Pop
  """Connect to the console of an instance.
847 a8083063 Iustin Pop

848 7232c04c Iustin Pop
  @param opts: the command line options selected by the user
849 7232c04c Iustin Pop
  @type args: list
850 7232c04c Iustin Pop
  @param args: should contain only one element, the instance name
851 7232c04c Iustin Pop
  @rtype: int
852 7232c04c Iustin Pop
  @return: the desired exit code
853 a8083063 Iustin Pop

854 a8083063 Iustin Pop
  """
855 a8083063 Iustin Pop
  instance_name = args[0]
856 a8083063 Iustin Pop
857 25ce3ec4 Michael Hanselmann
  cl = GetClient()
858 981224e9 Helga Velroyen
  qcl = GetClient(query=True)
859 25ce3ec4 Michael Hanselmann
  try:
860 25ce3ec4 Michael Hanselmann
    cluster_name = cl.QueryConfigValues(["cluster_name"])[0]
861 d6f46b6a Michael Hanselmann
    ((console_data, oper_state), ) = \
862 981224e9 Helga Velroyen
      qcl.QueryInstances([instance_name], ["console", "oper_state"], False)
863 25ce3ec4 Michael Hanselmann
  finally:
864 25ce3ec4 Michael Hanselmann
    # Ensure client connection is closed while external commands are run
865 25ce3ec4 Michael Hanselmann
    cl.Close()
866 981224e9 Helga Velroyen
    qcl.Close()
867 25ce3ec4 Michael Hanselmann
868 25ce3ec4 Michael Hanselmann
  del cl
869 981224e9 Helga Velroyen
  del qcl
870 25ce3ec4 Michael Hanselmann
871 d6f46b6a Michael Hanselmann
  if not console_data:
872 d6f46b6a Michael Hanselmann
    if oper_state:
873 d6f46b6a Michael Hanselmann
      # Instance is running
874 d6f46b6a Michael Hanselmann
      raise errors.OpExecError("Console information for instance %s is"
875 d6f46b6a Michael Hanselmann
                               " unavailable" % instance_name)
876 d6f46b6a Michael Hanselmann
    else:
877 d6f46b6a Michael Hanselmann
      raise errors.OpExecError("Instance %s is not running, can't get console" %
878 d6f46b6a Michael Hanselmann
                               instance_name)
879 d6f46b6a Michael Hanselmann
880 25ce3ec4 Michael Hanselmann
  return _DoConsole(objects.InstanceConsole.FromDict(console_data),
881 25ce3ec4 Michael Hanselmann
                    opts.show_command, cluster_name)
882 25ce3ec4 Michael Hanselmann
883 25ce3ec4 Michael Hanselmann
884 25ce3ec4 Michael Hanselmann
def _DoConsole(console, show_command, cluster_name, feedback_fn=ToStdout,
885 25ce3ec4 Michael Hanselmann
               _runcmd_fn=utils.RunCmd):
886 cc0dec7b Iustin Pop
  """Acts based on the result of L{opcodes.OpInstanceConsole}.
887 25ce3ec4 Michael Hanselmann

888 25ce3ec4 Michael Hanselmann
  @type console: L{objects.InstanceConsole}
889 25ce3ec4 Michael Hanselmann
  @param console: Console object
890 25ce3ec4 Michael Hanselmann
  @type show_command: bool
891 25ce3ec4 Michael Hanselmann
  @param show_command: Whether to just display commands
892 25ce3ec4 Michael Hanselmann
  @type cluster_name: string
893 25ce3ec4 Michael Hanselmann
  @param cluster_name: Cluster name as retrieved from master daemon
894 25ce3ec4 Michael Hanselmann

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

940 19708787 Iustin Pop
  """
941 cd3b4ff4 Helga Velroyen
  if dev_type == constants.DT_DRBD8:
942 1c3231aa Thomas Thrainer
    drbd_info = dev["drbd_info"]
943 19708787 Iustin Pop
    data = [
944 1c3231aa Thomas Thrainer
      ("nodeA", "%s, minor=%s" %
945 1c3231aa Thomas Thrainer
                (drbd_info["primary_node"],
946 1c3231aa Thomas Thrainer
                 compat.TryToRoman(drbd_info["primary_minor"],
947 1c3231aa Thomas Thrainer
                                   convert=roman))),
948 1c3231aa Thomas Thrainer
      ("nodeB", "%s, minor=%s" %
949 1c3231aa Thomas Thrainer
                (drbd_info["secondary_node"],
950 1c3231aa Thomas Thrainer
                 compat.TryToRoman(drbd_info["secondary_minor"],
951 1c3231aa Thomas Thrainer
                                   convert=roman))),
952 1c3231aa Thomas Thrainer
      ("port", str(compat.TryToRoman(drbd_info["port"], convert=roman))),
953 1c3231aa Thomas Thrainer
      ("auth key", str(drbd_info["secret"])),
954 19708787 Iustin Pop
      ]
955 cd3b4ff4 Helga Velroyen
  elif dev_type == constants.DT_PLAIN:
956 1c3231aa Thomas Thrainer
    vg_name, lv_name = dev["logical_id"]
957 19708787 Iustin Pop
    data = ["%s/%s" % (vg_name, lv_name)]
958 19708787 Iustin Pop
  else:
959 1c3231aa Thomas Thrainer
    data = [str(dev["logical_id"])]
960 19708787 Iustin Pop
961 19708787 Iustin Pop
  return data
962 19708787 Iustin Pop
963 19708787 Iustin Pop
964 f965260c Michael Hanselmann
def _FormatBlockDevInfo(idx, top_level, dev, roman):
965 a8083063 Iustin Pop
  """Show block device information.
966 a8083063 Iustin Pop

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

970 19708787 Iustin Pop
  @type idx: int
971 19708787 Iustin Pop
  @param idx: the index of the current disk
972 19708787 Iustin Pop
  @type top_level: boolean
973 19708787 Iustin Pop
  @param top_level: if this a top-level disk?
974 7232c04c Iustin Pop
  @type dev: dict
975 7232c04c Iustin Pop
  @param dev: dictionary with disk information
976 e2736e40 Guido Trotter
  @type roman: boolean
977 e2736e40 Guido Trotter
  @param roman: whether to try to use roman integers
978 19708787 Iustin Pop
  @return: a list of either strings, tuples or lists
979 19708787 Iustin Pop
      (which should be formatted at a higher indent level)
980 7232c04c Iustin Pop

981 a8083063 Iustin Pop
  """
982 19708787 Iustin Pop
  def helper(dtype, status):
983 7232c04c Iustin Pop
    """Format one line for physical device status.
984 7232c04c Iustin Pop

985 7232c04c Iustin Pop
    @type dtype: str
986 cd3b4ff4 Helga Velroyen
    @param dtype: a constant from the L{constants.DTS_BLOCK} set
987 7232c04c Iustin Pop
    @type status: tuple
988 7232c04c Iustin Pop
    @param status: a tuple as returned from L{backend.FindBlockDevice}
989 19708787 Iustin Pop
    @return: the string representing the status
990 7232c04c Iustin Pop

991 7232c04c Iustin Pop
    """
992 a8083063 Iustin Pop
    if not status:
993 19708787 Iustin Pop
      return "not active"
994 19708787 Iustin Pop
    txt = ""
995 f208978a Michael Hanselmann
    (path, major, minor, syncp, estt, degr, ldisk_status) = status
996 19708787 Iustin Pop
    if major is None:
997 19708787 Iustin Pop
      major_string = "N/A"
998 a8083063 Iustin Pop
    else:
999 e2736e40 Guido Trotter
      major_string = str(compat.TryToRoman(major, convert=roman))
1000 fd38ef95 Manuel Franceschini
1001 19708787 Iustin Pop
    if minor is None:
1002 19708787 Iustin Pop
      minor_string = "N/A"
1003 19708787 Iustin Pop
    else:
1004 e2736e40 Guido Trotter
      minor_string = str(compat.TryToRoman(minor, convert=roman))
1005 19708787 Iustin Pop
1006 19708787 Iustin Pop
    txt += ("%s (%s:%s)" % (path, major_string, minor_string))
1007 cd3b4ff4 Helga Velroyen
    if dtype in (constants.DT_DRBD8, ):
1008 19708787 Iustin Pop
      if syncp is not None:
1009 19708787 Iustin Pop
        sync_text = "*RECOVERING* %5.2f%%," % syncp
1010 19708787 Iustin Pop
        if estt:
1011 e2736e40 Guido Trotter
          sync_text += " ETA %ss" % compat.TryToRoman(estt, convert=roman)
1012 9db6dbce Iustin Pop
        else:
1013 19708787 Iustin Pop
          sync_text += " ETA unknown"
1014 19708787 Iustin Pop
      else:
1015 19708787 Iustin Pop
        sync_text = "in sync"
1016 19708787 Iustin Pop
      if degr:
1017 19708787 Iustin Pop
        degr_text = "*DEGRADED*"
1018 19708787 Iustin Pop
      else:
1019 19708787 Iustin Pop
        degr_text = "ok"
1020 f208978a Michael Hanselmann
      if ldisk_status == constants.LDS_FAULTY:
1021 19708787 Iustin Pop
        ldisk_text = " *MISSING DISK*"
1022 f208978a Michael Hanselmann
      elif ldisk_status == constants.LDS_UNKNOWN:
1023 f208978a Michael Hanselmann
        ldisk_text = " *UNCERTAIN STATE*"
1024 19708787 Iustin Pop
      else:
1025 19708787 Iustin Pop
        ldisk_text = ""
1026 19708787 Iustin Pop
      txt += (" %s, status %s%s" % (sync_text, degr_text, ldisk_text))
1027 cd3b4ff4 Helga Velroyen
    elif dtype == constants.DT_PLAIN:
1028 f208978a Michael Hanselmann
      if ldisk_status == constants.LDS_FAULTY:
1029 19708787 Iustin Pop
        ldisk_text = " *FAILED* (failed drive?)"
1030 19708787 Iustin Pop
      else:
1031 19708787 Iustin Pop
        ldisk_text = ""
1032 19708787 Iustin Pop
      txt += ldisk_text
1033 19708787 Iustin Pop
    return txt
1034 19708787 Iustin Pop
1035 19708787 Iustin Pop
  # the header
1036 19708787 Iustin Pop
  if top_level:
1037 19708787 Iustin Pop
    if dev["iv_name"] is not None:
1038 19708787 Iustin Pop
      txt = dev["iv_name"]
1039 19708787 Iustin Pop
    else:
1040 e2736e40 Guido Trotter
      txt = "disk %s" % compat.TryToRoman(idx, convert=roman)
1041 a8083063 Iustin Pop
  else:
1042 e2736e40 Guido Trotter
    txt = "child %s" % compat.TryToRoman(idx, convert=roman)
1043 c98162a7 Iustin Pop
  if isinstance(dev["size"], int):
1044 c98162a7 Iustin Pop
    nice_size = utils.FormatUnit(dev["size"], "h")
1045 c98162a7 Iustin Pop
  else:
1046 2cbcf95d Bernardo Dal Seno
    nice_size = str(dev["size"])
1047 2cbcf95d Bernardo Dal Seno
  data = [(txt, "%s, size %s" % (dev["dev_type"], nice_size))]
1048 19708787 Iustin Pop
  if top_level:
1049 75a6c8be Bernardo Dal Seno
    if dev["spindles"] is not None:
1050 75a6c8be Bernardo Dal Seno
      data.append(("spindles", dev["spindles"]))
1051 19708787 Iustin Pop
    data.append(("access mode", dev["mode"]))
1052 a8083063 Iustin Pop
  if dev["logical_id"] is not None:
1053 19708787 Iustin Pop
    try:
1054 1c3231aa Thomas Thrainer
      l_id = _FormatDiskDetails(dev["dev_type"], dev, roman)
1055 19708787 Iustin Pop
    except ValueError:
1056 19708787 Iustin Pop
      l_id = [str(dev["logical_id"])]
1057 19708787 Iustin Pop
    if len(l_id) == 1:
1058 19708787 Iustin Pop
      data.append(("logical_id", l_id[0]))
1059 19708787 Iustin Pop
    else:
1060 19708787 Iustin Pop
      data.extend(l_id)
1061 f965260c Michael Hanselmann
1062 f965260c Michael Hanselmann
  if dev["pstatus"]:
1063 19708787 Iustin Pop
    data.append(("on primary", helper(dev["dev_type"], dev["pstatus"])))
1064 f965260c Michael Hanselmann
1065 f965260c Michael Hanselmann
  if dev["sstatus"]:
1066 19708787 Iustin Pop
    data.append(("on secondary", helper(dev["dev_type"], dev["sstatus"])))
1067 a8083063 Iustin Pop
1068 fcbd025c Christos Stavrakakis
  data.append(("name", dev["name"]))
1069 fcbd025c Christos Stavrakakis
  data.append(("UUID", dev["uuid"]))
1070 fcbd025c Christos Stavrakakis
1071 a8083063 Iustin Pop
  if dev["children"]:
1072 2cbcf95d Bernardo Dal Seno
    data.append(("child devices", [
1073 2cbcf95d Bernardo Dal Seno
      _FormatBlockDevInfo(c_idx, False, child, roman)
1074 2cbcf95d Bernardo Dal Seno
      for c_idx, child in enumerate(dev["children"])
1075 2cbcf95d Bernardo Dal Seno
      ]))
1076 2cbcf95d Bernardo Dal Seno
  return data
1077 19708787 Iustin Pop
1078 19708787 Iustin Pop
1079 2cbcf95d Bernardo Dal Seno
def _FormatInstanceNicInfo(idx, nic):
1080 2cbcf95d Bernardo Dal Seno
  """Helper function for L{_FormatInstanceInfo()}"""
1081 d676dbea Sebastian Gebhard
  (name, uuid, ip, mac, mode, link, vlan, _, netinfo) = nic
1082 2cbcf95d Bernardo Dal Seno
  network_name = None
1083 2cbcf95d Bernardo Dal Seno
  if netinfo:
1084 2cbcf95d Bernardo Dal Seno
    network_name = netinfo["name"]
1085 2cbcf95d Bernardo Dal Seno
  return [
1086 2cbcf95d Bernardo Dal Seno
    ("nic/%d" % idx, ""),
1087 2cbcf95d Bernardo Dal Seno
    ("MAC", str(mac)),
1088 2cbcf95d Bernardo Dal Seno
    ("IP", str(ip)),
1089 2cbcf95d Bernardo Dal Seno
    ("mode", str(mode)),
1090 2cbcf95d Bernardo Dal Seno
    ("link", str(link)),
1091 d676dbea Sebastian Gebhard
    ("vlan", str(vlan)),
1092 2cbcf95d Bernardo Dal Seno
    ("network", str(network_name)),
1093 fcbd025c Christos Stavrakakis
    ("UUID", str(uuid)),
1094 fcbd025c Christos Stavrakakis
    ("name", str(name)),
1095 2cbcf95d Bernardo Dal Seno
    ]
1096 2cbcf95d Bernardo Dal Seno
1097 2cbcf95d Bernardo Dal Seno
1098 2cbcf95d Bernardo Dal Seno
def _FormatInstanceNodesInfo(instance):
1099 2cbcf95d Bernardo Dal Seno
  """Helper function for L{_FormatInstanceInfo()}"""
1100 2cbcf95d Bernardo Dal Seno
  pgroup = ("%s (UUID %s)" %
1101 2cbcf95d Bernardo Dal Seno
            (instance["pnode_group_name"], instance["pnode_group_uuid"]))
1102 2cbcf95d Bernardo Dal Seno
  secs = utils.CommaJoin(("%s (group %s, group UUID %s)" %
1103 2cbcf95d Bernardo Dal Seno
                          (name, group_name, group_uuid))
1104 2cbcf95d Bernardo Dal Seno
                         for (name, group_name, group_uuid) in
1105 2cbcf95d Bernardo Dal Seno
                           zip(instance["snodes"],
1106 2cbcf95d Bernardo Dal Seno
                               instance["snodes_group_names"],
1107 2cbcf95d Bernardo Dal Seno
                               instance["snodes_group_uuids"]))
1108 2cbcf95d Bernardo Dal Seno
  return [
1109 2cbcf95d Bernardo Dal Seno
    [
1110 2cbcf95d Bernardo Dal Seno
      ("primary", instance["pnode"]),
1111 2cbcf95d Bernardo Dal Seno
      ("group", pgroup),
1112 2cbcf95d Bernardo Dal Seno
      ],
1113 2cbcf95d Bernardo Dal Seno
    [("secondaries", secs)],
1114 2cbcf95d Bernardo Dal Seno
    ]
1115 2cbcf95d Bernardo Dal Seno
1116 2cbcf95d Bernardo Dal Seno
1117 2cbcf95d Bernardo Dal Seno
def _GetVncConsoleInfo(instance):
1118 2cbcf95d Bernardo Dal Seno
  """Helper function for L{_FormatInstanceInfo()}"""
1119 2cbcf95d Bernardo Dal Seno
  vnc_bind_address = instance["hv_actual"].get(constants.HV_VNC_BIND_ADDRESS,
1120 2cbcf95d Bernardo Dal Seno
                                               None)
1121 2cbcf95d Bernardo Dal Seno
  if vnc_bind_address:
1122 2cbcf95d Bernardo Dal Seno
    port = instance["network_port"]
1123 2cbcf95d Bernardo Dal Seno
    display = int(port) - constants.VNC_BASE_PORT
1124 2cbcf95d Bernardo Dal Seno
    if display > 0 and vnc_bind_address == constants.IP4_ADDRESS_ANY:
1125 2cbcf95d Bernardo Dal Seno
      vnc_console_port = "%s:%s (display %s)" % (instance["pnode"],
1126 2cbcf95d Bernardo Dal Seno
                                                 port,
1127 2cbcf95d Bernardo Dal Seno
                                                 display)
1128 2cbcf95d Bernardo Dal Seno
    elif display > 0 and netutils.IP4Address.IsValid(vnc_bind_address):
1129 2cbcf95d Bernardo Dal Seno
      vnc_console_port = ("%s:%s (node %s) (display %s)" %
1130 2cbcf95d Bernardo Dal Seno
                           (vnc_bind_address, port,
1131 2cbcf95d Bernardo Dal Seno
                            instance["pnode"], display))
1132 2cbcf95d Bernardo Dal Seno
    else:
1133 2cbcf95d Bernardo Dal Seno
      # vnc bind address is a file
1134 2cbcf95d Bernardo Dal Seno
      vnc_console_port = "%s:%s" % (instance["pnode"],
1135 2cbcf95d Bernardo Dal Seno
                                    vnc_bind_address)
1136 2cbcf95d Bernardo Dal Seno
    ret = "vnc to %s" % vnc_console_port
1137 2cbcf95d Bernardo Dal Seno
  else:
1138 2cbcf95d Bernardo Dal Seno
    ret = None
1139 2cbcf95d Bernardo Dal Seno
  return ret
1140 2cbcf95d Bernardo Dal Seno
1141 2cbcf95d Bernardo Dal Seno
1142 2cbcf95d Bernardo Dal Seno
def _FormatInstanceInfo(instance, roman_integers):
1143 2cbcf95d Bernardo Dal Seno
  """Format instance information for L{cli.PrintGenericInfo()}"""
1144 2cbcf95d Bernardo Dal Seno
  istate = "configured to be %s" % instance["config_state"]
1145 2cbcf95d Bernardo Dal Seno
  if instance["run_state"]:
1146 2cbcf95d Bernardo Dal Seno
    istate += ", actual state is %s" % instance["run_state"]
1147 2cbcf95d Bernardo Dal Seno
  info = [
1148 2cbcf95d Bernardo Dal Seno
    ("Instance name", instance["name"]),
1149 2cbcf95d Bernardo Dal Seno
    ("UUID", instance["uuid"]),
1150 2cbcf95d Bernardo Dal Seno
    ("Serial number",
1151 2cbcf95d Bernardo Dal Seno
     str(compat.TryToRoman(instance["serial_no"], convert=roman_integers))),
1152 2cbcf95d Bernardo Dal Seno
    ("Creation time", utils.FormatTime(instance["ctime"])),
1153 2cbcf95d Bernardo Dal Seno
    ("Modification time", utils.FormatTime(instance["mtime"])),
1154 2cbcf95d Bernardo Dal Seno
    ("State", istate),
1155 2cbcf95d Bernardo Dal Seno
    ("Nodes", _FormatInstanceNodesInfo(instance)),
1156 2cbcf95d Bernardo Dal Seno
    ("Operating system", instance["os"]),
1157 2cbcf95d Bernardo Dal Seno
    ("Operating system parameters",
1158 2cbcf95d Bernardo Dal Seno
     FormatParamsDictInfo(instance["os_instance"], instance["os_actual"])),
1159 2cbcf95d Bernardo Dal Seno
    ]
1160 2cbcf95d Bernardo Dal Seno
1161 2cbcf95d Bernardo Dal Seno
  if "network_port" in instance:
1162 2cbcf95d Bernardo Dal Seno
    info.append(("Allocated network port",
1163 2cbcf95d Bernardo Dal Seno
                 str(compat.TryToRoman(instance["network_port"],
1164 2cbcf95d Bernardo Dal Seno
                                       convert=roman_integers))))
1165 2cbcf95d Bernardo Dal Seno
  info.append(("Hypervisor", instance["hypervisor"]))
1166 2cbcf95d Bernardo Dal Seno
  console = _GetVncConsoleInfo(instance)
1167 2cbcf95d Bernardo Dal Seno
  if console:
1168 2cbcf95d Bernardo Dal Seno
    info.append(("console connection", console))
1169 2cbcf95d Bernardo Dal Seno
  # deprecated "memory" value, kept for one version for compatibility
1170 2cbcf95d Bernardo Dal Seno
  # TODO(ganeti 2.7) remove.
1171 2cbcf95d Bernardo Dal Seno
  be_actual = copy.deepcopy(instance["be_actual"])
1172 2cbcf95d Bernardo Dal Seno
  be_actual["memory"] = be_actual[constants.BE_MAXMEM]
1173 2cbcf95d Bernardo Dal Seno
  info.extend([
1174 2cbcf95d Bernardo Dal Seno
    ("Hypervisor parameters",
1175 2cbcf95d Bernardo Dal Seno
     FormatParamsDictInfo(instance["hv_instance"], instance["hv_actual"])),
1176 2cbcf95d Bernardo Dal Seno
    ("Back-end parameters",
1177 2cbcf95d Bernardo Dal Seno
     FormatParamsDictInfo(instance["be_instance"], be_actual)),
1178 2cbcf95d Bernardo Dal Seno
    ("NICs", [
1179 2cbcf95d Bernardo Dal Seno
      _FormatInstanceNicInfo(idx, nic)
1180 2cbcf95d Bernardo Dal Seno
      for (idx, nic) in enumerate(instance["nics"])
1181 2cbcf95d Bernardo Dal Seno
      ]),
1182 2cbcf95d Bernardo Dal Seno
    ("Disk template", instance["disk_template"]),
1183 2cbcf95d Bernardo Dal Seno
    ("Disks", [
1184 2cbcf95d Bernardo Dal Seno
      _FormatBlockDevInfo(idx, True, device, roman_integers)
1185 2cbcf95d Bernardo Dal Seno
      for (idx, device) in enumerate(instance["disks"])
1186 2cbcf95d Bernardo Dal Seno
      ]),
1187 2cbcf95d Bernardo Dal Seno
    ])
1188 2cbcf95d Bernardo Dal Seno
  return info
1189 19708787 Iustin Pop
1190 98825740 Michael Hanselmann
1191 a8083063 Iustin Pop
def ShowInstanceConfig(opts, args):
1192 a8083063 Iustin Pop
  """Compute instance run-time status.
1193 a8083063 Iustin Pop

1194 7232c04c Iustin Pop
  @param opts: the command line options selected by the user
1195 7232c04c Iustin Pop
  @type args: list
1196 7232c04c Iustin Pop
  @param args: either an empty list, and then we query all
1197 7232c04c Iustin Pop
      instances, or should contain a list of instance names
1198 7232c04c Iustin Pop
  @rtype: int
1199 7232c04c Iustin Pop
  @return: the desired exit code
1200 7232c04c Iustin Pop

1201 a8083063 Iustin Pop
  """
1202 220cde0b Guido Trotter
  if not args and not opts.show_all:
1203 220cde0b Guido Trotter
    ToStderr("No instance selected."
1204 220cde0b Guido Trotter
             " Please pass in --all if you want to query all instances.\n"
1205 220cde0b Guido Trotter
             "Note that this can take a long time on a big cluster.")
1206 220cde0b Guido Trotter
    return 1
1207 220cde0b Guido Trotter
  elif args and opts.show_all:
1208 220cde0b Guido Trotter
    ToStderr("Cannot use --all if you specify instance names.")
1209 220cde0b Guido Trotter
    return 1
1210 220cde0b Guido Trotter
1211 a8083063 Iustin Pop
  retcode = 0
1212 5c097318 Iustin Pop
  op = opcodes.OpInstanceQueryData(instances=args, static=opts.static,
1213 5c097318 Iustin Pop
                                   use_locking=not opts.static)
1214 400ca2f7 Iustin Pop
  result = SubmitOpCode(op, opts=opts)
1215 a8083063 Iustin Pop
  if not result:
1216 3a24c527 Iustin Pop
    ToStdout("No instances.")
1217 a8083063 Iustin Pop
    return 1
1218 a8083063 Iustin Pop
1219 2cbcf95d Bernardo Dal Seno
  PrintGenericInfo([
1220 2cbcf95d Bernardo Dal Seno
    _FormatInstanceInfo(instance, opts.roman_integers)
1221 2cbcf95d Bernardo Dal Seno
    for instance in result.values()
1222 2cbcf95d Bernardo Dal Seno
    ])
1223 a8083063 Iustin Pop
  return retcode
1224 a8083063 Iustin Pop
1225 a8083063 Iustin Pop
1226 a71f835e Michael Hanselmann
def _ConvertNicDiskModifications(mods):
1227 a71f835e Michael Hanselmann
  """Converts NIC/disk modifications from CLI to opcode.
1228 a71f835e Michael Hanselmann

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

1234 a71f835e Michael Hanselmann
  @type mods: list of tuples
1235 a71f835e Michael Hanselmann
  @param mods: Modifications as given by command line parser
1236 a71f835e Michael Hanselmann
  @rtype: list of tuples
1237 a71f835e Michael Hanselmann
  @return: Modifications as understood by L{opcodes.OpInstanceSetParams}
1238 a71f835e Michael Hanselmann

1239 a71f835e Michael Hanselmann
  """
1240 a71f835e Michael Hanselmann
  result = []
1241 a71f835e Michael Hanselmann
1242 b21d488b Christos Stavrakakis
  for (identifier, params) in mods:
1243 b21d488b Christos Stavrakakis
    if identifier == constants.DDM_ADD:
1244 a71f835e Michael Hanselmann
      # Add item as last item (legacy interface)
1245 a71f835e Michael Hanselmann
      action = constants.DDM_ADD
1246 b21d488b Christos Stavrakakis
      identifier = -1
1247 b21d488b Christos Stavrakakis
    elif identifier == constants.DDM_REMOVE:
1248 a71f835e Michael Hanselmann
      # Remove last item (legacy interface)
1249 a71f835e Michael Hanselmann
      action = constants.DDM_REMOVE
1250 b21d488b Christos Stavrakakis
      identifier = -1
1251 a71f835e Michael Hanselmann
    else:
1252 a71f835e Michael Hanselmann
      # Modifications and adding/removing at arbitrary indices
1253 a71f835e Michael Hanselmann
      add = params.pop(constants.DDM_ADD, _MISSING)
1254 a71f835e Michael Hanselmann
      remove = params.pop(constants.DDM_REMOVE, _MISSING)
1255 f0d22861 Constantinos Venetsanopoulos
      modify = params.pop(constants.DDM_MODIFY, _MISSING)
1256 f0d22861 Constantinos Venetsanopoulos
1257 f0d22861 Constantinos Venetsanopoulos
      if modify is _MISSING:
1258 f0d22861 Constantinos Venetsanopoulos
        if not (add is _MISSING or remove is _MISSING):
1259 f0d22861 Constantinos Venetsanopoulos
          raise errors.OpPrereqError("Cannot add and remove at the same time",
1260 f0d22861 Constantinos Venetsanopoulos
                                     errors.ECODE_INVAL)
1261 f0d22861 Constantinos Venetsanopoulos
        elif add is not _MISSING:
1262 f0d22861 Constantinos Venetsanopoulos
          action = constants.DDM_ADD
1263 f0d22861 Constantinos Venetsanopoulos
        elif remove is not _MISSING:
1264 f0d22861 Constantinos Venetsanopoulos
          action = constants.DDM_REMOVE
1265 f0d22861 Constantinos Venetsanopoulos
        else:
1266 f0d22861 Constantinos Venetsanopoulos
          action = constants.DDM_MODIFY
1267 a71f835e Michael Hanselmann
1268 7a70541e Michael Hanselmann
      elif add is _MISSING and remove is _MISSING:
1269 7a70541e Michael Hanselmann
        action = constants.DDM_MODIFY
1270 a71f835e Michael Hanselmann
      else:
1271 7a70541e Michael Hanselmann
        raise errors.OpPrereqError("Cannot modify and add/remove at the"
1272 7a70541e Michael Hanselmann
                                   " same time", errors.ECODE_INVAL)
1273 a71f835e Michael Hanselmann
1274 a71f835e Michael Hanselmann
      assert not (constants.DDMS_VALUES_WITH_MODIFY & set(params.keys()))
1275 a71f835e Michael Hanselmann
1276 a71f835e Michael Hanselmann
    if action == constants.DDM_REMOVE and params:
1277 a71f835e Michael Hanselmann
      raise errors.OpPrereqError("Not accepting parameters on removal",
1278 a71f835e Michael Hanselmann
                                 errors.ECODE_INVAL)
1279 a71f835e Michael Hanselmann
1280 b21d488b Christos Stavrakakis
    result.append((action, identifier, params))
1281 a71f835e Michael Hanselmann
1282 a71f835e Michael Hanselmann
  return result
1283 a71f835e Michael Hanselmann
1284 a71f835e Michael Hanselmann
1285 a71f835e Michael Hanselmann
def _ParseDiskSizes(mods):
1286 a71f835e Michael Hanselmann
  """Parses disk sizes in parameters.
1287 a71f835e Michael Hanselmann

1288 a71f835e Michael Hanselmann
  """
1289 a71f835e Michael Hanselmann
  for (action, _, params) in mods:
1290 1c785e0b Klaus Aehlig
    if params and constants.IDISK_SPINDLES in params:
1291 1c785e0b Klaus Aehlig
      params[constants.IDISK_SPINDLES] = \
1292 1c785e0b Klaus Aehlig
          int(params[constants.IDISK_SPINDLES])
1293 a71f835e Michael Hanselmann
    if params and constants.IDISK_SIZE in params:
1294 a71f835e Michael Hanselmann
      params[constants.IDISK_SIZE] = \
1295 a71f835e Michael Hanselmann
        utils.ParseUnit(params[constants.IDISK_SIZE])
1296 a71f835e Michael Hanselmann
    elif action == constants.DDM_ADD:
1297 a71f835e Michael Hanselmann
      raise errors.OpPrereqError("Missing required parameter 'size'",
1298 a71f835e Michael Hanselmann
                                 errors.ECODE_INVAL)
1299 a71f835e Michael Hanselmann
1300 a71f835e Michael Hanselmann
  return mods
1301 a71f835e Michael Hanselmann
1302 a71f835e Michael Hanselmann
1303 7767bbf5 Manuel Franceschini
def SetInstanceParams(opts, args):
1304 a8083063 Iustin Pop
  """Modifies an instance.
1305 a8083063 Iustin Pop

1306 a8083063 Iustin Pop
  All parameters take effect only at the next restart of the instance.
1307 a8083063 Iustin Pop

1308 7232c04c Iustin Pop
  @param opts: the command line options selected by the user
1309 7232c04c Iustin Pop
  @type args: list
1310 7232c04c Iustin Pop
  @param args: should contain only one element, the instance name
1311 7232c04c Iustin Pop
  @rtype: int
1312 7232c04c Iustin Pop
  @return: the desired exit code
1313 a8083063 Iustin Pop

1314 a8083063 Iustin Pop
  """
1315 1a182390 Santi Raffa
  if not (opts.nics or opts.disks or opts.disk_template or opts.hvparams or
1316 1a182390 Santi Raffa
          opts.beparams or opts.os or opts.osparams or opts.osparams_private
1317 1a182390 Santi Raffa
          or opts.offline_inst or opts.online_inst or opts.runtime_mem or
1318 3438e1f8 Klaus Aehlig
          opts.new_primary_node):
1319 3a24c527 Iustin Pop
    ToStderr("Please give at least one of the parameters.")
1320 a8083063 Iustin Pop
    return 1
1321 a8083063 Iustin Pop
1322 467ae11e Guido Trotter
  for param in opts.beparams:
1323 e9d622bc Guido Trotter
    if isinstance(opts.beparams[param], basestring):
1324 e9d622bc Guido Trotter
      if opts.beparams[param].lower() == "default":
1325 e9d622bc Guido Trotter
        opts.beparams[param] = constants.VALUE_DEFAULT
1326 a5728081 Guido Trotter
1327 b2e233a5 Guido Trotter
  utils.ForceDictType(opts.beparams, constants.BES_PARAMETER_COMPAT,
1328 a5728081 Guido Trotter
                      allowed_values=[constants.VALUE_DEFAULT])
1329 467ae11e Guido Trotter
1330 48f212d7 Iustin Pop
  for param in opts.hvparams:
1331 48f212d7 Iustin Pop
    if isinstance(opts.hvparams[param], basestring):
1332 48f212d7 Iustin Pop
      if opts.hvparams[param].lower() == "default":
1333 48f212d7 Iustin Pop
        opts.hvparams[param] = constants.VALUE_DEFAULT
1334 a5728081 Guido Trotter
1335 48f212d7 Iustin Pop
  utils.ForceDictType(opts.hvparams, constants.HVS_PARAMETER_TYPES,
1336 a5728081 Guido Trotter
                      allowed_values=[constants.VALUE_DEFAULT])
1337 02a6b50a Michele Tartara
  FixHvParams(opts.hvparams)
1338 61be6ba4 Iustin Pop
1339 a71f835e Michael Hanselmann
  nics = _ConvertNicDiskModifications(opts.nics)
1340 df58ca1c Dimitris Aragiorgis
  for action, _, __ in nics:
1341 e15a00dc Dimitris Aragiorgis
    if action == constants.DDM_MODIFY and opts.hotplug and not opts.force:
1342 df58ca1c Dimitris Aragiorgis
      usertext = ("You are about to hot-modify a NIC. This will be done"
1343 df58ca1c Dimitris Aragiorgis
                  " by removing the exisiting and then adding a new one."
1344 df58ca1c Dimitris Aragiorgis
                  " Network connection might be lost. Continue?")
1345 df58ca1c Dimitris Aragiorgis
      if not AskUser(usertext):
1346 df58ca1c Dimitris Aragiorgis
        return 1
1347 df58ca1c Dimitris Aragiorgis
1348 a71f835e Michael Hanselmann
  disks = _ParseDiskSizes(_ConvertNicDiskModifications(opts.disks))
1349 24991749 Iustin Pop
1350 e29e9550 Iustin Pop
  if (opts.disk_template and
1351 3429a076 Apollon Oikonomopoulos
      opts.disk_template in constants.DTS_INT_MIRROR and
1352 e29e9550 Iustin Pop
      not opts.node):
1353 e29e9550 Iustin Pop
    ToStderr("Changing the disk template to a mirrored one requires"
1354 e29e9550 Iustin Pop
             " specifying a secondary node")
1355 e29e9550 Iustin Pop
    return 1
1356 e29e9550 Iustin Pop
1357 3016bc1f Michael Hanselmann
  if opts.offline_inst:
1358 3016bc1f Michael Hanselmann
    offline = True
1359 3016bc1f Michael Hanselmann
  elif opts.online_inst:
1360 3016bc1f Michael Hanselmann
    offline = False
1361 3016bc1f Michael Hanselmann
  else:
1362 3016bc1f Michael Hanselmann
    offline = None
1363 3016bc1f Michael Hanselmann
1364 9a3cc7ae Iustin Pop
  op = opcodes.OpInstanceSetParams(instance_name=args[0],
1365 a71f835e Michael Hanselmann
                                   nics=nics,
1366 a71f835e Michael Hanselmann
                                   disks=disks,
1367 df58ca1c Dimitris Aragiorgis
                                   hotplug=opts.hotplug,
1368 96ed3a3e Dimitris Aragiorgis
                                   hotplug_if_possible=opts.hotplug_if_possible,
1369 e29e9550 Iustin Pop
                                   disk_template=opts.disk_template,
1370 e29e9550 Iustin Pop
                                   remote_node=opts.node,
1371 3438e1f8 Klaus Aehlig
                                   pnode=opts.new_primary_node,
1372 48f212d7 Iustin Pop
                                   hvparams=opts.hvparams,
1373 338e51e8 Iustin Pop
                                   beparams=opts.beparams,
1374 2c0af7da Guido Trotter
                                   runtime_mem=opts.runtime_mem,
1375 96b39bcc Iustin Pop
                                   os_name=opts.os,
1376 1052d622 Iustin Pop
                                   osparams=opts.osparams,
1377 1a182390 Santi Raffa
                                   osparams_private=opts.osparams_private,
1378 96b39bcc Iustin Pop
                                   force_variant=opts.force_variant,
1379 456798ab Iustin Pop
                                   force=opts.force,
1380 57de31c0 Agata Murawska
                                   wait_for_sync=opts.wait_for_sync,
1381 3016bc1f Michael Hanselmann
                                   offline=offline,
1382 9c784fb3 Dimitris Aragiorgis
                                   conflicts_check=opts.conflicts_check,
1383 1559e1e7 René Nussbaumer
                                   ignore_ipolicy=opts.ignore_ipolicy)
1384 31a853d2 Iustin Pop
1385 6340bb0a Iustin Pop
  # even if here we process the result, we allow submit only
1386 6340bb0a Iustin Pop
  result = SubmitOrSend(op, opts)
1387 a8083063 Iustin Pop
1388 a8083063 Iustin Pop
  if result:
1389 3a24c527 Iustin Pop
    ToStdout("Modified instance %s", args[0])
1390 a8083063 Iustin Pop
    for param, data in result:
1391 3a24c527 Iustin Pop
      ToStdout(" - %-5s -> %s", param, data)
1392 e29e9550 Iustin Pop
    ToStdout("Please don't forget that most parameters take effect"
1393 d976957d Iustin Pop
             " only at the next (re)start of the instance initiated by"
1394 d976957d Iustin Pop
             " ganeti; restarting from within the instance will"
1395 d976957d Iustin Pop
             " not be enough.")
1396 a8083063 Iustin Pop
  return 0
1397 a8083063 Iustin Pop
1398 a8083063 Iustin Pop
1399 bd2a5569 Michael Hanselmann
def ChangeGroup(opts, args):
1400 bd2a5569 Michael Hanselmann
  """Moves an instance to another group.
1401 bd2a5569 Michael Hanselmann

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