Statistics
| Branch: | Tag: | Revision:

root / lib / cli.py @ 936f3c59

History | View | Annotate | Download (56.9 kB)

1 2f31098c Iustin Pop
#
2 a8083063 Iustin Pop
#
3 a8083063 Iustin Pop
4 a8083063 Iustin Pop
# Copyright (C) 2006, 2007 Google Inc.
5 a8083063 Iustin Pop
#
6 a8083063 Iustin Pop
# This program is free software; you can redistribute it and/or modify
7 a8083063 Iustin Pop
# it under the terms of the GNU General Public License as published by
8 a8083063 Iustin Pop
# the Free Software Foundation; either version 2 of the License, or
9 a8083063 Iustin Pop
# (at your option) any later version.
10 a8083063 Iustin Pop
#
11 a8083063 Iustin Pop
# This program is distributed in the hope that it will be useful, but
12 a8083063 Iustin Pop
# WITHOUT ANY WARRANTY; without even the implied warranty of
13 a8083063 Iustin Pop
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 a8083063 Iustin Pop
# General Public License for more details.
15 a8083063 Iustin Pop
#
16 a8083063 Iustin Pop
# You should have received a copy of the GNU General Public License
17 a8083063 Iustin Pop
# along with this program; if not, write to the Free Software
18 a8083063 Iustin Pop
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 a8083063 Iustin Pop
# 02110-1301, USA.
20 a8083063 Iustin Pop
21 a8083063 Iustin Pop
22 a8083063 Iustin Pop
"""Module dealing with command line parsing"""
23 a8083063 Iustin Pop
24 a8083063 Iustin Pop
25 a8083063 Iustin Pop
import sys
26 a8083063 Iustin Pop
import textwrap
27 a8083063 Iustin Pop
import os.path
28 685ee993 Iustin Pop
import time
29 46fbdd04 Iustin Pop
import logging
30 73702ee7 Iustin Pop
from cStringIO import StringIO
31 a8083063 Iustin Pop
32 a8083063 Iustin Pop
from ganeti import utils
33 a8083063 Iustin Pop
from ganeti import errors
34 a8083063 Iustin Pop
from ganeti import constants
35 846baef9 Iustin Pop
from ganeti import opcodes
36 ceab32dd Iustin Pop
from ganeti import luxi
37 b33e986b Iustin Pop
from ganeti import ssconf
38 4331f6cd Michael Hanselmann
from ganeti import rpc
39 a8083063 Iustin Pop
40 c38c44ad Michael Hanselmann
from optparse import (OptionParser, TitledHelpFormatter,
41 38206f3c Iustin Pop
                      Option, OptionValueError)
42 a8083063 Iustin Pop
43 03298ebe Michael Hanselmann
44 4abc4f1e Iustin Pop
__all__ = [
45 4abc4f1e Iustin Pop
  # Command line options
46 e7e09483 Iustin Pop
  "ALLOCATABLE_OPT",
47 2d5e7ae1 Iustin Pop
  "ALL_OPT",
48 e00f7a05 Iustin Pop
  "AUTO_REPLACE_OPT",
49 087ed2ed Iustin Pop
  "BACKEND_OPT",
50 baef337d Iustin Pop
  "CLEANUP_OPT",
51 4abc4f1e Iustin Pop
  "CONFIRM_OPT",
52 e32df528 Iustin Pop
  "CP_SIZE_OPT",
53 4abc4f1e Iustin Pop
  "DEBUG_OPT",
54 a0c9776a Iustin Pop
  "DEBUG_SIMERR_OPT",
55 4b038a1e Iustin Pop
  "DISKIDX_OPT",
56 e3876ccb Iustin Pop
  "DISK_OPT",
57 4b038a1e Iustin Pop
  "DISK_TEMPLATE_OPT",
58 771734c9 Iustin Pop
  "DRAINED_OPT",
59 383a3591 Iustin Pop
  "ENABLED_HV_OPT",
60 14e9e7f3 Iustin Pop
  "ERROR_CODES_OPT",
61 4abc4f1e Iustin Pop
  "FIELDS_OPT",
62 4a25828c Iustin Pop
  "FILESTORE_DIR_OPT",
63 0f87c43e Iustin Pop
  "FILESTORE_DRIVER_OPT",
64 06073e85 Guido Trotter
  "FORCE_OPT",
65 06073e85 Guido Trotter
  "FORCE_VARIANT_OPT",
66 29392516 Iustin Pop
  "GLOBAL_FILEDIR_OPT",
67 073271f6 Iustin Pop
  "HVLIST_OPT",
68 48f212d7 Iustin Pop
  "HVOPTS_OPT",
69 236fd9c4 Iustin Pop
  "HYPERVISOR_OPT",
70 4eb62659 Iustin Pop
  "IALLOCATOR_OPT",
71 82a786d5 Iustin Pop
  "IGNORE_CONSIST_OPT",
72 b6e841a8 Iustin Pop
  "IGNORE_FAILURES_OPT",
73 ee3f9578 Iustin Pop
  "IGNORE_SECONDARIES_OPT",
74 05586c90 Iustin Pop
  "IGNORE_SIZE_OPT",
75 e3646f22 Iustin Pop
  "MAC_PREFIX_OPT",
76 29392516 Iustin Pop
  "MASTER_NETDEV_OPT",
77 771734c9 Iustin Pop
  "MC_OPT",
78 7d3a9fab Iustin Pop
  "NET_OPT",
79 a14db5ff Iustin Pop
  "NEW_SECONDARY_OPT",
80 4fbc93dd Iustin Pop
  "NIC_PARAMS_OPT",
81 7edc4637 Iustin Pop
  "NODE_LIST_OPT",
82 990b7886 Iustin Pop
  "NODE_PLACEMENT_OPT",
83 4abc4f1e Iustin Pop
  "NOHDR_OPT",
84 91e0748c Iustin Pop
  "NOIPCHECK_OPT",
85 831040bf Iustin Pop
  "NOLVM_STORAGE_OPT",
86 29392516 Iustin Pop
  "NOMODIFY_ETCHOSTS_OPT",
87 b989b9d9 Ken Wehr
  "NOMODIFY_SSH_SETUP_OPT",
88 26023ecd Iustin Pop
  "NONICS_OPT",
89 f2a0828c Iustin Pop
  "NONLIVE_OPT",
90 14e9e7f3 Iustin Pop
  "NONPLUS1_OPT",
91 44c44832 Iustin Pop
  "NOSHUTDOWN_OPT",
92 edeb878a Iustin Pop
  "NOSTART_OPT",
93 fcdde7f2 Iustin Pop
  "NOSSH_KEYCHECK_OPT",
94 58371861 Iustin Pop
  "NOVOTING_OPT",
95 3f75b4f3 Iustin Pop
  "NWSYNC_OPT",
96 a72d0a79 Iustin Pop
  "ON_PRIMARY_OPT",
97 feb09e6a Iustin Pop
  "ON_SECONDARY_OPT",
98 771734c9 Iustin Pop
  "OFFLINE_OPT",
99 d3ed23ff Iustin Pop
  "OS_OPT",
100 ff00c1a7 Iustin Pop
  "OS_SIZE_OPT",
101 b8d0f938 Iustin Pop
  "READD_OPT",
102 12054861 Iustin Pop
  "REBOOT_TYPE_OPT",
103 8d823629 Iustin Pop
  "SECONDARY_IP_OPT",
104 67840b40 Iustin Pop
  "SELECT_OS_OPT",
105 4abc4f1e Iustin Pop
  "SEP_OPT",
106 fdcf4d84 Iustin Pop
  "SHOWCMD_OPT",
107 7e5eaaa8 Guido Trotter
  "SHUTDOWN_TIMEOUT_OPT",
108 f36d7d81 Iustin Pop
  "SINGLE_NODE_OPT",
109 df62e5db Iustin Pop
  "SRC_DIR_OPT",
110 df62e5db Iustin Pop
  "SRC_NODE_OPT",
111 4abc4f1e Iustin Pop
  "SUBMIT_OPT",
112 99a8c799 Iustin Pop
  "STATIC_OPT",
113 4abc4f1e Iustin Pop
  "SYNC_OPT",
114 4abc4f1e Iustin Pop
  "TAG_SRC_OPT",
115 b5762e2a Guido Trotter
  "TIMEOUT_OPT",
116 4abc4f1e Iustin Pop
  "USEUNITS_OPT",
117 9cdb9578 Iustin Pop
  "VERBOSE_OPT",
118 b58726e8 Iustin Pop
  "VG_NAME_OPT",
119 1f587d3d Iustin Pop
  "YES_DOIT_OPT",
120 4abc4f1e Iustin Pop
  # Generic functions for CLI programs
121 4abc4f1e Iustin Pop
  "GenericMain",
122 d77490c5 Iustin Pop
  "GenericInstanceCreate",
123 4abc4f1e Iustin Pop
  "GetClient",
124 4abc4f1e Iustin Pop
  "GetOnlineNodes",
125 4abc4f1e Iustin Pop
  "JobExecutor",
126 4abc4f1e Iustin Pop
  "JobSubmittedException",
127 4abc4f1e Iustin Pop
  "ParseTimespec",
128 4abc4f1e Iustin Pop
  "SubmitOpCode",
129 4abc4f1e Iustin Pop
  "SubmitOrSend",
130 4abc4f1e Iustin Pop
  "UsesRPC",
131 4abc4f1e Iustin Pop
  # Formatting functions
132 4abc4f1e Iustin Pop
  "ToStderr", "ToStdout",
133 4abc4f1e Iustin Pop
  "FormatError",
134 4abc4f1e Iustin Pop
  "GenerateTable",
135 4abc4f1e Iustin Pop
  "AskUser",
136 4abc4f1e Iustin Pop
  "FormatTimestamp",
137 4abc4f1e Iustin Pop
  # Tags functions
138 4abc4f1e Iustin Pop
  "ListTags",
139 4abc4f1e Iustin Pop
  "AddTags",
140 4abc4f1e Iustin Pop
  "RemoveTags",
141 4abc4f1e Iustin Pop
  # command line options support infrastructure
142 4abc4f1e Iustin Pop
  "ARGS_MANY_INSTANCES",
143 4abc4f1e Iustin Pop
  "ARGS_MANY_NODES",
144 4abc4f1e Iustin Pop
  "ARGS_NONE",
145 4abc4f1e Iustin Pop
  "ARGS_ONE_INSTANCE",
146 4abc4f1e Iustin Pop
  "ARGS_ONE_NODE",
147 4abc4f1e Iustin Pop
  "ArgChoice",
148 4abc4f1e Iustin Pop
  "ArgCommand",
149 4abc4f1e Iustin Pop
  "ArgFile",
150 4abc4f1e Iustin Pop
  "ArgHost",
151 4abc4f1e Iustin Pop
  "ArgInstance",
152 4abc4f1e Iustin Pop
  "ArgJobId",
153 4abc4f1e Iustin Pop
  "ArgNode",
154 4abc4f1e Iustin Pop
  "ArgSuggest",
155 4abc4f1e Iustin Pop
  "ArgUnknown",
156 4abc4f1e Iustin Pop
  "OPT_COMPL_INST_ADD_NODES",
157 4abc4f1e Iustin Pop
  "OPT_COMPL_MANY_NODES",
158 4abc4f1e Iustin Pop
  "OPT_COMPL_ONE_IALLOCATOR",
159 4abc4f1e Iustin Pop
  "OPT_COMPL_ONE_INSTANCE",
160 4abc4f1e Iustin Pop
  "OPT_COMPL_ONE_NODE",
161 4abc4f1e Iustin Pop
  "OPT_COMPL_ONE_OS",
162 4abc4f1e Iustin Pop
  "cli_option",
163 4abc4f1e Iustin Pop
  "SplitNodeOption",
164 07150497 Guido Trotter
  "CalculateOSNames",
165 4abc4f1e Iustin Pop
  ]
166 846baef9 Iustin Pop
167 8b46606c Guido Trotter
NO_PREFIX = "no_"
168 8b46606c Guido Trotter
UN_PREFIX = "-"
169 846baef9 Iustin Pop
170 03298ebe Michael Hanselmann
171 863d7f46 Michael Hanselmann
class _Argument:
172 dff85078 Michael Hanselmann
  def __init__(self, min=0, max=None):
173 863d7f46 Michael Hanselmann
    self.min = min
174 863d7f46 Michael Hanselmann
    self.max = max
175 863d7f46 Michael Hanselmann
176 863d7f46 Michael Hanselmann
  def __repr__(self):
177 863d7f46 Michael Hanselmann
    return ("<%s min=%s max=%s>" %
178 863d7f46 Michael Hanselmann
            (self.__class__.__name__, self.min, self.max))
179 863d7f46 Michael Hanselmann
180 863d7f46 Michael Hanselmann
181 863d7f46 Michael Hanselmann
class ArgSuggest(_Argument):
182 863d7f46 Michael Hanselmann
  """Suggesting argument.
183 863d7f46 Michael Hanselmann

184 863d7f46 Michael Hanselmann
  Value can be any of the ones passed to the constructor.
185 863d7f46 Michael Hanselmann

186 863d7f46 Michael Hanselmann
  """
187 863d7f46 Michael Hanselmann
  def __init__(self, min=0, max=None, choices=None):
188 863d7f46 Michael Hanselmann
    _Argument.__init__(self, min=min, max=max)
189 863d7f46 Michael Hanselmann
    self.choices = choices
190 863d7f46 Michael Hanselmann
191 863d7f46 Michael Hanselmann
  def __repr__(self):
192 863d7f46 Michael Hanselmann
    return ("<%s min=%s max=%s choices=%r>" %
193 863d7f46 Michael Hanselmann
            (self.__class__.__name__, self.min, self.max, self.choices))
194 863d7f46 Michael Hanselmann
195 863d7f46 Michael Hanselmann
196 863d7f46 Michael Hanselmann
class ArgChoice(ArgSuggest):
197 863d7f46 Michael Hanselmann
  """Choice argument.
198 863d7f46 Michael Hanselmann

199 863d7f46 Michael Hanselmann
  Value can be any of the ones passed to the constructor. Like L{ArgSuggest},
200 863d7f46 Michael Hanselmann
  but value must be one of the choices.
201 863d7f46 Michael Hanselmann

202 863d7f46 Michael Hanselmann
  """
203 863d7f46 Michael Hanselmann
204 863d7f46 Michael Hanselmann
205 863d7f46 Michael Hanselmann
class ArgUnknown(_Argument):
206 863d7f46 Michael Hanselmann
  """Unknown argument to program (e.g. determined at runtime).
207 863d7f46 Michael Hanselmann

208 863d7f46 Michael Hanselmann
  """
209 863d7f46 Michael Hanselmann
210 863d7f46 Michael Hanselmann
211 863d7f46 Michael Hanselmann
class ArgInstance(_Argument):
212 863d7f46 Michael Hanselmann
  """Instances argument.
213 863d7f46 Michael Hanselmann

214 863d7f46 Michael Hanselmann
  """
215 863d7f46 Michael Hanselmann
216 863d7f46 Michael Hanselmann
217 863d7f46 Michael Hanselmann
class ArgNode(_Argument):
218 863d7f46 Michael Hanselmann
  """Node argument.
219 863d7f46 Michael Hanselmann

220 863d7f46 Michael Hanselmann
  """
221 863d7f46 Michael Hanselmann
222 863d7f46 Michael Hanselmann
class ArgJobId(_Argument):
223 863d7f46 Michael Hanselmann
  """Job ID argument.
224 863d7f46 Michael Hanselmann

225 863d7f46 Michael Hanselmann
  """
226 863d7f46 Michael Hanselmann
227 863d7f46 Michael Hanselmann
228 863d7f46 Michael Hanselmann
class ArgFile(_Argument):
229 863d7f46 Michael Hanselmann
  """File path argument.
230 863d7f46 Michael Hanselmann

231 863d7f46 Michael Hanselmann
  """
