Statistics
| Branch: | Tag: | Revision:

root / lib / cli.py @ 4d98c565

History | View | Annotate | Download (56.7 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 26023ecd Iustin Pop
  "NONICS_OPT",
88 f2a0828c Iustin Pop
  "NONLIVE_OPT",
89 14e9e7f3 Iustin Pop
  "NONPLUS1_OPT",
90 44c44832 Iustin Pop
  "NOSHUTDOWN_OPT",
91 edeb878a Iustin Pop
  "NOSTART_OPT",
92 fcdde7f2 Iustin Pop
  "NOSSH_KEYCHECK_OPT",
93 58371861 Iustin Pop
  "NOVOTING_OPT",
94 3f75b4f3 Iustin Pop
  "NWSYNC_OPT",
95 a72d0a79 Iustin Pop
  "ON_PRIMARY_OPT",
96 feb09e6a Iustin Pop
  "ON_SECONDARY_OPT",
97 771734c9 Iustin Pop
  "OFFLINE_OPT",
98 d3ed23ff Iustin Pop
  "OS_OPT",
99 ff00c1a7 Iustin Pop
  "OS_SIZE_OPT",
100 b8d0f938 Iustin Pop
  "READD_OPT",
101 12054861 Iustin Pop
  "REBOOT_TYPE_OPT",
102 8d823629 Iustin Pop
  "SECONDARY_IP_OPT",
103 67840b40 Iustin Pop
  "SELECT_OS_OPT",
104 4abc4f1e Iustin Pop
  "SEP_OPT",
105 fdcf4d84 Iustin Pop
  "SHOWCMD_OPT",
106 7e5eaaa8 Guido Trotter
  "SHUTDOWN_TIMEOUT_OPT",
107 f36d7d81 Iustin Pop
  "SINGLE_NODE_OPT",
108 df62e5db Iustin Pop
  "SRC_DIR_OPT",
109 df62e5db Iustin Pop
  "SRC_NODE_OPT",
110 4abc4f1e Iustin Pop
  "SUBMIT_OPT",
111 99a8c799 Iustin Pop
  "STATIC_OPT",
112 4abc4f1e Iustin Pop
  "SYNC_OPT",
113 4abc4f1e Iustin Pop
  "TAG_SRC_OPT",
114 b5762e2a Guido Trotter
  "TIMEOUT_OPT",
115 4abc4f1e Iustin Pop
  "USEUNITS_OPT",
116 9cdb9578 Iustin Pop
  "VERBOSE_OPT",
117 b58726e8 Iustin Pop
  "VG_NAME_OPT",
118 1f587d3d Iustin Pop
  "YES_DOIT_OPT",
119 4abc4f1e Iustin Pop
  # Generic functions for CLI programs
120 4abc4f1e Iustin Pop
  "GenericMain",
121 d77490c5 Iustin Pop
  "GenericInstanceCreate",
122 4abc4f1e Iustin Pop
  "GetClient",
123 4abc4f1e Iustin Pop
  "GetOnlineNodes",
124 4abc4f1e Iustin Pop
  "JobExecutor",
125 4abc4f1e Iustin Pop
  "JobSubmittedException",
126 4abc4f1e Iustin Pop
  "ParseTimespec",
127 4abc4f1e Iustin Pop
  "SubmitOpCode",
128 4abc4f1e Iustin Pop
  "SubmitOrSend",
129 4abc4f1e Iustin Pop
  "UsesRPC",
130 4abc4f1e Iustin Pop
  # Formatting functions
131 4abc4f1e Iustin Pop
  "ToStderr", "ToStdout",
132 4abc4f1e Iustin Pop
  "FormatError",
133 4abc4f1e Iustin Pop
  "GenerateTable",
134 4abc4f1e Iustin Pop
  "AskUser",
135 4abc4f1e Iustin Pop
  "FormatTimestamp",
136 4abc4f1e Iustin Pop
  # Tags functions
137 4abc4f1e Iustin Pop
  "ListTags",
138 4abc4f1e Iustin Pop
  "AddTags",
139 4abc4f1e Iustin Pop
  "RemoveTags",
140 4abc4f1e Iustin Pop
  # command line options support infrastructure
141 4abc4f1e Iustin Pop
  "ARGS_MANY_INSTANCES",
142 4abc4f1e Iustin Pop
  "ARGS_MANY_NODES",
143 4abc4f1e Iustin Pop
  "ARGS_NONE",
144 4abc4f1e Iustin Pop
  "ARGS_ONE_INSTANCE",
145 4abc4f1e Iustin Pop
  "ARGS_ONE_NODE",
146 4abc4f1e Iustin Pop
  "ArgChoice",
147 4abc4f1e Iustin Pop
  "ArgCommand",
148 4abc4f1e Iustin Pop
  "ArgFile",
149 4abc4f1e Iustin Pop
  "ArgHost",
150 4abc4f1e Iustin Pop
  "ArgInstance",
151 4abc4f1e Iustin Pop
  "ArgJobId",
152 4abc4f1e Iustin Pop
  "ArgNode",
153 4abc4f1e Iustin Pop
  "ArgSuggest",
154 4abc4f1e Iustin Pop
  "ArgUnknown",
155 4abc4f1e Iustin Pop
  "OPT_COMPL_INST_ADD_NODES",
156 4abc4f1e Iustin Pop
  "OPT_COMPL_MANY_NODES",
157 4abc4f1e Iustin Pop
  "OPT_COMPL_ONE_IALLOCATOR",
158 4abc4f1e Iustin Pop
  "OPT_COMPL_ONE_INSTANCE",
159 4abc4f1e Iustin Pop
  "OPT_COMPL_ONE_NODE",
160 4abc4f1e Iustin Pop
  "OPT_COMPL_ONE_OS",
161 4abc4f1e Iustin Pop
  "cli_option",
162 4abc4f1e Iustin Pop
  "SplitNodeOption",
163 07150497 Guido Trotter
  "CalculateOSNames",
164 4abc4f1e Iustin Pop
  ]
165 846baef9 Iustin Pop
166 8b46606c Guido Trotter
NO_PREFIX = "no_"
167 8b46606c Guido Trotter
UN_PREFIX = "-"
168 846baef9 Iustin Pop
169 03298ebe Michael Hanselmann
170 863d7f46 Michael Hanselmann
class _Argument:
171 dff85078 Michael Hanselmann
  def __init__(self, min=0, max=None):
172 863d7f46 Michael Hanselmann
    self.min = min
173 863d7f46 Michael Hanselmann
    self.max = max
174 863d7f46 Michael Hanselmann
175 863d7f46 Michael Hanselmann
  def __repr__(self):
176 863d7f46 Michael Hanselmann
    return ("<%s min=%s max=%s>" %
177 863d7f46 Michael Hanselmann
            (self.__class__.__name__, self.min, self.max))
178 863d7f46 Michael Hanselmann
179 863d7f46 Michael Hanselmann
180 863d7f46 Michael Hanselmann
class ArgSuggest(_Argument):
181 863d7f46 Michael Hanselmann
  """Suggesting argument.
182 863d7f46 Michael Hanselmann

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

836 c41eea6e Iustin Pop
  @param argv: the command line
837 c41eea6e Iustin Pop
  @param commands: dictionary with special contents, see the design
838 c41eea6e Iustin Pop
      doc for cmdline handling
839 c41eea6e Iustin Pop
  @param aliases: dictionary with command aliases {'alias': 'target, ...}
840 098c0958 Michael Hanselmann

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

911 a8005e17 Michael Hanselmann
  Algorithm:
912 a8005e17 Michael Hanselmann

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

915 a8005e17 Michael Hanselmann
    1. For each argument in definition
916 a8005e17 Michael Hanselmann

917 a8005e17 Michael Hanselmann
      1. Keep running count of minimum number of values (min_count)
918 a8005e17 Michael Hanselmann
      1. Keep running count of maximum number of values (max_count)
919 a8005e17 Michael Hanselmann
      1. If it has an unlimited number of values
920 a8005e17 Michael Hanselmann

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

923 a8005e17 Michael Hanselmann
    1. If last argument has limited number of values
924 a8005e17 Michael Hanselmann

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

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

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

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

992 07150497 Guido Trotter
  @type os_name: string
993 07150497 Guido Trotter
  @param os_name: base name of the os
994 07150497 Guido Trotter
  @type os_variants: list or None
995 07150497 Guido Trotter
  @param os_variants: list of supported variants
996 07150497 Guido Trotter
  @rtype: list
997 07150497 Guido Trotter
  @return: list of valid names
998 07150497 Guido Trotter

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

1019 c41eea6e Iustin Pop
  @param text: the question to ask
1020 a8083063 Iustin Pop

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

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

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

1076 e9d741b6 Iustin Pop
  This exception has one argument, the ID of the job that was
1077 e9d741b6 Iustin Pop
  submitted. The handler should print this ID.
1078 e9d741b6 Iustin Pop

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

1081 e9d741b6 Iustin Pop
  """