232 863d7f46 Michael Hanselmann
233 863d7f46 Michael Hanselmann
234 863d7f46 Michael Hanselmann
class ArgCommand(_Argument):
235 863d7f46 Michael Hanselmann
  """Command argument.
236 863d7f46 Michael Hanselmann

237 863d7f46 Michael Hanselmann
  """
238 863d7f46 Michael Hanselmann
239 863d7f46 Michael Hanselmann
240 83ec7961 Michael Hanselmann
class ArgHost(_Argument):
241 83ec7961 Michael Hanselmann
  """Host argument.
242 83ec7961 Michael Hanselmann

243 83ec7961 Michael Hanselmann
  """
244 83ec7961 Michael Hanselmann
245 83ec7961 Michael Hanselmann
246 4a265c08 Michael Hanselmann
ARGS_NONE = []
247 4a265c08 Michael Hanselmann
ARGS_MANY_INSTANCES = [ArgInstance()]
248 4a265c08 Michael Hanselmann
ARGS_MANY_NODES = [ArgNode()]
249 4a265c08 Michael Hanselmann
ARGS_ONE_INSTANCE = [ArgInstance(min=1, max=1)]
250 4a265c08 Michael Hanselmann
ARGS_ONE_NODE = [ArgNode(min=1, max=1)]
251 4a265c08 Michael Hanselmann
252 4a265c08 Michael Hanselmann
253 73b90123 Michael Hanselmann
254 846baef9 Iustin Pop
def _ExtractTagsObject(opts, args):
255 846baef9 Iustin Pop
  """Extract the tag type object.
256 846baef9 Iustin Pop

257 846baef9 Iustin Pop
  Note that this function will modify its args parameter.
258 846baef9 Iustin Pop

259 846baef9 Iustin Pop
  """
260 846baef9 Iustin Pop
  if not hasattr(opts, "tag_type"):
261 846baef9 Iustin Pop
    raise errors.ProgrammerError("tag_type not passed to _ExtractTagsObject")
262 846baef9 Iustin Pop
  kind = opts.tag_type
263 846baef9 Iustin Pop
  if kind == constants.TAG_CLUSTER:
264 846baef9 Iustin Pop
    retval = kind, kind
265 846baef9 Iustin Pop
  elif kind == constants.TAG_NODE or kind == constants.TAG_INSTANCE:
266 846baef9 Iustin Pop
    if not args:
267 0c434948 Iustin Pop
      raise errors.OpPrereqError("no arguments passed to the command")
268 846baef9 Iustin Pop
    name = args.pop(0)
269 846baef9 Iustin Pop
    retval = kind, name
270 846baef9 Iustin Pop
  else:
271 846baef9 Iustin Pop
    raise errors.ProgrammerError("Unhandled tag type '%s'" % kind)
272 846baef9 Iustin Pop
  return retval
273 846baef9 Iustin Pop
274 846baef9 Iustin Pop
275 810c50b7 Iustin Pop
def _ExtendTags(opts, args):
276 810c50b7 Iustin Pop
  """Extend the args if a source file has been given.
277 810c50b7 Iustin Pop

278 810c50b7 Iustin Pop
  This function will extend the tags with the contents of the file
279 810c50b7 Iustin Pop
  passed in the 'tags_source' attribute of the opts parameter. A file
280 810c50b7 Iustin Pop
  named '-' will be replaced by stdin.
281 810c50b7 Iustin Pop

282 810c50b7 Iustin Pop
  """
283 810c50b7 Iustin Pop
  fname = opts.tags_source
284 810c50b7 Iustin Pop
  if fname is None:
285 810c50b7 Iustin Pop
    return
286 810c50b7 Iustin Pop
  if fname == "-":
287 810c50b7 Iustin Pop
    new_fh = sys.stdin
288 810c50b7 Iustin Pop
  else:
289 810c50b7 Iustin Pop
    new_fh = open(fname, "r")
290 810c50b7 Iustin Pop
  new_data = []
291 810c50b7 Iustin Pop
  try:
292 810c50b7 Iustin Pop
    # we don't use the nice 'new_data = [line.strip() for line in fh]'
293 810c50b7 Iustin Pop
    # because of python bug 1633941
294 810c50b7 Iustin Pop
    while True:
295 810c50b7 Iustin Pop
      line = new_fh.readline()
296 810c50b7 Iustin Pop
      if not line:
297 810c50b7 Iustin Pop
        break
298 810c50b7 Iustin Pop
      new_data.append(line.strip())
299 810c50b7 Iustin Pop
  finally:
300 810c50b7 Iustin Pop
    new_fh.close()
301 810c50b7 Iustin Pop
  args.extend(new_data)
302 810c50b7 Iustin Pop
303 810c50b7 Iustin Pop
304 846baef9 Iustin Pop
def ListTags(opts, args):
305 846baef9 Iustin Pop
  """List the tags on a given object.
306 846baef9 Iustin Pop

307 846baef9 Iustin Pop
  This is a generic implementation that knows how to deal with all
308 846baef9 Iustin Pop
  three cases of tag objects (cluster, node, instance). The opts
309 846baef9 Iustin Pop
  argument is expected to contain a tag_type field denoting what
310 846baef9 Iustin Pop
  object type we work on.
311 846baef9 Iustin Pop

312 846baef9 Iustin Pop
  """
313 846baef9 Iustin Pop
  kind, name = _ExtractTagsObject(opts, args)
314 846baef9 Iustin Pop
  op = opcodes.OpGetTags(kind=kind, name=name)
315 846baef9 Iustin Pop
  result = SubmitOpCode(op)
316 846baef9 Iustin Pop
  result = list(result)
317 846baef9 Iustin Pop
  result.sort()
318 846baef9 Iustin Pop
  for tag in result:
319 03298ebe Michael Hanselmann
    ToStdout(tag)
320 846baef9 Iustin Pop
321 846baef9 Iustin Pop
322 846baef9 Iustin Pop
def AddTags(opts, args):
323 846baef9 Iustin Pop
  """Add tags on a given object.
324 846baef9 Iustin Pop

325 846baef9 Iustin Pop
  This is a generic implementation that knows how to deal with all
326 846baef9 Iustin Pop
  three cases of tag objects (cluster, node, instance). The opts
327 846baef9 Iustin Pop
  argument is expected to contain a tag_type field denoting what
328 846baef9 Iustin Pop
  object type we work on.
329 846baef9 Iustin Pop

330 846baef9 Iustin Pop
  """
331 846baef9 Iustin Pop
  kind, name = _ExtractTagsObject(opts, args)
332 810c50b7 Iustin Pop
  _ExtendTags(opts, args)
333 846baef9 Iustin Pop
  if not args:
334 846baef9 Iustin Pop
    raise errors.OpPrereqError("No tags to be added")
335 846baef9 Iustin Pop
  op = opcodes.OpAddTags(kind=kind, name=name, tags=args)
336 846baef9 Iustin Pop
  SubmitOpCode(op)
337 846baef9 Iustin Pop
338 846baef9 Iustin Pop
339 846baef9 Iustin Pop
def RemoveTags(opts, args):
340 846baef9 Iustin Pop
  """Remove tags from a given object.
341 846baef9 Iustin Pop

342 846baef9 Iustin Pop
  This is a generic implementation that knows how to deal with all
343 846baef9 Iustin Pop
  three cases of tag objects (cluster, node, instance). The opts
344 846baef9 Iustin Pop
  argument is expected to contain a tag_type field denoting what
345 846baef9 Iustin Pop
  object type we work on.
346 846baef9 Iustin Pop

347 846baef9 Iustin Pop
  """
348 846baef9 Iustin Pop
  kind, name = _ExtractTagsObject(opts, args)
349 810c50b7 Iustin Pop
  _ExtendTags(opts, args)
350 846baef9 Iustin Pop
  if not args:
351 846baef9 Iustin Pop
    raise errors.OpPrereqError("No tags to be removed")
352 846baef9 Iustin Pop
  op = opcodes.OpDelTags(kind=kind, name=name, tags=args)
353 846baef9 Iustin Pop
  SubmitOpCode(op)
354 846baef9 Iustin Pop
355 a8083063 Iustin Pop
356 a8083063 Iustin Pop
def check_unit(option, opt, value):
357 65fe4693 Iustin Pop
  """OptParsers custom converter for units.
358 65fe4693 Iustin Pop

359 65fe4693 Iustin Pop
  """
360 a8083063 Iustin Pop
  try:
361 a8083063 Iustin Pop
    return utils.ParseUnit(value)
362 a8083063 Iustin Pop
  except errors.UnitParseError, err:
363 3ecf6786 Iustin Pop
    raise OptionValueError("option %s: %s" % (opt, err))
364 a8083063 Iustin Pop
365 a8083063 Iustin Pop
366 a8469393 Iustin Pop
def _SplitKeyVal(opt, data):
367 a8469393 Iustin Pop
  """Convert a KeyVal string into a dict.
368 a8469393 Iustin Pop

369 a8469393 Iustin Pop
  This function will convert a key=val[,...] string into a dict. Empty
370 a8469393 Iustin Pop
  values will be converted specially: keys which have the prefix 'no_'
371 a8469393 Iustin Pop
  will have the value=False and the prefix stripped, the others will
372 a8469393 Iustin Pop
  have value=True.
373 a8469393 Iustin Pop

374 a8469393 Iustin Pop
  @type opt: string
375 a8469393 Iustin Pop
  @param opt: a string holding the option name for which we process the
376 a8469393 Iustin Pop
      data, used in building error messages
377 a8469393 Iustin Pop
  @type data: string
378 a8469393 Iustin Pop
  @param data: a string of the format key=val,key=val,...
379 a8469393 Iustin Pop
  @rtype: dict
380 a8469393 Iustin Pop
  @return: {key=val, key=val}
381 a8469393 Iustin Pop
  @raises errors.ParameterError: if there are duplicate keys
382 a8469393 Iustin Pop

383 a8469393 Iustin Pop
  """
384 a8469393 Iustin Pop
  kv_dict = {}
385 4f31882e Guido Trotter
  if data:
386 4f31882e Guido Trotter
    for elem in data.split(","):
387 4f31882e Guido Trotter
      if "=" in elem:
388 4f31882e Guido Trotter
        key, val = elem.split("=", 1)
389 a8469393 Iustin Pop
      else:
390 4f31882e Guido Trotter
        if elem.startswith(NO_PREFIX):
391 4f31882e Guido Trotter
          key, val = elem[len(NO_PREFIX):], False
392 4f31882e Guido Trotter
        elif elem.startswith(UN_PREFIX):
393 4f31882e Guido Trotter
          key, val = elem[len(UN_PREFIX):], None
394 4f31882e Guido Trotter
        else:
395 4f31882e Guido Trotter
          key, val = elem, True
396 4f31882e Guido Trotter
      if key in kv_dict:
397 4f31882e Guido Trotter
        raise errors.ParameterError("Duplicate key '%s' in option %s" %
398 4f31882e Guido Trotter
                                    (key, opt))
399 4f31882e Guido Trotter
      kv_dict[key] = val
400 a8469393 Iustin Pop
  return kv_dict
401 a8469393 Iustin Pop
402 a8469393 Iustin Pop
403 a8469393 Iustin Pop
def check_ident_key_val(option, opt, value):
404 552c8dff Michael Hanselmann
  """Custom parser for ident:key=val,key=val options.
405 552c8dff Michael Hanselmann

406 552c8dff Michael Hanselmann
  This will store the parsed values as a tuple (ident, {key: val}). As such,
407 552c8dff Michael Hanselmann
  multiple uses of this option via action=append is possible.
408 a8469393 Iustin Pop

409 a8469393 Iustin Pop
  """
410 a8469393 Iustin Pop
  if ":" not in value:
411 8b46606c Guido Trotter
    ident, rest = value, ''
412 a8469393 Iustin Pop
  else:
413 a8469393 Iustin Pop
    ident, rest = value.split(":", 1)
414 8b46606c Guido Trotter
415 8b46606c Guido Trotter
  if ident.startswith(NO_PREFIX):
416 8b46606c Guido Trotter
    if rest:
417 8b46606c Guido Trotter
      msg = "Cannot pass options when removing parameter groups: %s" % value
418 8b46606c Guido Trotter
      raise errors.ParameterError(msg)
419 8b46606c Guido Trotter
    retval = (ident[len(NO_PREFIX):], False)
420 8b46606c Guido Trotter
  elif ident.startswith(UN_PREFIX):
421 8b46606c Guido Trotter
    if rest:
422 8b46606c Guido Trotter
      msg = "Cannot pass options when removing parameter groups: %s" % value
423 8b46606c Guido Trotter
      raise errors.ParameterError(msg)
424 8b46606c Guido Trotter
    retval = (ident[len(UN_PREFIX):], None)
425 8b46606c Guido Trotter
  else:
426 a8469393 Iustin Pop
    kv_dict = _SplitKeyVal(opt, rest)
427 a8469393 Iustin Pop
    retval = (ident, kv_dict)
428 a8469393 Iustin Pop
  return retval
429 a8469393 Iustin Pop
430 a8469393 Iustin Pop
431 a8469393 Iustin Pop
def check_key_val(option, opt, value):
432 552c8dff Michael Hanselmann
  """Custom parser class for key=val,key=val options.
433 552c8dff Michael Hanselmann

434 552c8dff Michael Hanselmann
  This will store the parsed values as a dict {key: val}.
435 a8469393 Iustin Pop

436 a8469393 Iustin Pop
  """
437 a8469393 Iustin Pop
  return _SplitKeyVal(opt, value)
438 a8469393 Iustin Pop
439 a8469393 Iustin Pop
440 63d44c55 Michael Hanselmann
# completion_suggestion is normally a list. Using numeric values not evaluating
441 63d44c55 Michael Hanselmann
# to False for dynamic completion.
442 63d44c55 Michael Hanselmann
(OPT_COMPL_MANY_NODES,
443 63d44c55 Michael Hanselmann
 OPT_COMPL_ONE_NODE,
444 63d44c55 Michael Hanselmann
 OPT_COMPL_ONE_INSTANCE,
445 63d44c55 Michael Hanselmann
 OPT_COMPL_ONE_OS,
446 2d3ed64b Michael Hanselmann
 OPT_COMPL_ONE_IALLOCATOR,
447 2d3ed64b Michael Hanselmann
 OPT_COMPL_INST_ADD_NODES) = range(100, 106)
448 63d44c55 Michael Hanselmann
449 63d44c55 Michael Hanselmann
OPT_COMPL_ALL = frozenset([
450 63d44c55 Michael Hanselmann
  OPT_COMPL_MANY_NODES,
451 63d44c55 Michael Hanselmann
  OPT_COMPL_ONE_NODE,
452 63d44c55 Michael Hanselmann
  OPT_COMPL_ONE_INSTANCE,
453 63d44c55 Michael Hanselmann
  OPT_COMPL_ONE_OS,
454 63d44c55 Michael Hanselmann
  OPT_COMPL_ONE_IALLOCATOR,
455 2d3ed64b Michael Hanselmann
  OPT_COMPL_INST_ADD_NODES,
456 63d44c55 Michael Hanselmann
  ])
457 63d44c55 Michael Hanselmann
458 63d44c55 Michael Hanselmann
459 552c8dff Michael Hanselmann
class CliOption(Option):
460 552c8dff Michael Hanselmann
  """Custom option class for optparse.
461 a8469393 Iustin Pop

462 a8469393 Iustin Pop
  """
463 863d7f46 Michael Hanselmann
  ATTRS = Option.ATTRS + [
464 863d7f46 Michael Hanselmann
    "completion_suggest",
465 863d7f46 Michael Hanselmann
    ]
466 552c8dff Michael Hanselmann
  TYPES = Option.TYPES + (
467 552c8dff Michael Hanselmann
    "identkeyval",
468 552c8dff Michael Hanselmann
    "keyval",
469 552c8dff Michael Hanselmann
    "unit",
470 552c8dff Michael Hanselmann
    )
471 552c8dff Michael Hanselmann
  TYPE_CHECKER = Option.TYPE_CHECKER.copy()
472 552c8dff Michael Hanselmann
  TYPE_CHECKER["identkeyval"] = check_ident_key_val
473 a8469393 Iustin Pop
  TYPE_CHECKER["keyval"] = check_key_val
474 552c8dff Michael Hanselmann
  TYPE_CHECKER["unit"] = check_unit
475 a8469393 Iustin Pop
476 a8469393 Iustin Pop
477 a8083063 Iustin Pop
# optparse.py sets make_option, so we do it for our own option class, too
478 a8083063 Iustin Pop
cli_option = CliOption
479 a8083063 Iustin Pop
480 a8083063 Iustin Pop
481 771734c9 Iustin Pop
_YESNO = ("yes", "no")
482 771734c9 Iustin Pop
_YORNO = "yes|no"
483 771734c9 Iustin Pop
484 c38c44ad Michael Hanselmann
DEBUG_OPT = cli_option("-d", "--debug", default=False,
485 c38c44ad Michael Hanselmann
                       action="store_true",
486 c38c44ad Michael Hanselmann
                       help="Turn debugging on")
487 c38c44ad Michael Hanselmann
488 c38c44ad Michael Hanselmann
NOHDR_OPT = cli_option("--no-headers", default=False,
489 c38c44ad Michael Hanselmann
                       action="store_true", dest="no_headers",
490 c38c44ad Michael Hanselmann
                       help="Don't display column headers")
491 c38c44ad Michael Hanselmann
492 c38c44ad Michael Hanselmann
SEP_OPT = cli_option("--separator", default=None,
493 c38c44ad Michael Hanselmann
                     action="store", dest="separator",
494 c38c44ad Michael Hanselmann
                     help=("Separator between output fields"
495 c38c44ad Michael Hanselmann
                           " (defaults to one space)"))
496 c38c44ad Michael Hanselmann
497 c38c44ad Michael Hanselmann
USEUNITS_OPT = cli_option("--units", default=None,
498 c38c44ad Michael Hanselmann
                          dest="units", choices=('h', 'm', 'g', 't'),
499 c38c44ad Michael Hanselmann
                          help="Specify units for output (one of hmgt)")
500 c38c44ad Michael Hanselmann
501 c38c44ad Michael Hanselmann
FIELDS_OPT = cli_option("-o", "--output", dest="output", action="store",
502 c38c44ad Michael Hanselmann
                        type="string", metavar="FIELDS",
503 c38c44ad Michael Hanselmann
                        help="Comma separated list of output fields")
504 c38c44ad Michael Hanselmann
505 c38c44ad Michael Hanselmann
FORCE_OPT = cli_option("-f", "--force", dest="force", action="store_true",
506 c38c44ad Michael Hanselmann
                       default=False, help="Force the operation")
507 c38c44ad Michael Hanselmann
508 c38c44ad Michael Hanselmann
CONFIRM_OPT = cli_option("--yes", dest="confirm", action="store_true",
509 c38c44ad Michael Hanselmann
                         default=False, help="Do not require confirmation")
510 c38c44ad Michael Hanselmann
511 c38c44ad Michael Hanselmann
TAG_SRC_OPT = cli_option("--from", dest="tags_source",
512 c38c44ad Michael Hanselmann
                         default=None, help="File with tag names")
513 c38c44ad Michael Hanselmann
514 c38c44ad Michael Hanselmann
SUBMIT_OPT = cli_option("--submit", dest="submit_only",
515 c38c44ad Michael Hanselmann
                        default=False, action="store_true",
516 c38c44ad Michael Hanselmann
                        help=("Submit the job and return the job ID, but"
517 c38c44ad Michael Hanselmann
                              " don't wait for the job to finish"))
518 c38c44ad Michael Hanselmann
519 c38c44ad Michael Hanselmann
SYNC_OPT = cli_option("--sync", dest="do_locking",
520 c38c44ad Michael Hanselmann
                      default=False, action="store_true",
521 c38c44ad Michael Hanselmann
                      help=("Grab locks while doing the queries"
522 c38c44ad Michael Hanselmann
                            " in order to ensure more consistent results"))
523 c38c44ad Michael Hanselmann
524 c38c44ad Michael Hanselmann
_DRY_RUN_OPT = cli_option("--dry-run", default=False,
525 c38c44ad Michael Hanselmann
                          action="store_true",
526 c38c44ad Michael Hanselmann
                          help=("Do not execute the operation, just run the"
527 c38c44ad Michael Hanselmann
                                " check steps and verify it it could be"
528 c38c44ad Michael Hanselmann
                                " executed"))
529 c38c44ad Michael Hanselmann
530 9cdb9578 Iustin Pop
VERBOSE_OPT = cli_option("-v", "--verbose", default=False,
531 9cdb9578 Iustin Pop
                         action="store_true",
532 9cdb9578 Iustin Pop
                         help="Increase the verbosity of the operation")
533 9cdb9578 Iustin Pop
534 a0c9776a Iustin Pop
DEBUG_SIMERR_OPT = cli_option("--debug-simulate-errors", default=False,
535 a0c9776a Iustin Pop
                              action="store_true", dest="simulate_errors",
536 a0c9776a Iustin Pop
                              help="Debugging option that makes the operation"
537 a0c9776a Iustin Pop
                              " treat most runtime checks as failed")
538 a0c9776a Iustin Pop
539 3f75b4f3 Iustin Pop
NWSYNC_OPT = cli_option("--no-wait-for-sync", dest="wait_for_sync",
540 3f75b4f3 Iustin Pop
                        default=True, action="store_false",
541 3f75b4f3 Iustin Pop
                        help="Don't wait for sync (DANGEROUS!)")
542 3f75b4f3 Iustin Pop
543 4f365444 Iustin Pop
DISK_TEMPLATE_OPT = cli_option("-t", "--disk-template", dest="disk_template",
544 4f365444 Iustin Pop
                               help="Custom disk setup (diskless, file,"
545 4f365444 Iustin Pop
                               " plain or drbd)",
546 4f365444 Iustin Pop
                               default=None, metavar="TEMPL",
547 4f365444 Iustin Pop
                               choices=list(constants.DISK_TEMPLATES))
548 4f365444 Iustin Pop
549 26023ecd Iustin Pop
NONICS_OPT = cli_option("--no-nics", default=False, action="store_true",
550 26023ecd Iustin Pop
                        help="Do not create any network cards for"
551 26023ecd Iustin Pop
                        " the instance")
552 26023ecd Iustin Pop
553 4a25828c Iustin Pop
FILESTORE_DIR_OPT = cli_option("--file-storage-dir", dest="file_storage_dir",
554 4a25828c Iustin Pop
                               help="Relative path under default cluster-wide"
555 4a25828c Iustin Pop
                               " file storage dir to store file-based disks",
556 4a25828c Iustin Pop
                               default=None, metavar="<DIR>")
557 4a25828c Iustin Pop
558 0f87c43e Iustin Pop
FILESTORE_DRIVER_OPT = cli_option("--file-driver", dest="file_driver",
559 0f87c43e Iustin Pop
                                  help="Driver to use for image files",
560 0f87c43e Iustin Pop
                                  default="loop", metavar="<DRIVER>",
561 0f87c43e Iustin Pop
                                  choices=list(constants.FILE_DRIVER))
562 0f87c43e Iustin Pop
563 4eb62659 Iustin Pop
IALLOCATOR_OPT = cli_option("-I", "--iallocator", metavar="<NAME>",
564 4eb62659 Iustin Pop
                            help="Select nodes for the instance automatically"
565 4eb62659 Iustin Pop
                            " using the <NAME> iallocator plugin",
566 4eb62659 Iustin Pop
                            default=None, type="string",
567 4eb62659 Iustin Pop
                            completion_suggest=OPT_COMPL_ONE_IALLOCATOR)
568 4eb62659 Iustin Pop
569 d3ed23ff Iustin Pop
OS_OPT = cli_option("-o", "--os-type", dest="os", help="What OS to run",
570 d3ed23ff Iustin Pop
                    metavar="<os>",
571 d3ed23ff Iustin Pop
                    completion_suggest=OPT_COMPL_ONE_OS)
572 d3ed23ff Iustin Pop
573 06073e85 Guido Trotter
FORCE_VARIANT_OPT = cli_option("--force-variant", dest="force_variant",
574 06073e85 Guido Trotter
                               action="store_true", default=False,
575 06073e85 Guido Trotter
                               help="Force an unknown variant")
576 06073e85 Guido Trotter
577 087ed2ed Iustin Pop
BACKEND_OPT = cli_option("-B", "--backend-parameters", dest="beparams",
578 087ed2ed Iustin Pop
                         type="keyval", default={},
579 087ed2ed Iustin Pop
                         help="Backend parameters")
580 48f212d7 Iustin Pop
581 48f212d7 Iustin Pop
HVOPTS_OPT =  cli_option("-H", "--hypervisor-parameters", type="keyval",
582 48f212d7 Iustin Pop
                         default={}, dest="hvparams",
583 48f212d7 Iustin Pop
                         help="Hypervisor parameters")
584 087ed2ed Iustin Pop
585 236fd9c4 Iustin Pop
HYPERVISOR_OPT = cli_option("-H", "--hypervisor-parameters", dest="hypervisor",
586 236fd9c4 Iustin Pop
                            help="Hypervisor and hypervisor options, in the"
587 236fd9c4 Iustin Pop
                            " format hypervisor:option=value,option=value,...",
588 236fd9c4 Iustin Pop
                            default=None, type="identkeyval")
589 073271f6 Iustin Pop
590 073271f6 Iustin Pop
HVLIST_OPT = cli_option("-H", "--hypervisor-parameters", dest="hvparams",
591 073271f6 Iustin Pop
                        help="Hypervisor and hypervisor options, in the"
592 073271f6 Iustin Pop
                        " format hypervisor:option=value,option=value,...",
593 073271f6 Iustin Pop
                        default=[], action="append", type="identkeyval")
594 236fd9c4 Iustin Pop
595 91e0748c Iustin Pop
NOIPCHECK_OPT = cli_option("--no-ip-check", dest="ip_check", default=True,
596 91e0748c Iustin Pop
                           action="store_false",
597 91e0748c Iustin Pop
                           help="Don't check that the instance's IP"
598 91e0748c Iustin Pop
                           " is alive")
599 91e0748c Iustin Pop
600 7d3a9fab Iustin Pop
NET_OPT = cli_option("--net",
601 7d3a9fab Iustin Pop
                     help="NIC parameters", default=[],
602 7d3a9fab Iustin Pop
                     dest="nics", action="append", type="identkeyval")
603 e3876ccb Iustin Pop
604 e3876ccb Iustin Pop
DISK_OPT = cli_option("--disk", help="Disk parameters", default=[],
605 e3876ccb Iustin Pop
                      dest="disks", action="append", type="identkeyval")
606 91e0748c Iustin Pop
607 4b038a1e Iustin Pop
DISKIDX_OPT = cli_option("--disks", dest="disks", default=None,
608 4b038a1e Iustin Pop
                         help="Comma-separated list of disks"
609 4b038a1e Iustin Pop
                         " indices to act on (e.g. 0,2) (optional,"
610 4b038a1e Iustin Pop
                         " defaults to all disks)")
611 4b038a1e Iustin Pop
612 ff00c1a7 Iustin Pop
OS_SIZE_OPT = cli_option("-s", "--os-size", dest="sd_size",
613 ff00c1a7 Iustin Pop
                         help="Enforces a single-disk configuration using the"
614 ff00c1a7 Iustin Pop
                         " given disk size, in MiB unless a suffix is used",
615 ff00c1a7 Iustin Pop
                         default=None, type="unit", metavar="<size>")
616 ff00c1a7 Iustin Pop
617 82a786d5 Iustin Pop
IGNORE_CONSIST_OPT = cli_option("--ignore-consistency",
618 82a786d5 Iustin Pop
                                dest="ignore_consistency",
619 82a786d5 Iustin Pop
                                action="store_true", default=False,
620 82a786d5 Iustin Pop
                                help="Ignore the consistency of the disks on"
621 82a786d5 Iustin Pop
                                " the secondary")
622 82a786d5 Iustin Pop
623 f2a0828c Iustin Pop
NONLIVE_OPT = cli_option("--non-live", dest="live",
624 f2a0828c Iustin Pop
                         default=True, action="store_false",
625 f2a0828c Iustin Pop
                         help="Do a non-live migration (this usually means"
626 f2a0828c Iustin Pop
                         " freeze the instance, save the state, transfer and"
627 f2a0828c Iustin Pop
                         " only then resume running on the secondary node)")
628 f2a0828c Iustin Pop
629 990b7886 Iustin Pop
NODE_PLACEMENT_OPT = cli_option("-n", "--node", dest="node",
630 990b7886 Iustin Pop
                                help="Target node and optional secondary node",
631 990b7886 Iustin Pop
                                metavar="<pnode>[:<snode>]",
632 990b7886 Iustin Pop
                                completion_suggest=OPT_COMPL_INST_ADD_NODES)
633 990b7886 Iustin Pop
634 7edc4637 Iustin Pop
NODE_LIST_OPT = cli_option("-n", "--node", dest="nodes", default=[],
635 7edc4637 Iustin Pop
                           action="append", metavar="<node>",
636 7edc4637 Iustin Pop
                           help="Use only this node (can be used multiple"
637 7edc4637 Iustin Pop
                           " times, if not given defaults to all nodes)",
638 7edc4637 Iustin Pop
                           completion_suggest=OPT_COMPL_ONE_NODE)
639 f36d7d81 Iustin Pop
640 f36d7d81 Iustin Pop
SINGLE_NODE_OPT = cli_option("-n", "--node", dest="node", help="Target node",
641 f36d7d81 Iustin Pop
                             metavar="<node>",
642 f36d7d81 Iustin Pop
                             completion_suggest=OPT_COMPL_ONE_NODE)
643 7edc4637 Iustin Pop
644 edeb878a Iustin Pop
NOSTART_OPT = cli_option("--no-start", dest="start", default=True,
645 edeb878a Iustin Pop
                         action="store_false",
646 edeb878a Iustin Pop
                         help="Don't start the instance after creation")
647 edeb878a Iustin Pop
648 fdcf4d84 Iustin Pop
SHOWCMD_OPT = cli_option("--show-cmd", dest="show_command",
649 fdcf4d84 Iustin Pop
                         action="store_true", default=False,
650 fdcf4d84 Iustin Pop
                         help="Show command instead of executing it")
651 fdcf4d84 Iustin Pop
652 baef337d Iustin Pop
CLEANUP_OPT = cli_option("--cleanup", dest="cleanup",
653 baef337d Iustin Pop
                         default=False, action="store_true",
654 baef337d Iustin Pop
                         help="Instead of performing the migration, try to"
655 baef337d Iustin Pop
                         " recover from a failed cleanup. This is safe"
656 baef337d Iustin Pop
                         " to run even if the instance is healthy, but it"
657 baef337d Iustin Pop
                         " will create extra replication traffic and "
658 baef337d Iustin Pop
                         " disrupt briefly the replication (like during the"
659 baef337d Iustin Pop
                         " migration")
660 baef337d Iustin Pop
661 99a8c799 Iustin Pop
STATIC_OPT = cli_option("-s", "--static", dest="static",
662 99a8c799 Iustin Pop
                        action="store_true", default=False,
663 99a8c799 Iustin Pop
                        help="Only show configuration data, not runtime data")
664 99a8c799 Iustin Pop
665 2d5e7ae1 Iustin Pop
ALL_OPT = cli_option("--all", dest="show_all",
666 2d5e7ae1 Iustin Pop
                     default=False, action="store_true",
667 2d5e7ae1 Iustin Pop
                     help="Show info on all instances on the cluster."
668 2d5e7ae1 Iustin Pop
                     " This can take a long time to run, use wisely")
669 2d5e7ae1 Iustin Pop
670 67840b40 Iustin Pop
SELECT_OS_OPT = cli_option("--select-os", dest="select_os",
671 67840b40 Iustin Pop
                           action="store_true", default=False,
672 67840b40 Iustin Pop
                           help="Interactive OS reinstall, lists available"
673 67840b40 Iustin Pop
                           " OS templates for selection")