1082 e9d741b6 Iustin Pop
1083 e9d741b6 Iustin Pop
1084 0a1e74d9 Iustin Pop
def SendJob(ops, cl=None):
1085 0a1e74d9 Iustin Pop
  """Function to submit an opcode without waiting for the results.
1086 a8083063 Iustin Pop

1087 0a1e74d9 Iustin Pop
  @type ops: list
1088 0a1e74d9 Iustin Pop
  @param ops: list of opcodes
1089 0a1e74d9 Iustin Pop
  @type cl: luxi.Client
1090 0a1e74d9 Iustin Pop
  @param cl: the luxi client to use for communicating with the master;
1091 0a1e74d9 Iustin Pop
             if None, a new client will be created
1092 a8083063 Iustin Pop

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

1105 0a1e74d9 Iustin Pop
  @type job_id: job identified
1106 0a1e74d9 Iustin Pop
  @param job_id: the job to poll for results
1107 0a1e74d9 Iustin Pop
  @type cl: luxi.Client
1108 0a1e74d9 Iustin Pop
  @param cl: the luxi client to use for communicating with the master;
1109 0a1e74d9 Iustin Pop
             if None, a new client will be created
1110 0a1e74d9 Iustin Pop

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

1177 0a1e74d9 Iustin Pop
  This is just a simple wrapper over the construction of the processor
1178 0a1e74d9 Iustin Pop
  instance. It should be extended to better handle feedback and
1179 0a1e74d9 Iustin Pop
  interaction functions.
1180 0a1e74d9 Iustin Pop

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

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

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

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

1230 73702ee7 Iustin Pop
  This function takes an exception instance and returns a tuple
1231 73702ee7 Iustin Pop
  consisting of two values: first, the recommended exit code, and
1232 73702ee7 Iustin Pop
  second, a string describing the error message (not
1233 73702ee7 Iustin Pop
  newline-terminated).
1234 73702ee7 Iustin Pop

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

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

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

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

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

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

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

1574 3386e7a9 Iustin Pop
  @type ts: timestamp
1575 3386e7a9 Iustin Pop
  @param ts: a timeval-type timestamp, a tuple of seconds and microseconds
1576 3386e7a9 Iustin Pop

1577 3386e7a9 Iustin Pop
  @rtype: string
1578 5fcc718f Iustin Pop
  @return: a string with the formatted timestamp
1579 3386e7a9 Iustin Pop

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

1590 2241e2b9 Iustin Pop
  The following suffixed will be recognized:
1591 2241e2b9 Iustin Pop

1592 2241e2b9 Iustin Pop
    - s: seconds
1593 2241e2b9 Iustin Pop
    - m: minutes
1594 2241e2b9 Iustin Pop
    - h: hours
1595 2241e2b9 Iustin Pop
    - d: day
1596 2241e2b9 Iustin Pop
    - w: weeks
1597 2241e2b9 Iustin Pop

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

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

1632 4040a784 Iustin Pop
  This function will also log a warning on stderr with the names of
1633 4040a784 Iustin Pop
  the online nodes.
1634 4040a784 Iustin Pop

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

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

1658 46fbdd04 Iustin Pop
  @type stream: file object
1659 46fbdd04 Iustin Pop
  @param stream: the file to which we should write
1660 46fbdd04 Iustin Pop
  @type txt: str
1661 46fbdd04 Iustin Pop
  @param txt: the message
1662 46fbdd04 Iustin Pop

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

1676 46fbdd04 Iustin Pop
  This is just a wrapper over _ToStream.
1677 46fbdd04 Iustin Pop

1678 46fbdd04 Iustin Pop
  @type txt: str
1679 46fbdd04 Iustin Pop
  @param txt: the message
1680 46fbdd04 Iustin Pop

1681 46fbdd04 Iustin Pop
  """