674 2d5e7ae1 Iustin Pop
675 b6e841a8 Iustin Pop
IGNORE_FAILURES_OPT = cli_option("--ignore-failures", dest="ignore_failures",
676 b6e841a8 Iustin Pop
                                 action="store_true", default=False,
677 b6e841a8 Iustin Pop
                                 help="Remove the instance from the cluster"
678 b6e841a8 Iustin Pop
                                 " configuration even if there are failures"
679 b6e841a8 Iustin Pop
                                 " during the removal process")
680 b6e841a8 Iustin Pop
681 a14db5ff Iustin Pop
NEW_SECONDARY_OPT = cli_option("-n", "--new-secondary", dest="dst_node",
682 a14db5ff Iustin Pop
                               help="Specifies the new secondary node",
683 a14db5ff Iustin Pop
                               metavar="NODE", default=None,
684 a14db5ff Iustin Pop
                               completion_suggest=OPT_COMPL_ONE_NODE)
685 a14db5ff Iustin Pop
686 a72d0a79 Iustin Pop
ON_PRIMARY_OPT = cli_option("-p", "--on-primary", dest="on_primary",
687 a72d0a79 Iustin Pop
                            default=False, action="store_true",
688 a72d0a79 Iustin Pop
                            help="Replace the disk(s) on the primary"
689 a72d0a79 Iustin Pop
                            " node (only for the drbd template)")
690 feb09e6a Iustin Pop
691 feb09e6a Iustin Pop
ON_SECONDARY_OPT = cli_option("-s", "--on-secondary", dest="on_secondary",
692 feb09e6a Iustin Pop
                              default=False, action="store_true",
693 feb09e6a Iustin Pop
                              help="Replace the disk(s) on the secondary"
694 feb09e6a Iustin Pop
                              " node (only for the drbd template)")
695 e00f7a05 Iustin Pop
696 e00f7a05 Iustin Pop
AUTO_REPLACE_OPT = cli_option("-a", "--auto", dest="auto",
697 e00f7a05 Iustin Pop
                              default=False, action="store_true",
698 e00f7a05 Iustin Pop
                              help="Automatically replace faulty disks"
699 e00f7a05 Iustin Pop
                              " (only for the drbd template)")
700 a72d0a79 Iustin Pop
701 05586c90 Iustin Pop
IGNORE_SIZE_OPT = cli_option("--ignore-size", dest="ignore_size",
702 05586c90 Iustin Pop
                             default=False, action="store_true",
703 05586c90 Iustin Pop
                             help="Ignore current recorded size"
704 05586c90 Iustin Pop
                             " (useful for forcing activation when"
705 05586c90 Iustin Pop
                             " the recorded size is wrong)")
706 05586c90 Iustin Pop
707 df62e5db Iustin Pop
SRC_NODE_OPT = cli_option("--src-node", dest="src_node", help="Source node",
708 df62e5db Iustin Pop
                          metavar="<node>",
709 df62e5db Iustin Pop
                          completion_suggest=OPT_COMPL_ONE_NODE)
710 df62e5db Iustin Pop
711 df62e5db Iustin Pop
SRC_DIR_OPT = cli_option("--src-dir", dest="src_dir", help="Source directory",
712 df62e5db Iustin Pop
                         metavar="<dir>")
713 df62e5db Iustin Pop
714 8d823629 Iustin Pop
SECONDARY_IP_OPT = cli_option("-s", "--secondary-ip", dest="secondary_ip",
715 8d823629 Iustin Pop
                              help="Specify the secondary ip for the node",
716 8d823629 Iustin Pop
                              metavar="ADDRESS", default=None)
717 8d823629 Iustin Pop
718 b8d0f938 Iustin Pop
READD_OPT = cli_option("--readd", dest="readd",
719 b8d0f938 Iustin Pop
                       default=False, action="store_true",
720 b8d0f938 Iustin Pop
                       help="Readd old node after replacing it")
721 b8d0f938 Iustin Pop
722 fcdde7f2 Iustin Pop
NOSSH_KEYCHECK_OPT = cli_option("--no-ssh-key-check", dest="ssh_key_check",
723 fcdde7f2 Iustin Pop
                                default=True, action="store_false",
724 fcdde7f2 Iustin Pop
                                help="Disable SSH key fingerprint checking")
725 fcdde7f2 Iustin Pop
726 c38c44ad Michael Hanselmann
727 771734c9 Iustin Pop
MC_OPT = cli_option("-C", "--master-candidate", dest="master_candidate",
728 771734c9 Iustin Pop
                    choices=_YESNO, default=None, metavar=_YORNO,
729 771734c9 Iustin Pop
                    help="Set the master_candidate flag on the node")
730 771734c9 Iustin Pop
731 771734c9 Iustin Pop
OFFLINE_OPT = cli_option("-O", "--offline", dest="offline", metavar=_YORNO,
732 771734c9 Iustin Pop
                         choices=_YESNO, default=None,
733 771734c9 Iustin Pop
                         help="Set the offline flag on the node")
734 771734c9 Iustin Pop
735 771734c9 Iustin Pop
DRAINED_OPT = cli_option("-D", "--drained", dest="drained", metavar=_YORNO,
736 771734c9 Iustin Pop
                         choices=_YESNO, default=None,
737 771734c9 Iustin Pop
                         help="Set the drained flag on the node")
738 771734c9 Iustin Pop
739 e7e09483 Iustin Pop
ALLOCATABLE_OPT = cli_option("--allocatable", dest="allocatable",
740 e7e09483 Iustin Pop
                             choices=_YESNO, default=None, metavar=_YORNO,
741 e7e09483 Iustin Pop
                             help="Set the allocatable flag on a volume")
742 e7e09483 Iustin Pop
743 831040bf Iustin Pop
NOLVM_STORAGE_OPT = cli_option("--no-lvm-storage", dest="lvm_storage",
744 831040bf Iustin Pop
                               help="Disable support for lvm based instances"
745 831040bf Iustin Pop
                               " (cluster-wide)",
746 831040bf Iustin Pop
                               action="store_false", default=True)
747 831040bf Iustin Pop
748 383a3591 Iustin Pop
ENABLED_HV_OPT = cli_option("--enabled-hypervisors",
749 383a3591 Iustin Pop
                            dest="enabled_hypervisors",
750 383a3591 Iustin Pop
                            help="Comma-separated list of hypervisors",
751 383a3591 Iustin Pop
                            type="string", default=None)
752 383a3591 Iustin Pop
753 4fbc93dd Iustin Pop
NIC_PARAMS_OPT = cli_option("-N", "--nic-parameters", dest="nicparams",
754 4fbc93dd Iustin Pop
                            type="keyval", default={},
755 4fbc93dd Iustin Pop
                            help="NIC parameters")
756 4fbc93dd Iustin Pop
757 e32df528 Iustin Pop
CP_SIZE_OPT = cli_option("-C", "--candidate-pool-size", default=None,
758 e32df528 Iustin Pop
                         dest="candidate_pool_size", type="int",
759 e32df528 Iustin Pop
                         help="Set the candidate pool size")
760 e32df528 Iustin Pop
761 b58726e8 Iustin Pop
VG_NAME_OPT = cli_option("-g", "--vg-name", dest="vg_name",
762 b58726e8 Iustin Pop
                         help="Enables LVM and specifies the volume group"
763 b58726e8 Iustin Pop
                         " name (cluster-wide) for disk allocation [xenvg]",
764 b58726e8 Iustin Pop
                         metavar="VG", default=None)
765 b58726e8 Iustin Pop
766 1f587d3d Iustin Pop
YES_DOIT_OPT = cli_option("--yes-do-it", dest="yes_do_it",
767 1f587d3d Iustin Pop
                          help="Destroy cluster", action="store_true")
768 b58726e8 Iustin Pop
769 58371861 Iustin Pop
NOVOTING_OPT = cli_option("--no-voting", dest="no_voting",
770 58371861 Iustin Pop
                          help="Skip node agreement check (dangerous)",
771 58371861 Iustin Pop
                          action="store_true", default=False)
772 58371861 Iustin Pop
773 e3646f22 Iustin Pop
MAC_PREFIX_OPT = cli_option("-m", "--mac-prefix", dest="mac_prefix",
774 e3646f22 Iustin Pop
                            help="Specify the mac prefix for the instance IP"
775 e3646f22 Iustin Pop
                            " addresses, in the format XX:XX:XX",
776 e3646f22 Iustin Pop
                            metavar="PREFIX",
777 e3646f22 Iustin Pop
                            default=None)
778 e3646f22 Iustin Pop
779 29392516 Iustin Pop
MASTER_NETDEV_OPT = cli_option("--master-netdev", dest="master_netdev",
780 29392516 Iustin Pop
                               help="Specify the node interface (cluster-wide)"
781 29392516 Iustin Pop
                               " on which the master IP address will be added "
782 29392516 Iustin Pop
                               " [%s]" % constants.DEFAULT_BRIDGE,
783 29392516 Iustin Pop
                               metavar="NETDEV",
784 29392516 Iustin Pop
                               default=constants.DEFAULT_BRIDGE)
785 29392516 Iustin Pop
786 29392516 Iustin Pop
787 29392516 Iustin Pop
GLOBAL_FILEDIR_OPT = cli_option("--file-storage-dir", dest="file_storage_dir",
788 29392516 Iustin Pop
                                help="Specify the default directory (cluster-"
789 29392516 Iustin Pop
                                "wide) for storing the file-based disks [%s]" %
790 29392516 Iustin Pop
                                constants.DEFAULT_FILE_STORAGE_DIR,
791 29392516 Iustin Pop
                                metavar="DIR",
792 29392516 Iustin Pop
                                default=constants.DEFAULT_FILE_STORAGE_DIR)
793 29392516 Iustin Pop
794 29392516 Iustin Pop
NOMODIFY_ETCHOSTS_OPT = cli_option("--no-etc-hosts", dest="modify_etc_hosts",
795 29392516 Iustin Pop
                                   help="Don't modify /etc/hosts",
796 29392516 Iustin Pop
                                   action="store_false", default=True)
797 29392516 Iustin Pop
798 b989b9d9 Ken Wehr
NOMODIFY_SSH_SETUP_OPT = cli_option("--no-ssh-init", dest="modify_ssh_setup",
799 b989b9d9 Ken Wehr
                                    help="Don't initialize SSH keys",
800 b989b9d9 Ken Wehr
                                    action="store_false", default=True)
801 b989b9d9 Ken Wehr
802 14e9e7f3 Iustin Pop
ERROR_CODES_OPT = cli_option("--error-codes", dest="error_codes",
803 14e9e7f3 Iustin Pop
                             help="Enable parseable error messages",
804 14e9e7f3 Iustin Pop
                             action="store_true", default=False)
805 14e9e7f3 Iustin Pop
806 14e9e7f3 Iustin Pop
NONPLUS1_OPT = cli_option("--no-nplus1-mem", dest="skip_nplusone_mem",
807 14e9e7f3 Iustin Pop
                          help="Skip N+1 memory redundancy tests",
808 14e9e7f3 Iustin Pop
                          action="store_true", default=False)
809 14e9e7f3 Iustin Pop
810 12054861 Iustin Pop
REBOOT_TYPE_OPT = cli_option("-t", "--type", dest="reboot_type",
811 12054861 Iustin Pop
                             help="Type of reboot: soft/hard/full",
812 12054861 Iustin Pop
                             default=constants.INSTANCE_REBOOT_HARD,
813 12054861 Iustin Pop
                             metavar="<REBOOT>",
814 12054861 Iustin Pop
                             choices=list(constants.REBOOT_TYPES))
815 12054861 Iustin Pop
816 ee3f9578 Iustin Pop
IGNORE_SECONDARIES_OPT = cli_option("--ignore-secondaries",
817 ee3f9578 Iustin Pop
                                    dest="ignore_secondaries",
818 ee3f9578 Iustin Pop
                                    default=False, action="store_true",
819 ee3f9578 Iustin Pop
                                    help="Ignore errors from secondaries")
820 ee3f9578 Iustin Pop
821 69b99987 Michael Hanselmann
NOSHUTDOWN_OPT = cli_option("--noshutdown", dest="shutdown",
822 44c44832 Iustin Pop
                            action="store_false", default=True,
823 44c44832 Iustin Pop
                            help="Don't shutdown the instance (unsafe)")
824 44c44832 Iustin Pop
825 b5762e2a Guido Trotter
TIMEOUT_OPT = cli_option("--timeout", dest="timeout", type="int",
826 b5762e2a Guido Trotter
                         default=constants.DEFAULT_SHUTDOWN_TIMEOUT,
827 b5762e2a Guido Trotter
                         help="Maximum time to wait")
828 44c44832 Iustin Pop
829 4d98c565 Guido Trotter
SHUTDOWN_TIMEOUT_OPT = cli_option("--shutdown-timeout",
830 4d98c565 Guido Trotter
                         dest="shutdown_timeout", type="int",
831 7e5eaaa8 Guido Trotter
                         default=constants.DEFAULT_SHUTDOWN_TIMEOUT,
832 7e5eaaa8 Guido Trotter
                         help="Maximum time to wait for instance shutdown")
833 7e5eaaa8 Guido Trotter
834 771734c9 Iustin Pop
835 de47cf8f Guido Trotter
def _ParseArgs(argv, commands, aliases):
836 c41eea6e Iustin Pop
  """Parser for the command line arguments.
837 a8083063 Iustin Pop

838 5bbd3f7f Michael Hanselmann
  This function parses the arguments and returns the function which
839 c41eea6e Iustin Pop
  must be executed together with its (modified) arguments.
840 a8083063 Iustin Pop

841 c41eea6e Iustin Pop
  @param argv: the command line
842 c41eea6e Iustin Pop
  @param commands: dictionary with special contents, see the design
843 c41eea6e Iustin Pop
      doc for cmdline handling
844 c41eea6e Iustin Pop
  @param aliases: dictionary with command aliases {'alias': 'target, ...}
845 098c0958 Michael Hanselmann

846 a8083063 Iustin Pop
  """
847 a8083063 Iustin Pop
  if len(argv) == 0:
848 a8083063 Iustin Pop
    binary = "<command>"
849 a8083063 Iustin Pop
  else:
850 a8083063 Iustin Pop
    binary = argv[0].split("/")[-1]
851 a8083063 Iustin Pop
852 a8083063 Iustin Pop
  if len(argv) > 1 and argv[1] == "--version":
853 03298ebe Michael Hanselmann
    ToStdout("%s (ganeti) %s", binary, constants.RELEASE_VERSION)
854 a8083063 Iustin Pop
    # Quit right away. That way we don't have to care about this special
855 a8083063 Iustin Pop
    # argument. optparse.py does it the same.
856 a8083063 Iustin Pop
    sys.exit(0)
857 a8083063 Iustin Pop
858 de47cf8f Guido Trotter
  if len(argv) < 2 or not (argv[1] in commands or
859 70a35b6f Guido Trotter
                           argv[1] in aliases):
860 a8083063 Iustin Pop
    # let's do a nice thing
861 a8083063 Iustin Pop
    sortedcmds = commands.keys()
862 a8083063 Iustin Pop
    sortedcmds.sort()
863 03298ebe Michael Hanselmann
864 03298ebe Michael Hanselmann
    ToStdout("Usage: %s {command} [options...] [argument...]", binary)
865 03298ebe Michael Hanselmann
    ToStdout("%s <command> --help to see details, or man %s", binary, binary)
866 03298ebe Michael Hanselmann
    ToStdout("")
867 03298ebe Michael Hanselmann
868 a8083063 Iustin Pop
    # compute the max line length for cmd + usage
869 4e713df6 Iustin Pop
    mlen = max([len(" %s" % cmd) for cmd in commands])
870 a8083063 Iustin Pop
    mlen = min(60, mlen) # should not get here...
871 03298ebe Michael Hanselmann
872 a8083063 Iustin Pop
    # and format a nice command list
873 03298ebe Michael Hanselmann
    ToStdout("Commands:")
874 a8083063 Iustin Pop
    for cmd in sortedcmds:
875 4e713df6 Iustin Pop
      cmdstr = " %s" % (cmd,)
876 9a033156 Iustin Pop
      help_text = commands[cmd][4]
877 03298ebe Michael Hanselmann
      help_lines = textwrap.wrap(help_text, 79 - 3 - mlen)
878 03298ebe Michael Hanselmann
      ToStdout("%-*s - %s", mlen, cmdstr, help_lines.pop(0))
879 a8083063 Iustin Pop
      for line in help_lines:
880 03298ebe Michael Hanselmann
        ToStdout("%-*s   %s", mlen, "", line)
881 03298ebe Michael Hanselmann
882 03298ebe Michael Hanselmann
    ToStdout("")
883 03298ebe Michael Hanselmann
884 a8083063 Iustin Pop
    return None, None, None
885 de47cf8f Guido Trotter
886 de47cf8f Guido Trotter
  # get command, unalias it, and look it up in commands
887 a8083063 Iustin Pop
  cmd = argv.pop(1)
888 de47cf8f Guido Trotter
  if cmd in aliases:
889 de47cf8f Guido Trotter
    if cmd in commands:
890 de47cf8f Guido Trotter
      raise errors.ProgrammerError("Alias '%s' overrides an existing"
891 de47cf8f Guido Trotter
                                   " command" % cmd)
892 de47cf8f Guido Trotter
893 de47cf8f Guido Trotter
    if aliases[cmd] not in commands:
894 de47cf8f Guido Trotter
      raise errors.ProgrammerError("Alias '%s' maps to non-existing"
895 de47cf8f Guido Trotter
                                   " command '%s'" % (cmd, aliases[cmd]))
896 de47cf8f Guido Trotter
897 de47cf8f Guido Trotter
    cmd = aliases[cmd]
898 de47cf8f Guido Trotter
899 a8005e17 Michael Hanselmann
  func, args_def, parser_opts, usage, description = commands[cmd]
900 064c21f8 Iustin Pop
  parser = OptionParser(option_list=parser_opts + [_DRY_RUN_OPT, DEBUG_OPT],
901 a8083063 Iustin Pop
                        description=description,
902 a8083063 Iustin Pop
                        formatter=TitledHelpFormatter(),
903 a8083063 Iustin Pop
                        usage="%%prog %s %s" % (cmd, usage))
904 a8083063 Iustin Pop
  parser.disable_interspersed_args()
905 a8083063 Iustin Pop
  options, args = parser.parse_args()
906 a8005e17 Michael Hanselmann
907 a8005e17 Michael Hanselmann
  if not _CheckArguments(cmd, args_def, args):
908 a8083063 Iustin Pop
    return None, None, None
909 a8083063 Iustin Pop
910 a8083063 Iustin Pop
  return func, options, args
911 a8083063 Iustin Pop
912 a8083063 Iustin Pop
913 a8005e17 Michael Hanselmann
def _CheckArguments(cmd, args_def, args):
914 a8005e17 Michael Hanselmann
  """Verifies the arguments using the argument definition.
915 a8005e17 Michael Hanselmann

916 a8005e17 Michael Hanselmann
  Algorithm:
917 a8005e17 Michael Hanselmann

918 a8005e17 Michael Hanselmann
    1. Abort with error if values specified by user but none expected.
919 a8005e17 Michael Hanselmann

920 a8005e17 Michael Hanselmann
    1. For each argument in definition
921 a8005e17 Michael Hanselmann

922 a8005e17 Michael Hanselmann
      1. Keep running count of minimum number of values (min_count)
923 a8005e17 Michael Hanselmann
      1. Keep running count of maximum number of values (max_count)
924 a8005e17 Michael Hanselmann
      1. If it has an unlimited number of values
925 a8005e17 Michael Hanselmann

926 a8005e17 Michael Hanselmann
        1. Abort with error if it's not the last argument in the definition
927 a8005e17 Michael Hanselmann

928 a8005e17 Michael Hanselmann
    1. If last argument has limited number of values
929 a8005e17 Michael Hanselmann

930 a8005e17 Michael Hanselmann
      1. Abort with error if number of values doesn't match or is too large
931 a8005e17 Michael Hanselmann

932 a8005e17 Michael Hanselmann
    1. Abort with error if user didn't pass enough values (min_count)
933 a8005e17 Michael Hanselmann

934 a8005e17 Michael Hanselmann
  """
935 a8005e17 Michael Hanselmann
  if args and not args_def:
936 a8005e17 Michael Hanselmann
    ToStderr("Error: Command %s expects no arguments", cmd)
937 a8005e17 Michael Hanselmann
    return False
938 a8005e17 Michael Hanselmann
939 a8005e17 Michael Hanselmann
  min_count = None
940 a8005e17 Michael Hanselmann
  max_count = None
941 a8005e17 Michael Hanselmann
  check_max = None
942 a8005e17 Michael Hanselmann
943 a8005e17 Michael Hanselmann
  last_idx = len(args_def) - 1
944 a8005e17 Michael Hanselmann
945 a8005e17 Michael Hanselmann
  for idx, arg in enumerate(args_def):
946 a8005e17 Michael Hanselmann
    if min_count is None:
947 a8005e17 Michael Hanselmann
      min_count = arg.min
948 a8005e17 Michael Hanselmann
    elif arg.min is not None:
949 a8005e17 Michael Hanselmann
      min_count += arg.min
950 a8005e17 Michael Hanselmann
951 a8005e17 Michael Hanselmann
    if max_count is None:
952 a8005e17 Michael Hanselmann
      max_count = arg.max
953 a8005e17 Michael Hanselmann
    elif arg.max is not None:
954 a8005e17 Michael Hanselmann
      max_count += arg.max
955 a8005e17 Michael Hanselmann
956 a8005e17 Michael Hanselmann
    if idx == last_idx:
957 a8005e17 Michael Hanselmann
      check_max = (arg.max is not None)
958 a8005e17 Michael Hanselmann
959 a8005e17 Michael Hanselmann
    elif arg.max is None:
960 a8005e17 Michael Hanselmann
      raise errors.ProgrammerError("Only the last argument can have max=None")
961 a8005e17 Michael Hanselmann
962 a8005e17 Michael Hanselmann
  if check_max:
963 a8005e17 Michael Hanselmann
    # Command with exact number of arguments
964 a8005e17 Michael Hanselmann
    if (min_count is not None and max_count is not None and
965 a8005e17 Michael Hanselmann
        min_count == max_count and len(args) != min_count):
966 a8005e17 Michael Hanselmann
      ToStderr("Error: Command %s expects %d argument(s)", cmd, min_count)
967 a8005e17 Michael Hanselmann
      return False
968 a8005e17 Michael Hanselmann
969 a8005e17 Michael Hanselmann
    # Command with limited number of arguments
970 a8005e17 Michael Hanselmann
    if max_count is not None and len(args) > max_count:
971 a8005e17 Michael Hanselmann
      ToStderr("Error: Command %s expects only %d argument(s)",
972 a8005e17 Michael Hanselmann
               cmd, max_count)
973 a8005e17 Michael Hanselmann
      return False
974 a8005e17 Michael Hanselmann
975 a8005e17 Michael Hanselmann
  # Command with some required arguments
976 a8005e17 Michael Hanselmann
  if min_count is not None and len(args) < min_count:
977 a8005e17 Michael Hanselmann
    ToStderr("Error: Command %s expects at least %d argument(s)",
978 a8005e17 Michael Hanselmann
             cmd, min_count)
979 a8005e17 Michael Hanselmann
    return False
980 a8005e17 Michael Hanselmann
981 a8005e17 Michael Hanselmann
  return True
982 a8005e17 Michael Hanselmann
983 a8005e17 Michael Hanselmann
984 60d49723 Michael Hanselmann
def SplitNodeOption(value):
985 60d49723 Michael Hanselmann
  """Splits the value of a --node option.
986 60d49723 Michael Hanselmann

987 60d49723 Michael Hanselmann
  """
988 60d49723 Michael Hanselmann
  if value and ':' in value:
989 60d49723 Michael Hanselmann
    return value.split(':', 1)
990 60d49723 Michael Hanselmann
  else:
991 60d49723 Michael Hanselmann
    return (value, None)
992 60d49723 Michael Hanselmann
993 60d49723 Michael Hanselmann
994 07150497 Guido Trotter
def CalculateOSNames(os_name, os_variants):
995 07150497 Guido Trotter
  """Calculates all the names an OS can be called, according to its variants.
996 07150497 Guido Trotter

997 07150497 Guido Trotter
  @type os_name: string
998 07150497 Guido Trotter
  @param os_name: base name of the os
999 07150497 Guido Trotter
  @type os_variants: list or None
1000 07150497 Guido Trotter
  @param os_variants: list of supported variants
1001 07150497 Guido Trotter
  @rtype: list
1002 07150497 Guido Trotter
  @return: list of valid names
1003 07150497 Guido Trotter

1004 07150497 Guido Trotter
  """
1005 07150497 Guido Trotter
  if os_variants:
1006 07150497 Guido Trotter
    return ['%s+%s' % (os_name, v) for v in os_variants]
1007 07150497 Guido Trotter
  else:
1008 07150497 Guido Trotter
    return [os_name]
1009 07150497 Guido Trotter
1010 07150497 Guido Trotter
1011 4331f6cd Michael Hanselmann
def UsesRPC(fn):
1012 4331f6cd Michael Hanselmann
  def wrapper(*args, **kwargs):
1013 4331f6cd Michael Hanselmann
    rpc.Init()
1014 4331f6cd Michael Hanselmann
    try:
1015 4331f6cd Michael Hanselmann
      return fn(*args, **kwargs)
1016 4331f6cd Michael Hanselmann
    finally:
1017 4331f6cd Michael Hanselmann
      rpc.Shutdown()
1018 4331f6cd Michael Hanselmann
  return wrapper
1019 4331f6cd Michael Hanselmann
1020 4331f6cd Michael Hanselmann
1021 47988778 Iustin Pop
def AskUser(text, choices=None):
1022 47988778 Iustin Pop
  """Ask the user a question.
1023 a8083063 Iustin Pop

1024 c41eea6e Iustin Pop
  @param text: the question to ask
1025 a8083063 Iustin Pop

1026 c41eea6e Iustin Pop
  @param choices: list with elements tuples (input_char, return_value,
1027 c41eea6e Iustin Pop
      description); if not given, it will default to: [('y', True,
1028 c41eea6e Iustin Pop
      'Perform the operation'), ('n', False, 'Do no do the operation')];
1029 c41eea6e Iustin Pop
      note that the '?' char is reserved for help
1030 47988778 Iustin Pop

1031 c41eea6e Iustin Pop
  @return: one of the return values from the choices list; if input is
1032 c41eea6e Iustin Pop
      not possible (i.e. not running with a tty, we return the last
1033 c41eea6e Iustin Pop
      entry from the list
1034 a8083063 Iustin Pop

1035 a8083063 Iustin Pop
  """
1036 47988778 Iustin Pop
  if choices is None:
1037 47988778 Iustin Pop
    choices = [('y', True, 'Perform the operation'),
1038 47988778 Iustin Pop
               ('n', False, 'Do not perform the operation')]
1039 47988778 Iustin Pop
  if not choices or not isinstance(choices, list):
1040 5bbd3f7f Michael Hanselmann
    raise errors.ProgrammerError("Invalid choices argument to AskUser")
1041 47988778 Iustin Pop
  for entry in choices:
1042 47988778 Iustin Pop
    if not isinstance(entry, tuple) or len(entry) < 3 or entry[0] == '?':
1043 5bbd3f7f Michael Hanselmann
      raise errors.ProgrammerError("Invalid choices element to AskUser")
1044 47988778 Iustin Pop
1045 47988778 Iustin Pop
  answer = choices[-1][1]
1046 47988778 Iustin Pop
  new_text = []
1047 47988778 Iustin Pop
  for line in text.splitlines():
1048 47988778 Iustin Pop
    new_text.append(textwrap.fill(line, 70, replace_whitespace=False))
1049 47988778 Iustin Pop
  text = "\n".join(new_text)
1050 a8083063 Iustin Pop
  try:
1051 3023170f Iustin Pop
    f = file("/dev/tty", "a+")
1052 a8083063 Iustin Pop
  except IOError:
1053 47988778 Iustin Pop
    return answer
1054 a8083063 Iustin Pop
  try:
1055 47988778 Iustin Pop
    chars = [entry[0] for entry in choices]
1056 47988778 Iustin Pop
    chars[-1] = "[%s]" % chars[-1]
1057 47988778 Iustin Pop
    chars.append('?')
1058 47988778 Iustin Pop
    maps = dict([(entry[0], entry[1]) for entry in choices])
1059 47988778 Iustin Pop
    while True:
1060 47988778 Iustin Pop
      f.write(text)
1061 47988778 Iustin Pop
      f.write('\n')
1062 47988778 Iustin Pop
      f.write("/".join(chars))
1063 47988778 Iustin Pop
      f.write(": ")
1064 47988778 Iustin Pop
      line = f.readline(2).strip().lower()
1065 47988778 Iustin Pop
      if line in maps:
1066 47988778 Iustin Pop
        answer = maps[line]
1067 47988778 Iustin Pop
        break
1068 47988778 Iustin Pop
      elif line == '?':
1069 47988778 Iustin Pop
        for entry in choices:
1070 47988778 Iustin Pop
          f.write(" %s - %s\n" % (entry[0], entry[2]))
1071 47988778 Iustin Pop
        f.write("\n")
1072 47988778 Iustin Pop
        continue
1073 a8083063 Iustin Pop
  finally:
1074 a8083063 Iustin Pop
    f.close()
1075 a8083063 Iustin Pop
  return answer
1076 a8083063 Iustin Pop
1077 a8083063 Iustin Pop
1078 e9d741b6 Iustin Pop
class JobSubmittedException(Exception):
1079 e9d741b6 Iustin Pop
  """Job was submitted, client should exit.
1080 e9d741b6 Iustin Pop

1081 e9d741b6 Iustin Pop
  This exception has one argument, the ID of the job that was
1082 e9d741b6 Iustin Pop
  submitted. The handler should print this ID.
1083 e9d741b6 Iustin Pop

1084 e9d741b6 Iustin Pop
  This is not an error, just a structured way to exit from clients.
1085 e9d741b6 Iustin Pop

1086 e9d741b6 Iustin Pop
  """
1087 e9d741b6 Iustin Pop
1088 e9d741b6 Iustin Pop
1089 0a1e74d9 Iustin Pop
def SendJob(ops, cl=None):
1090 0a1e74d9 Iustin Pop
  """Function to submit an opcode without waiting for the results.
1091 a8083063 Iustin Pop

1092 0a1e74d9 Iustin Pop
  @type ops: list
1093 0a1e74d9 Iustin Pop
  @param ops: list of opcodes
1094 0a1e74d9 Iustin Pop
  @type cl: luxi.Client
1095 0a1e74d9 Iustin Pop
  @param cl: the luxi client to use for communicating with the master;
1096 0a1e74d9 Iustin Pop
             if None, a new client will be created
1097 a8083063 Iustin Pop

1098 a8083063 Iustin Pop
  """
1099 e2212007 Iustin Pop
  if cl is None:
1100 b33e986b Iustin Pop
    cl = GetClient()
1101 685ee993 Iustin Pop
1102 0a1e74d9 Iustin Pop
  job_id = cl.SubmitJob(ops)
1103 0a1e74d9 Iustin Pop
1104 0a1e74d9 Iustin Pop
  return job_id
1105 0a1e74d9 Iustin Pop
1106 0a1e74d9 Iustin Pop
1107 281606c1 Michael Hanselmann
def PollJob(job_id, cl=None, feedback_fn=None):
1108 0a1e74d9 Iustin Pop
  """Function to poll for the result of a job.
1109 0a1e74d9 Iustin Pop

1110 0a1e74d9 Iustin Pop
  @type job_id: job identified
1111 0a1e74d9 Iustin Pop
  @param job_id: the job to poll for results
1112 0a1e74d9 Iustin Pop
  @type cl: luxi.Client
1113 0a1e74d9 Iustin Pop
  @param cl: the luxi client to use for communicating with the master;
1114 0a1e74d9 Iustin Pop
             if None, a new client will be created
1115 0a1e74d9 Iustin Pop

1116 0a1e74d9 Iustin Pop
  """