1682 46fbdd04 Iustin Pop
  _ToStream(sys.stdout, txt, *args)
1683 46fbdd04 Iustin Pop
1684 46fbdd04 Iustin Pop
1685 46fbdd04 Iustin Pop
def ToStderr(txt, *args):
1686 46fbdd04 Iustin Pop
  """Write a message to stderr only, bypassing the logging system
1687 46fbdd04 Iustin Pop

1688 46fbdd04 Iustin Pop
  This is just a wrapper over _ToStream.
1689 46fbdd04 Iustin Pop

1690 46fbdd04 Iustin Pop
  @type txt: str
1691 46fbdd04 Iustin Pop
  @param txt: the message
1692 46fbdd04 Iustin Pop

1693 46fbdd04 Iustin Pop
  """
1694 46fbdd04 Iustin Pop
  _ToStream(sys.stderr, txt, *args)
1695 479636a3 Iustin Pop
1696 479636a3 Iustin Pop
1697 479636a3 Iustin Pop
class JobExecutor(object):
1698 479636a3 Iustin Pop
  """Class which manages the submission and execution of multiple jobs.
1699 479636a3 Iustin Pop

1700 479636a3 Iustin Pop
  Note that instances of this class should not be reused between
1701 479636a3 Iustin Pop
  GetResults() calls.
1702 479636a3 Iustin Pop

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

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

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

1731 479636a3 Iustin Pop
    @rtype: list
1732 479636a3 Iustin Pop
    @return: list of tuples (success, job results), in the same order
1733 479636a3 Iustin Pop
        as the submitted jobs; if a job has failed, instead of the result
1734 479636a3 Iustin Pop
        there will be the error message
1735 479636a3 Iustin Pop

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

1766 479636a3 Iustin Pop
    @type wait: boolean
1767 479636a3 Iustin Pop
    @param wait: whether to wait or not
1768 479636a3 Iustin Pop

1769 479636a3 Iustin Pop
    """
1770 479636a3 Iustin Pop
    if wait:
1771 479636a3 Iustin Pop
      return self.GetResults()
1772 479636a3 Iustin Pop
    else:
1773 23b4b983 Iustin Pop
      if not self.jobs:
1774 23b4b983 Iustin Pop
        self.SubmitPending()
1775 23b4b983 Iustin Pop
      for status, result, name in self.jobs:
1776 23b4b983 Iustin Pop
        if status:
1777 23b4b983 Iustin Pop
          ToStdout("%s: %s", result, name)
1778 23b4b983 Iustin Pop
        else:
1779 23b4b983 Iustin Pop
          ToStderr("Failure for %s: %s", name, result)