1117 0a1e74d9 Iustin Pop
  if cl is None:
1118 0a1e74d9 Iustin Pop
    cl = GetClient()
1119 685ee993 Iustin Pop
1120 6c5a7090 Michael Hanselmann
  prev_job_info = None
1121 6c5a7090 Michael Hanselmann
  prev_logmsg_serial = None
1122 6c5a7090 Michael Hanselmann
1123 685ee993 Iustin Pop
  while True:
1124 6c5a7090 Michael Hanselmann
    result = cl.WaitForJobChange(job_id, ["status"], prev_job_info,
1125 6c5a7090 Michael Hanselmann
                                 prev_logmsg_serial)
1126 6c5a7090 Michael Hanselmann
    if not result:
1127 685ee993 Iustin Pop
      # job not found, go away!
1128 0bbe448c Michael Hanselmann
      raise errors.JobLost("Job with id %s lost" % job_id)
1129 685ee993 Iustin Pop
1130 6c5a7090 Michael Hanselmann
    # Split result, a tuple of (field values, log entries)
1131 6c5a7090 Michael Hanselmann
    (job_info, log_entries) = result
1132 6c5a7090 Michael Hanselmann
    (status, ) = job_info
1133 6c5a7090 Michael Hanselmann
1134 6c5a7090 Michael Hanselmann
    if log_entries:
1135 6c5a7090 Michael Hanselmann
      for log_entry in log_entries:
1136 6c5a7090 Michael Hanselmann
        (serial, timestamp, _, message) = log_entry
1137 6c5a7090 Michael Hanselmann
        if callable(feedback_fn):
1138 6c5a7090 Michael Hanselmann
          feedback_fn(log_entry[1:])
1139 6c5a7090 Michael Hanselmann
        else:
1140 26f15862 Iustin Pop
          encoded = utils.SafeEncode(message)
1141 03298ebe Michael Hanselmann
          ToStdout("%s %s", time.ctime(utils.MergeTime(timestamp)), encoded)
1142 6c5a7090 Michael Hanselmann
        prev_logmsg_serial = max(prev_logmsg_serial, serial)
1143 6c5a7090 Michael Hanselmann
1144 0bbe448c Michael Hanselmann
    # TODO: Handle canceled and archived jobs
1145 fbf0262f Michael Hanselmann
    elif status in (constants.JOB_STATUS_SUCCESS,
1146 fbf0262f Michael Hanselmann
                    constants.JOB_STATUS_ERROR,
1147 fbf0262f Michael Hanselmann
                    constants.JOB_STATUS_CANCELING,
1148 fbf0262f Michael Hanselmann
                    constants.JOB_STATUS_CANCELED):
1149 685ee993 Iustin Pop
      break
1150 6c5a7090 Michael Hanselmann
1151 6c5a7090 Michael Hanselmann
    prev_job_info = job_info
1152 685ee993 Iustin Pop
1153 0e050889 Iustin Pop
  jobs = cl.QueryJobs([job_id], ["status", "opstatus", "opresult"])
1154 0bbe448c Michael Hanselmann
  if not jobs:
1155 0bbe448c Michael Hanselmann
    raise errors.JobLost("Job with id %s lost" % job_id)
1156 685ee993 Iustin Pop
1157 0e050889 Iustin Pop
  status, opstatus, result = jobs[0]
1158 0bbe448c Michael Hanselmann
  if status == constants.JOB_STATUS_SUCCESS:
1159 53c04d04 Iustin Pop
    return result
1160 fbf0262f Michael Hanselmann
  elif status in (constants.JOB_STATUS_CANCELING,
1161 fbf0262f Michael Hanselmann
                  constants.JOB_STATUS_CANCELED):
1162 fbf0262f Michael Hanselmann
    raise errors.OpExecError("Job was canceled")
1163 0bbe448c Michael Hanselmann
  else:
1164 0e050889 Iustin Pop
    has_ok = False
1165 0e050889 Iustin Pop
    for idx, (status, msg) in enumerate(zip(opstatus, result)):
1166 0e050889 Iustin Pop
      if status == constants.OP_STATUS_SUCCESS:
1167 0e050889 Iustin Pop
        has_ok = True
1168 0e050889 Iustin Pop
      elif status == constants.OP_STATUS_ERROR:
1169 bcb66fca Iustin Pop
        errors.MaybeRaise(msg)
1170 0e050889 Iustin Pop
        if has_ok:
1171 0e050889 Iustin Pop
          raise errors.OpExecError("partial failure (opcode %d): %s" %
1172 0e050889 Iustin Pop
                                   (idx, msg))
1173 0e050889 Iustin Pop
        else:
1174 0e050889 Iustin Pop
          raise errors.OpExecError(str(msg))
1175 0e050889 Iustin Pop
    # default failure mode
1176 0bbe448c Michael Hanselmann
    raise errors.OpExecError(result)
1177 ceab32dd Iustin Pop
1178 ceab32dd Iustin Pop
1179 0a1e74d9 Iustin Pop
def SubmitOpCode(op, cl=None, feedback_fn=None):
1180 0a1e74d9 Iustin Pop
  """Legacy function to submit an opcode.
1181 0a1e74d9 Iustin Pop

1182 0a1e74d9 Iustin Pop
  This is just a simple wrapper over the construction of the processor
1183 0a1e74d9 Iustin Pop
  instance. It should be extended to better handle feedback and
1184 0a1e74d9 Iustin Pop
  interaction functions.
1185 0a1e74d9 Iustin Pop

1186 0a1e74d9 Iustin Pop
  """
1187 0a1e74d9 Iustin Pop
  if cl is None:
1188 0a1e74d9 Iustin Pop
    cl = GetClient()
1189 0a1e74d9 Iustin Pop
1190 0a1e74d9 Iustin Pop
  job_id = SendJob([op], cl)
1191 0a1e74d9 Iustin Pop
1192 53c04d04 Iustin Pop
  op_results = PollJob(job_id, cl=cl, feedback_fn=feedback_fn)
1193 53c04d04 Iustin Pop
1194 53c04d04 Iustin Pop
  return op_results[0]
1195 0a1e74d9 Iustin Pop
1196 0a1e74d9 Iustin Pop
1197 94428652 Iustin Pop
def SubmitOrSend(op, opts, cl=None, feedback_fn=None):
1198 94428652 Iustin Pop
  """Wrapper around SubmitOpCode or SendJob.
1199 94428652 Iustin Pop

1200 94428652 Iustin Pop
  This function will decide, based on the 'opts' parameter, whether to
1201 94428652 Iustin Pop
  submit and wait for the result of the opcode (and return it), or
1202 94428652 Iustin Pop
  whether to just send the job and print its identifier. It is used in
1203 94428652 Iustin Pop
  order to simplify the implementation of the '--submit' option.
1204 94428652 Iustin Pop

1205 64c65a2a Iustin Pop
  It will also add the dry-run parameter from the options passed, if true.
1206 64c65a2a Iustin Pop

1207 94428652 Iustin Pop
  """
1208 64c65a2a Iustin Pop
  if opts and opts.dry_run:
1209 64c65a2a Iustin Pop
    op.dry_run = opts.dry_run
1210 94428652 Iustin Pop
  if opts and opts.submit_only:
1211 e9d741b6 Iustin Pop
    job_id = SendJob([op], cl=cl)
1212 e9d741b6 Iustin Pop
    raise JobSubmittedException(job_id)
1213 94428652 Iustin Pop
  else:
1214 94428652 Iustin Pop
    return SubmitOpCode(op, cl=cl, feedback_fn=feedback_fn)
1215 94428652 Iustin Pop
1216 94428652 Iustin Pop
1217 af30b2fd Michael Hanselmann
def GetClient():
1218 af30b2fd Michael Hanselmann
  # TODO: Cache object?
1219 b33e986b Iustin Pop
  try:
1220 b33e986b Iustin Pop
    client = luxi.Client()
1221 b33e986b Iustin Pop
  except luxi.NoMasterError:
1222 b33e986b Iustin Pop
    master, myself = ssconf.GetMasterAndMyself()
1223 b33e986b Iustin Pop
    if master != myself:
1224 b33e986b Iustin Pop
      raise errors.OpPrereqError("This is not the master node, please connect"
1225 b33e986b Iustin Pop
                                 " to node '%s' and rerun the command" %
1226 b33e986b Iustin Pop
                                 master)
1227 b33e986b Iustin Pop
    else:
1228 b33e986b Iustin Pop
      raise
1229 b33e986b Iustin Pop
  return client
1230 af30b2fd Michael Hanselmann
1231 af30b2fd Michael Hanselmann
1232 73702ee7 Iustin Pop
def FormatError(err):
1233 73702ee7 Iustin Pop
  """Return a formatted error message for a given error.
1234 73702ee7 Iustin Pop

1235 73702ee7 Iustin Pop
  This function takes an exception instance and returns a tuple
1236 73702ee7 Iustin Pop
  consisting of two values: first, the recommended exit code, and
1237 73702ee7 Iustin Pop
  second, a string describing the error message (not
1238 73702ee7 Iustin Pop
  newline-terminated).
1239 73702ee7 Iustin Pop

1240 73702ee7 Iustin Pop
  """
1241 73702ee7 Iustin Pop
  retcode = 1
1242 73702ee7 Iustin Pop
  obuf = StringIO()
1243 e2e521d0 Iustin Pop
  msg = str(err)
1244 73702ee7 Iustin Pop
  if isinstance(err, errors.ConfigurationError):
1245 e2e521d0 Iustin Pop
    txt = "Corrupt configuration file: %s" % msg
1246 46fbdd04 Iustin Pop
    logging.error(txt)
1247 e2e521d0 Iustin Pop
    obuf.write(txt + "\n")
1248 73702ee7 Iustin Pop
    obuf.write("Aborting.")
1249 73702ee7 Iustin Pop
    retcode = 2
1250 73702ee7 Iustin Pop
  elif isinstance(err, errors.HooksAbort):
1251 73702ee7 Iustin Pop
    obuf.write("Failure: hooks execution failed:\n")
1252 73702ee7 Iustin Pop
    for node, script, out in err.args[0]:
1253 73702ee7 Iustin Pop
      if out:
1254 73702ee7 Iustin Pop
        obuf.write("  node: %s, script: %s, output: %s\n" %
1255 73702ee7 Iustin Pop
                   (node, script, out))
1256 73702ee7 Iustin Pop
      else:
1257 73702ee7 Iustin Pop
        obuf.write("  node: %s, script: %s (no output)\n" %
1258 73702ee7 Iustin Pop
                   (node, script))
1259 73702ee7 Iustin Pop
  elif isinstance(err, errors.HooksFailure):
1260 e2e521d0 Iustin Pop
    obuf.write("Failure: hooks general failure: %s" % msg)
1261 73702ee7 Iustin Pop
  elif isinstance(err, errors.ResolverError):
1262 73702ee7 Iustin Pop
    this_host = utils.HostInfo.SysName()
1263 73702ee7 Iustin Pop
    if err.args[0] == this_host:
1264 73702ee7 Iustin Pop
      msg = "Failure: can't resolve my own hostname ('%s')"
1265 73702ee7 Iustin Pop
    else:
1266 73702ee7 Iustin Pop
      msg = "Failure: can't resolve hostname '%s'"
1267 73702ee7 Iustin Pop
    obuf.write(msg % err.args[0])
1268 73702ee7 Iustin Pop
  elif isinstance(err, errors.OpPrereqError):
1269 73702ee7 Iustin Pop
    obuf.write("Failure: prerequisites not met for this"
1270 e2e521d0 Iustin Pop
               " operation:\n%s" % msg)
1271 73702ee7 Iustin Pop
  elif isinstance(err, errors.OpExecError):
1272 e2e521d0 Iustin Pop
    obuf.write("Failure: command execution error:\n%s" % msg)
1273 73702ee7 Iustin Pop
  elif isinstance(err, errors.TagError):
1274 e2e521d0 Iustin Pop
    obuf.write("Failure: invalid tag(s) given:\n%s" % msg)
1275 686d7433 Iustin Pop
  elif isinstance(err, errors.JobQueueDrainError):
1276 686d7433 Iustin Pop
    obuf.write("Failure: the job queue is marked for drain and doesn't"
1277 686d7433 Iustin Pop
               " accept new requests\n")
1278 f87b405e Michael Hanselmann
  elif isinstance(err, errors.JobQueueFull):
1279 f87b405e Michael Hanselmann
    obuf.write("Failure: the job queue is full and doesn't accept new"
1280 f87b405e Michael Hanselmann
               " job submissions until old jobs are archived\n")
1281 a5728081 Guido Trotter
  elif isinstance(err, errors.TypeEnforcementError):
1282 a5728081 Guido Trotter
    obuf.write("Parameter Error: %s" % msg)
1283 c1ce76bb Iustin Pop
  elif isinstance(err, errors.ParameterError):
1284 c1ce76bb Iustin Pop
    obuf.write("Failure: unknown/wrong parameter name '%s'" % msg)
1285 73702ee7 Iustin Pop
  elif isinstance(err, errors.GenericError):
1286 e2e521d0 Iustin Pop
    obuf.write("Unhandled Ganeti error: %s" % msg)
1287 03a8dbdc Iustin Pop
  elif isinstance(err, luxi.NoMasterError):
1288 03a8dbdc Iustin Pop
    obuf.write("Cannot communicate with the master daemon.\nIs it running"
1289 082c5adb Michael Hanselmann
               " and listening for connections?")
1290 03a8dbdc Iustin Pop
  elif isinstance(err, luxi.TimeoutError):
1291 03a8dbdc Iustin Pop
    obuf.write("Timeout while talking to the master daemon. Error:\n"
1292 03a8dbdc Iustin Pop
               "%s" % msg)
1293 03a8dbdc Iustin Pop
  elif isinstance(err, luxi.ProtocolError):
1294 03a8dbdc Iustin Pop
    obuf.write("Unhandled protocol error while talking to the master daemon:\n"
1295 03a8dbdc Iustin Pop
               "%s" % msg)
1296 e9d741b6 Iustin Pop
  elif isinstance(err, JobSubmittedException):
1297 e9d741b6 Iustin Pop
    obuf.write("JobID: %s\n" % err.args[0])
1298 e9d741b6 Iustin Pop
    retcode = 0
1299 73702ee7 Iustin Pop
  else:
1300 e2e521d0 Iustin Pop
    obuf.write("Unhandled exception: %s" % msg)
1301 73702ee7 Iustin Pop
  return retcode, obuf.getvalue().rstrip('\n')
1302 73702ee7 Iustin Pop
1303 73702ee7 Iustin Pop
1304 de47cf8f Guido Trotter
def GenericMain(commands, override=None, aliases=None):
1305 a8083063 Iustin Pop
  """Generic main function for all the gnt-* commands.
1306 a8083063 Iustin Pop

1307 334d1483 Iustin Pop
  Arguments:
1308 334d1483 Iustin Pop
    - commands: a dictionary with a special structure, see the design doc
1309 334d1483 Iustin Pop
                for command line handling.
1310 334d1483 Iustin Pop
    - override: if not None, we expect a dictionary with keys that will
1311 334d1483 Iustin Pop
                override command line options; this can be used to pass
1312 334d1483 Iustin Pop
                options from the scripts to generic functions
1313 de47cf8f Guido Trotter
    - aliases: dictionary with command aliases {'alias': 'target, ...}
1314 a8083063 Iustin Pop

1315 a8083063 Iustin Pop
  """
1316 a8083063 Iustin Pop
  # save the program name and the entire command line for later logging
1317 a8083063 Iustin Pop
  if sys.argv:
1318 a8083063 Iustin Pop
    binary = os.path.basename(sys.argv[0]) or sys.argv[0]
1319 a8083063 Iustin Pop
    if len(sys.argv) >= 2:
1320 a8083063 Iustin Pop
      binary += " " + sys.argv[1]
1321 a8083063 Iustin Pop
      old_cmdline = " ".join(sys.argv[2:])
1322 a8083063 Iustin Pop
    else:
1323 a8083063 Iustin Pop
      old_cmdline = ""
1324 a8083063 Iustin Pop
  else:
1325 a8083063 Iustin Pop
    binary = "<unknown program>"
1326 a8083063 Iustin Pop
    old_cmdline = ""
1327 a8083063 Iustin Pop
1328 de47cf8f Guido Trotter
  if aliases is None:
1329 de47cf8f Guido Trotter
    aliases = {}
1330 de47cf8f Guido Trotter
1331 3126878d Guido Trotter
  try:
1332 3126878d Guido Trotter
    func, options, args = _ParseArgs(sys.argv, commands, aliases)
1333 3126878d Guido Trotter
  except errors.ParameterError, err:
1334 3126878d Guido Trotter
    result, err_msg = FormatError(err)
1335 3126878d Guido Trotter
    ToStderr(err_msg)
1336 3126878d Guido Trotter
    return 1
1337 3126878d Guido Trotter
1338 a8083063 Iustin Pop
  if func is None: # parse error
1339 a8083063 Iustin Pop
    return 1
1340 a8083063 Iustin Pop
1341 334d1483 Iustin Pop
  if override is not None:
1342 334d1483 Iustin Pop
    for key, val in override.iteritems():
1343 334d1483 Iustin Pop
      setattr(options, key, val)
1344 334d1483 Iustin Pop
1345 82d9caef Iustin Pop
  utils.SetupLogging(constants.LOG_COMMANDS, debug=options.debug,
1346 82d9caef Iustin Pop
                     stderr_logging=True, program=binary)
1347 a8083063 Iustin Pop
1348 a8083063 Iustin Pop
  if old_cmdline:
1349 46fbdd04 Iustin Pop
    logging.info("run with arguments '%s'", old_cmdline)
1350 a8083063 Iustin Pop
  else:
1351 46fbdd04 Iustin Pop
    logging.info("run with no arguments")
1352 a8083063 Iustin Pop
1353 a8083063 Iustin Pop
  try:
1354 a4af651e Iustin Pop
    result = func(options, args)
1355 d8353c3a Iustin Pop
  except (errors.GenericError, luxi.ProtocolError,
1356 d8353c3a Iustin Pop
          JobSubmittedException), err:
1357 a4af651e Iustin Pop
    result, err_msg = FormatError(err)
1358 5bbd3f7f Michael Hanselmann
    logging.exception("Error during command processing")
1359 46fbdd04 Iustin Pop
    ToStderr(err_msg)
1360 a8083063 Iustin Pop
1361 a8083063 Iustin Pop
  return result
1362 137161c9 Michael Hanselmann
1363 137161c9 Michael Hanselmann
1364 d77490c5 Iustin Pop
def GenericInstanceCreate(mode, opts, args):
1365 d77490c5 Iustin Pop
  """Add an instance to the cluster via either creation or import.
1366 d77490c5 Iustin Pop

1367 d77490c5 Iustin Pop
  @param mode: constants.INSTANCE_CREATE or constants.INSTANCE_IMPORT
1368 d77490c5 Iustin Pop
  @param opts: the command line options selected by the user
1369 d77490c5 Iustin Pop
  @type args: list
1370 d77490c5 Iustin Pop
  @param args: should contain only one element, the new instance name
1371 d77490c5 Iustin Pop
  @rtype: int
1372 d77490c5 Iustin Pop
  @return: the desired exit code
1373 d77490c5 Iustin Pop

1374 d77490c5 Iustin Pop
  """
1375 d77490c5 Iustin Pop
  instance = args[0]
1376 d77490c5 Iustin Pop
1377 d77490c5 Iustin Pop
  (pnode, snode) = SplitNodeOption(opts.node)
1378 d77490c5 Iustin Pop
1379 d77490c5 Iustin Pop
  hypervisor = None
1380 d77490c5 Iustin Pop
  hvparams = {}
1381 d77490c5 Iustin Pop
  if opts.hypervisor:
1382 d77490c5 Iustin Pop
    hypervisor, hvparams = opts.hypervisor
1383 d77490c5 Iustin Pop
1384 d77490c5 Iustin Pop
  if opts.nics:
1385 d77490c5 Iustin Pop
    try:
1386 d77490c5 Iustin Pop
      nic_max = max(int(nidx[0])+1 for nidx in opts.nics)
1387 d77490c5 Iustin Pop
    except ValueError, err:
1388 d77490c5 Iustin Pop
      raise errors.OpPrereqError("Invalid NIC index passed: %s" % str(err))
1389 d77490c5 Iustin Pop
    nics = [{}] * nic_max
1390 d77490c5 Iustin Pop
    for nidx, ndict in opts.nics:
1391 d77490c5 Iustin Pop
      nidx = int(nidx)
1392 d77490c5 Iustin Pop
      if not isinstance(ndict, dict):
1393 d77490c5 Iustin Pop
        msg = "Invalid nic/%d value: expected dict, got %s" % (nidx, ndict)
1394 d77490c5 Iustin Pop
        raise errors.OpPrereqError(msg)
1395 d77490c5 Iustin Pop
      nics[nidx] = ndict
1396 d77490c5 Iustin Pop
  elif opts.no_nics:
1397 d77490c5 Iustin Pop
    # no nics
1398 d77490c5 Iustin Pop
    nics = []
1399 d77490c5 Iustin Pop
  else:
1400 d77490c5 Iustin Pop
    # default of one nic, all auto
1401 d77490c5 Iustin Pop
    nics = [{}]
1402 d77490c5 Iustin Pop
1403 d77490c5 Iustin Pop
  if opts.disk_template == constants.DT_DISKLESS:
1404 d77490c5 Iustin Pop
    if opts.disks or opts.sd_size is not None:
1405 d77490c5 Iustin Pop
      raise errors.OpPrereqError("Diskless instance but disk"
1406 d77490c5 Iustin Pop
                                 " information passed")
1407 d77490c5 Iustin Pop
    disks = []
1408 d77490c5 Iustin Pop
  else:
1409 d77490c5 Iustin Pop
    if not opts.disks and not opts.sd_size:
1410 d77490c5 Iustin Pop
      raise errors.OpPrereqError("No disk information specified")
1411 d77490c5 Iustin Pop
    if opts.disks and opts.sd_size is not None:
1412 d77490c5 Iustin Pop
      raise errors.OpPrereqError("Please use either the '--disk' or"
1413 d77490c5 Iustin Pop
                                 " '-s' option")
1414 d77490c5 Iustin Pop
    if opts.sd_size is not None:
1415 d77490c5 Iustin Pop
      opts.disks = [(0, {"size": opts.sd_size})]
1416 d77490c5 Iustin Pop
    try:
1417 d77490c5 Iustin Pop
      disk_max = max(int(didx[0])+1 for didx in opts.disks)
1418 d77490c5 Iustin Pop
    except ValueError, err:
1419 d77490c5 Iustin Pop
      raise errors.OpPrereqError("Invalid disk index passed: %s" % str(err))
1420 d77490c5 Iustin Pop
    disks = [{}] * disk_max
1421 d77490c5 Iustin Pop
    for didx, ddict in opts.disks:
1422 d77490c5 Iustin Pop
      didx = int(didx)
1423 d77490c5 Iustin Pop
      if not isinstance(ddict, dict):
1424 d77490c5 Iustin Pop
        msg = "Invalid disk/%d value: expected dict, got %s" % (didx, ddict)
1425 d77490c5 Iustin Pop
        raise errors.OpPrereqError(msg)
1426 d77490c5 Iustin Pop
      elif "size" not in ddict:
1427 d77490c5 Iustin Pop
        raise errors.OpPrereqError("Missing size for disk %d" % didx)
1428 d77490c5 Iustin Pop
      try:
1429 d77490c5 Iustin Pop
        ddict["size"] = utils.ParseUnit(ddict["size"])
1430 d77490c5 Iustin Pop
      except ValueError, err:
1431 d77490c5 Iustin Pop
        raise errors.OpPrereqError("Invalid disk size for disk %d: %s" %
1432 d77490c5 Iustin Pop
                                   (didx, err))
1433 d77490c5 Iustin Pop
      disks[didx] = ddict
1434 d77490c5 Iustin Pop
1435 d77490c5 Iustin Pop
  utils.ForceDictType(opts.beparams, constants.BES_PARAMETER_TYPES)
1436 d77490c5 Iustin Pop
  utils.ForceDictType(hvparams, constants.HVS_PARAMETER_TYPES)
1437 d77490c5 Iustin Pop
1438 d77490c5 Iustin Pop
  if mode == constants.INSTANCE_CREATE:
1439 d77490c5 Iustin Pop
    start = opts.start
1440 d77490c5 Iustin Pop
    os_type = opts.os
1441 d77490c5 Iustin Pop
    src_node = None
1442 d77490c5 Iustin Pop
    src_path = None
1443 d77490c5 Iustin Pop
  elif mode == constants.INSTANCE_IMPORT:
1444 d77490c5 Iustin Pop
    start = False
1445 d77490c5 Iustin Pop
    os_type = None
1446 d77490c5 Iustin Pop
    src_node = opts.src_node
1447 d77490c5 Iustin Pop
    src_path = opts.src_dir
1448 d77490c5 Iustin Pop
  else:
1449 d77490c5 Iustin Pop
    raise errors.ProgrammerError("Invalid creation mode %s" % mode)
1450 d77490c5 Iustin Pop
1451 d77490c5 Iustin Pop
  op = opcodes.OpCreateInstance(instance_name=instance,
1452 d77490c5 Iustin Pop
                                disks=disks,
1453 d77490c5 Iustin Pop
                                disk_template=opts.disk_template,
1454 d77490c5 Iustin Pop
                                nics=nics,
1455 d77490c5 Iustin Pop
                                pnode=pnode, snode=snode,
1456 d77490c5 Iustin Pop
                                ip_check=opts.ip_check,
1457 d77490c5 Iustin Pop
                                wait_for_sync=opts.wait_for_sync,
1458 d77490c5 Iustin Pop
                                file_storage_dir=opts.file_storage_dir,
1459 d77490c5 Iustin Pop
                                file_driver=opts.file_driver,
1460 d77490c5 Iustin Pop
                                iallocator=opts.iallocator,
1461 d77490c5 Iustin Pop
                                hypervisor=hypervisor,
1462 d77490c5 Iustin Pop
                                hvparams=hvparams,
1463 d77490c5 Iustin Pop
                                beparams=opts.beparams,
1464 d77490c5 Iustin Pop
                                mode=mode,
1465 d77490c5 Iustin Pop
                                start=start,
1466 d77490c5 Iustin Pop
                                os_type=os_type,
1467 d77490c5 Iustin Pop
                                src_node=src_node,
1468 d77490c5 Iustin Pop
                                src_path=src_path)
1469 d77490c5 Iustin Pop
1470 d77490c5 Iustin Pop
  SubmitOrSend(op, opts)
1471 d77490c5 Iustin Pop
  return 0
1472 d77490c5 Iustin Pop
1473 d77490c5 Iustin Pop
1474 16be8703 Iustin Pop
def GenerateTable(headers, fields, separator, data,
1475 9fbfbb7b Iustin Pop
                  numfields=None, unitfields=None,
1476 9fbfbb7b Iustin Pop
                  units=None):
1477 137161c9 Michael Hanselmann
  """Prints a table with headers and different fields.
1478 137161c9 Michael Hanselmann

1479 9fbfbb7b Iustin Pop
  @type headers: dict
1480 9fbfbb7b Iustin Pop
  @param headers: dictionary mapping field names to headers for
1481 9fbfbb7b Iustin Pop
      the table
1482 9fbfbb7b Iustin Pop
  @type fields: list
1483 9fbfbb7b Iustin Pop
  @param fields: the field names corresponding to each row in
1484 9fbfbb7b Iustin Pop
      the data field
1485 9fbfbb7b Iustin Pop
  @param separator: the separator to be used; if this is None,
1486 9fbfbb7b Iustin Pop
      the default 'smart' algorithm is used which computes optimal
1487 9fbfbb7b Iustin Pop
      field width, otherwise just the separator is used between
1488 9fbfbb7b Iustin Pop
      each field
1489 9fbfbb7b Iustin Pop
  @type data: list
1490 9fbfbb7b Iustin Pop
  @param data: a list of lists, each sublist being one row to be output
1491 9fbfbb7b Iustin Pop
  @type numfields: list
1492 9fbfbb7b Iustin Pop
  @param numfields: a list with the fields that hold numeric
1493 9fbfbb7b Iustin Pop
      values and thus should be right-aligned
1494 9fbfbb7b Iustin Pop
  @type unitfields: list
1495 9fbfbb7b Iustin Pop
  @param unitfields: a list with the fields that hold numeric
1496 9fbfbb7b Iustin Pop
      values that should be formatted with the units field
1497 9fbfbb7b Iustin Pop
  @type units: string or None
1498 9fbfbb7b Iustin Pop
  @param units: the units we should use for formatting, or None for
1499 9fbfbb7b Iustin Pop
      automatic choice (human-readable for non-separator usage, otherwise
1500 9fbfbb7b Iustin Pop
      megabytes); this is a one-letter string
1501 137161c9 Michael Hanselmann

1502 137161c9 Michael Hanselmann
  """
1503 9fbfbb7b Iustin Pop
  if units is None:
1504 9fbfbb7b Iustin Pop
    if separator:
1505 9fbfbb7b Iustin Pop
      units = "m"
1506 9fbfbb7b Iustin Pop
    else:
1507 9fbfbb7b Iustin Pop
      units = "h"
1508 9fbfbb7b Iustin Pop
1509 137161c9 Michael Hanselmann
  if numfields is None:
1510 137161c9 Michael Hanselmann
    numfields = []
1511 137161c9 Michael Hanselmann
  if unitfields is None:
1512 137161c9 Michael Hanselmann
    unitfields = []
1513 137161c9 Michael Hanselmann
1514 00430f8e Iustin Pop
  numfields = utils.FieldSet(*numfields)
1515 00430f8e Iustin Pop
  unitfields = utils.FieldSet(*unitfields)
1516 00430f8e Iustin Pop
1517 137161c9 Michael Hanselmann
  format_fields = []
1518 137161c9 Michael Hanselmann
  for field in fields:
1519 01ca31ae Iustin Pop
    if headers and field not in headers:
1520 ea5a5b74 Guido Trotter
      # TODO: handle better unknown fields (either revert to old
1521 71c1af58 Iustin Pop
      # style of raising exception, or deal more intelligently with
1522 71c1af58 Iustin Pop
      # variable fields)
1523 71c1af58 Iustin Pop
      headers[field] = field
1524 137161c9 Michael Hanselmann
    if separator is not None:
1525 137161c9 Michael Hanselmann
      format_fields.append("%s")
1526 00430f8e Iustin Pop
    elif numfields.Matches(field):
1527 137161c9 Michael Hanselmann
      format_fields.append("%*s")
1528 137161c9 Michael Hanselmann
    else:
1529 137161c9 Michael Hanselmann
      format_fields.append("%-*s")
1530 137161c9 Michael Hanselmann
1531 137161c9 Michael Hanselmann
  if separator is None:
1532 137161c9 Michael Hanselmann
    mlens = [0 for name in fields]
1533 137161c9 Michael Hanselmann
    format = ' '.join(format_fields)
1534 137161c9 Michael Hanselmann
  else:
1535 137161c9 Michael Hanselmann
    format = separator.replace("%", "%%").join(format_fields)
1536 137161c9 Michael Hanselmann
1537 137161c9 Michael Hanselmann
  for row in data:
1538 dcbd6288 Guido Trotter
    if row is None:
1539 dcbd6288 Guido Trotter
      continue
1540 137161c9 Michael Hanselmann
    for idx, val in enumerate(row):
1541 00430f8e Iustin Pop
      if unitfields.Matches(fields[idx]):
1542 137161c9 Michael Hanselmann
        try:
1543 137161c9 Michael Hanselmann
          val = int(val)
1544 137161c9 Michael Hanselmann
        except ValueError:
1545 137161c9 Michael Hanselmann
          pass
1546 137161c9 Michael Hanselmann
        else:
1547 9fbfbb7b Iustin Pop
          val = row[idx] = utils.FormatUnit(val, units)
1548 01ca31ae Iustin Pop
      val = row[idx] = str(val)
1549 137161c9 Michael Hanselmann
      if separator is None:
1550 137161c9 Michael Hanselmann
        mlens[idx] = max(mlens[idx], len(val))
1551 137161c9 Michael Hanselmann
1552 16be8703 Iustin Pop
  result = []
1553 137161c9 Michael Hanselmann
  if headers:
1554 137161c9 Michael Hanselmann
    args = []
1555 137161c9 Michael Hanselmann
    for idx, name in enumerate(fields):
1556 137161c9 Michael Hanselmann
      hdr = headers[name]
1557 137161c9 Michael Hanselmann
      if separator is None:
1558 137161c9 Michael Hanselmann
        mlens[idx] = max(mlens[idx], len(hdr))
1559 137161c9 Michael Hanselmann
        args.append(mlens[idx])
1560 137161c9 Michael Hanselmann
      args.append(hdr)
1561 16be8703 Iustin Pop
    result.append(format % tuple(args))
1562 137161c9 Michael Hanselmann
1563 137161c9 Michael Hanselmann
  for line in data:
1564 137161c9 Michael Hanselmann
    args = []
1565 dcbd6288 Guido Trotter
    if line is None:
1566 dcbd6288 Guido Trotter
      line = ['-' for _ in fields]
1567 f1501b3f Michael Hanselmann
    for idx in range(len(fields)):
1568 137161c9 Michael Hanselmann
      if separator is None:
1569 137161c9 Michael Hanselmann
        args.append(mlens[idx])
1570 137161c9 Michael Hanselmann
      args.append(line[idx])
1571 16be8703 Iustin Pop
    result.append(format % tuple(args))
1572 16be8703 Iustin Pop
1573 16be8703 Iustin Pop
  return result
1574 3386e7a9 Iustin Pop
1575 3386e7a9 Iustin Pop
1576 3386e7a9 Iustin Pop
def FormatTimestamp(ts):
1577 3386e7a9 Iustin Pop
  """Formats a given timestamp.
1578 3386e7a9 Iustin Pop

1579 3386e7a9 Iustin Pop
  @type ts: timestamp
1580 3386e7a9 Iustin Pop
  @param ts: a timeval-type timestamp, a tuple of seconds and microseconds
1581 3386e7a9 Iustin Pop

1582 3386e7a9 Iustin Pop
  @rtype: string
1583 5fcc718f Iustin Pop
  @return: a string with the formatted timestamp
1584 3386e7a9 Iustin Pop

1585 3386e7a9 Iustin Pop
  """
1586 e0ec0ff6 Iustin Pop
  if not isinstance (ts, (tuple, list)) or len(ts) != 2:
1587 e0ec0ff6 Iustin Pop
    return '?'
1588 3386e7a9 Iustin Pop
  sec, usec = ts
1589 3386e7a9 Iustin Pop
  return time.strftime("%F %T", time.localtime(sec)) + ".%06d" % usec
1590 2241e2b9 Iustin Pop
1591 2241e2b9 Iustin Pop
1592 2241e2b9 Iustin Pop
def ParseTimespec(value):
1593 2241e2b9 Iustin Pop
  """Parse a time specification.
1594 2241e2b9 Iustin Pop

1595 2241e2b9 Iustin Pop
  The following suffixed will be recognized:
1596 2241e2b9 Iustin Pop

1597 2241e2b9 Iustin Pop
    - s: seconds
1598 2241e2b9 Iustin Pop
    - m: minutes
1599 2241e2b9 Iustin Pop
    - h: hours
1600 2241e2b9 Iustin Pop
    - d: day
1601 2241e2b9 Iustin Pop
    - w: weeks
1602 2241e2b9 Iustin Pop

1603 2241e2b9 Iustin Pop
  Without any suffix, the value will be taken to be in seconds.
1604 2241e2b9 Iustin Pop

1605 2241e2b9 Iustin Pop
  """
1606 2241e2b9 Iustin Pop
  value = str(value)
1607 2241e2b9 Iustin Pop
  if not value:
1608 2241e2b9 Iustin Pop
    raise errors.OpPrereqError("Empty time specification passed")
1609 2241e2b9 Iustin Pop
  suffix_map = {
1610 2241e2b9 Iustin Pop
    's': 1,
1611 2241e2b9 Iustin Pop
    'm': 60,
1612 2241e2b9 Iustin Pop
    'h': 3600,
1613 2241e2b9 Iustin Pop
    'd': 86400,
1614 2241e2b9 Iustin Pop
    'w': 604800,
1615 2241e2b9 Iustin Pop
    }
1616 2241e2b9 Iustin Pop
  if value[-1] not in suffix_map:
1617 2241e2b9 Iustin Pop
    try:
1618 2241e2b9 Iustin Pop
      value = int(value)
1619 2241e2b9 Iustin Pop
    except ValueError:
1620 2241e2b9 Iustin Pop
      raise errors.OpPrereqError("Invalid time specification '%s'" % value)
1621 2241e2b9 Iustin Pop
  else:
1622 2241e2b9 Iustin Pop
    multiplier = suffix_map[value[-1]]
1623 2241e2b9 Iustin Pop
    value = value[:-1]
1624 2241e2b9 Iustin Pop
    if not value: # no data left after stripping the suffix
1625 2241e2b9 Iustin Pop
      raise errors.OpPrereqError("Invalid time specification (only"
1626 2241e2b9 Iustin Pop
                                 " suffix passed)")
1627 2241e2b9 Iustin Pop
    try:
1628 2241e2b9 Iustin Pop
      value = int(value) * multiplier
1629 2241e2b9 Iustin Pop
    except ValueError:
1630 2241e2b9 Iustin Pop
      raise errors.OpPrereqError("Invalid time specification '%s'" % value)
1631 2241e2b9 Iustin Pop
  return value
1632 46fbdd04 Iustin Pop
1633 46fbdd04 Iustin Pop
1634 4040a784 Iustin Pop
def GetOnlineNodes(nodes, cl=None, nowarn=False):
1635 4040a784 Iustin Pop
  """Returns the names of online nodes.
1636 4040a784 Iustin Pop

1637 4040a784 Iustin Pop
  This function will also log a warning on stderr with the names of
1638 4040a784 Iustin Pop
  the online nodes.
1639 4040a784 Iustin Pop

1640 4040a784 Iustin Pop
  @param nodes: if not empty, use only this subset of nodes (minus the
1641 4040a784 Iustin Pop
      offline ones)
1642 4040a784 Iustin Pop
  @param cl: if not None, luxi client to use
1643 4040a784 Iustin Pop
  @type nowarn: boolean
1644 4040a784 Iustin Pop
  @param nowarn: by default, this function will output a note with the
1645 4040a784 Iustin Pop
      offline nodes that are skipped; if this parameter is True the
1646 4040a784 Iustin Pop
      note is not displayed
1647 4040a784 Iustin Pop

1648 4040a784 Iustin Pop
  """
1649 4040a784 Iustin Pop
  if cl is None:
1650 4040a784 Iustin Pop
    cl = GetClient()
1651 4040a784 Iustin Pop
1652 2e7b8369 Iustin Pop
  result = cl.QueryNodes(names=nodes, fields=["name", "offline"],
1653 2e7b8369 Iustin Pop
                         use_locking=False)
1654 4040a784 Iustin Pop
  offline = [row[0] for row in result if row[1]]
1655 4040a784 Iustin Pop
  if offline and not nowarn:
1656 4040a784 Iustin Pop
    ToStderr("Note: skipping offline node(s): %s" % ", ".join(offline))
1657 4040a784 Iustin Pop
  return [row[0] for row in result if not row[1]]
1658 4040a784 Iustin Pop
1659 4040a784 Iustin Pop
1660 46fbdd04 Iustin Pop
def _ToStream(stream, txt, *args):
1661 46fbdd04 Iustin Pop
  """Write a message to a stream, bypassing the logging system
1662 46fbdd04 Iustin Pop

1663 46fbdd04 Iustin Pop
  @type stream: file object
1664 46fbdd04 Iustin Pop
  @param stream: the file to which we should write
1665 46fbdd04 Iustin Pop
  @type txt: str
1666 46fbdd04 Iustin Pop
  @param txt: the message
1667 46fbdd04 Iustin Pop

1668 46fbdd04 Iustin Pop
  """
1669 46fbdd04 Iustin Pop
  if args:
1670 46fbdd04 Iustin Pop
    args = tuple(args)
1671 46fbdd04 Iustin Pop
    stream.write(txt % args)
1672 46fbdd04 Iustin Pop
  else:
1673 46fbdd04 Iustin Pop
    stream.write(txt)
1674 46fbdd04 Iustin Pop
  stream.write('\n')
1675 46fbdd04 Iustin Pop
  stream.flush()
1676 46fbdd04 Iustin Pop
1677 46fbdd04 Iustin Pop
1678 46fbdd04 Iustin Pop
def ToStdout(txt, *args):
1679 46fbdd04 Iustin Pop
  """Write a message to stdout only, bypassing the logging system
1680 46fbdd04 Iustin Pop

1681 46fbdd04 Iustin Pop
  This is just a wrapper over _ToStream.
1682 46fbdd04 Iustin Pop

1683 46fbdd04 Iustin Pop
  @type txt: str
1684 46fbdd04 Iustin Pop
  @param txt: the message
1685 46fbdd04 Iustin Pop

1686 46fbdd04 Iustin Pop
  """
1687 46fbdd04 Iustin Pop
  _ToStream(sys.stdout, txt, *args)
1688 46fbdd04 Iustin Pop
1689 46fbdd04 Iustin Pop
1690 46fbdd04 Iustin Pop
def ToStderr(txt, *args):
1691 46fbdd04 Iustin Pop
  """Write a message to stderr only, bypassing the logging system
1692 46fbdd04 Iustin Pop

1693 46fbdd04 Iustin Pop
  This is just a wrapper over _ToStream.
1694 46fbdd04 Iustin Pop

1695 46fbdd04 Iustin Pop
  @type txt: str
1696 46fbdd04 Iustin Pop
  @param txt: the message
1697 46fbdd04 Iustin Pop

1698 46fbdd04 Iustin Pop
  """
1699 46fbdd04 Iustin Pop
  _ToStream(sys.stderr, txt, *args)
1700 479636a3 Iustin Pop
1701 479636a3 Iustin Pop
1702 479636a3 Iustin Pop
class JobExecutor(object):
1703 479636a3 Iustin Pop
  """Class which manages the submission and execution of multiple jobs.
1704 479636a3 Iustin Pop

1705 479636a3 Iustin Pop
  Note that instances of this class should not be reused between
1706 479636a3 Iustin Pop
  GetResults() calls.
1707 479636a3 Iustin Pop

1708 479636a3 Iustin Pop
  """
1709 479636a3 Iustin Pop
  def __init__(self, cl=None, verbose=True):
1710 479636a3 Iustin Pop
    self.queue = []
1711 479636a3 Iustin Pop
    if cl is None:
1712 479636a3 Iustin Pop
      cl = GetClient()
1713 479636a3 Iustin Pop
    self.cl = cl
1714 479636a3 Iustin Pop
    self.verbose = verbose
1715 23b4b983 Iustin Pop
    self.jobs = []
1716 479636a3 Iustin Pop
1717 479636a3 Iustin Pop
  def QueueJob(self, name, *ops):
1718 23b4b983 Iustin Pop
    """Record a job for later submit.
1719 479636a3 Iustin Pop

1720 479636a3 Iustin Pop
    @type name: string
1721 479636a3 Iustin Pop
    @param name: a description of the job, will be used in WaitJobSet
1722 479636a3 Iustin Pop
    """
1723 23b4b983 Iustin Pop
    self.queue.append((name, ops))
1724 23b4b983 Iustin Pop
1725 23b4b983 Iustin Pop
  def SubmitPending(self):
1726 23b4b983 Iustin Pop
    """Submit all pending jobs.
1727 23b4b983 Iustin Pop

1728 23b4b983 Iustin Pop
    """
1729 23b4b983 Iustin Pop
    results = self.cl.SubmitManyJobs([row[1] for row in self.queue])
1730 23b4b983 Iustin Pop
    for ((status, data), (name, _)) in zip(results, self.queue):
1731 23b4b983 Iustin Pop
      self.jobs.append((status, data, name))
1732 479636a3 Iustin Pop
1733 479636a3 Iustin Pop
  def GetResults(self):
1734 479636a3 Iustin Pop
    """Wait for and return the results of all jobs.
1735 479636a3 Iustin Pop

1736 479636a3 Iustin Pop
    @rtype: list
1737 479636a3 Iustin Pop
    @return: list of tuples (success, job results), in the same order
1738 479636a3 Iustin Pop
        as the submitted jobs; if a job has failed, instead of the result
1739 479636a3 Iustin Pop
        there will be the error message
1740 479636a3 Iustin Pop

1741 479636a3 Iustin Pop
    """
1742 23b4b983 Iustin Pop
    if not self.jobs:
1743 23b4b983 Iustin Pop
      self.SubmitPending()
1744 479636a3 Iustin Pop
    results = []
1745 479636a3 Iustin Pop
    if self.verbose:
1746 23b4b983 Iustin Pop
      ok_jobs = [row[1] for row in self.jobs if row[0]]
1747 23b4b983 Iustin Pop
      if ok_jobs:
1748 23b4b983 Iustin Pop
        ToStdout("Submitted jobs %s", ", ".join(ok_jobs))
1749 23b4b983 Iustin Pop
    for submit_status, jid, name in self.jobs:
1750 23b4b983 Iustin Pop
      if not submit_status:
1751 23b4b983 Iustin Pop
        ToStderr("Failed to submit job for %s: %s", name, jid)
1752 23b4b983 Iustin Pop
        results.append((False, jid))
1753 23b4b983 Iustin Pop
        continue
1754 479636a3 Iustin Pop
      if self.verbose:
1755 479636a3 Iustin Pop
        ToStdout("Waiting for job %s for %s...", jid, name)
1756 479636a3 Iustin Pop
      try:
1757 479636a3 Iustin Pop
        job_result = PollJob(jid, cl=self.cl)
1758 479636a3 Iustin Pop
        success = True
1759 479636a3 Iustin Pop
      except (errors.GenericError, luxi.ProtocolError), err:
1760 479636a3 Iustin Pop
        _, job_result = FormatError(err)
1761 479636a3 Iustin Pop
        success = False
1762 479636a3 Iustin Pop
        # the error message will always be shown, verbose or not
1763 479636a3 Iustin Pop
        ToStderr("Job %s for %s has failed: %s", jid, name, job_result)
1764 479636a3 Iustin Pop
1765 479636a3 Iustin Pop
      results.append((success, job_result))
1766 479636a3 Iustin Pop
    return results
1767 479636a3 Iustin Pop
1768 479636a3 Iustin Pop
  def WaitOrShow(self, wait):
1769 479636a3 Iustin Pop
    """Wait for job results or only print the job IDs.
1770 479636a3 Iustin Pop

1771 479636a3 Iustin Pop
    @type wait: boolean
1772 479636a3 Iustin Pop
    @param wait: whether to wait or not
1773 479636a3 Iustin Pop

1774 479636a3 Iustin Pop
    """
1775 479636a3 Iustin Pop
    if wait:
1776 479636a3 Iustin Pop
      return self.GetResults()
1777 479636a3 Iustin Pop
    else:
1778 23b4b983 Iustin Pop
      if not self.jobs:
1779 23b4b983 Iustin Pop
        self.SubmitPending()
1780 23b4b983 Iustin Pop
      for status, result, name in self.jobs:
1781 23b4b983 Iustin Pop
        if status:
1782 23b4b983 Iustin Pop
          ToStdout("%s: %s", result, name)
1783 23b4b983 Iustin Pop
        else:
1784 23b4b983 Iustin Pop
          ToStderr("Failure for %s: %s", name, result)