Statistics
| Branch: | Tag: | Revision:

root / lib / cli.py @ b5762e2a

History | View | Annotate | Download (56.4 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 a8083063 Iustin Pop
import copy
29 685ee993 Iustin Pop
import time
30 46fbdd04 Iustin Pop
import logging
31 73702ee7 Iustin Pop
from cStringIO import StringIO
32 a8083063 Iustin Pop
33 a8083063 Iustin Pop
from ganeti import utils
34 a8083063 Iustin Pop
from ganeti import errors
35 a8083063 Iustin Pop
from ganeti import constants
36 846baef9 Iustin Pop
from ganeti import opcodes
37 ceab32dd Iustin Pop
from ganeti import luxi
38 b33e986b Iustin Pop
from ganeti import ssconf
39 4331f6cd Michael Hanselmann
from ganeti import rpc
40 a8083063 Iustin Pop
41 c38c44ad Michael Hanselmann
from optparse import (OptionParser, TitledHelpFormatter,
42 38206f3c Iustin Pop
                      Option, OptionValueError)
43 a8083063 Iustin Pop
44 03298ebe Michael Hanselmann
45 4abc4f1e Iustin Pop
__all__ = [
46 4abc4f1e Iustin Pop
  # Command line options
47 e7e09483 Iustin Pop
  "ALLOCATABLE_OPT",
48 2d5e7ae1 Iustin Pop
  "ALL_OPT",
49 e00f7a05 Iustin Pop
  "AUTO_REPLACE_OPT",
50 087ed2ed Iustin Pop
  "BACKEND_OPT",
51 baef337d Iustin Pop
  "CLEANUP_OPT",
52 4abc4f1e Iustin Pop
  "CONFIRM_OPT",
53 e32df528 Iustin Pop
  "CP_SIZE_OPT",
54 4abc4f1e Iustin Pop
  "DEBUG_OPT",
55 a0c9776a Iustin Pop
  "DEBUG_SIMERR_OPT",
56 4b038a1e Iustin Pop
  "DISKIDX_OPT",
57 e3876ccb Iustin Pop
  "DISK_OPT",
58 4b038a1e Iustin Pop
  "DISK_TEMPLATE_OPT",
59 771734c9 Iustin Pop
  "DRAINED_OPT",
60 383a3591 Iustin Pop
  "ENABLED_HV_OPT",
61 14e9e7f3 Iustin Pop
  "ERROR_CODES_OPT",
62 4abc4f1e Iustin Pop
  "FIELDS_OPT",
63 4a25828c Iustin Pop
  "FILESTORE_DIR_OPT",
64 0f87c43e Iustin Pop
  "FILESTORE_DRIVER_OPT",
65 06073e85 Guido Trotter
  "FORCE_OPT",
66 06073e85 Guido Trotter
  "FORCE_VARIANT_OPT",
67 29392516 Iustin Pop
  "GLOBAL_FILEDIR_OPT",
68 073271f6 Iustin Pop
  "HVLIST_OPT",
69 48f212d7 Iustin Pop
  "HVOPTS_OPT",
70 236fd9c4 Iustin Pop
  "HYPERVISOR_OPT",
71 4eb62659 Iustin Pop
  "IALLOCATOR_OPT",
72 82a786d5 Iustin Pop
  "IGNORE_CONSIST_OPT",
73 b6e841a8 Iustin Pop
  "IGNORE_FAILURES_OPT",
74 ee3f9578 Iustin Pop
  "IGNORE_SECONDARIES_OPT",
75 05586c90 Iustin Pop
  "IGNORE_SIZE_OPT",
76 e3646f22 Iustin Pop
  "MAC_PREFIX_OPT",
77 29392516 Iustin Pop
  "MASTER_NETDEV_OPT",
78 771734c9 Iustin Pop
  "MC_OPT",
79 7d3a9fab Iustin Pop
  "NET_OPT",
80 a14db5ff Iustin Pop
  "NEW_SECONDARY_OPT",
81 4fbc93dd Iustin Pop
  "NIC_PARAMS_OPT",
82 7edc4637 Iustin Pop
  "NODE_LIST_OPT",
83 990b7886 Iustin Pop
  "NODE_PLACEMENT_OPT",
84 4abc4f1e Iustin Pop
  "NOHDR_OPT",
85 91e0748c Iustin Pop
  "NOIPCHECK_OPT",
86 831040bf Iustin Pop
  "NOLVM_STORAGE_OPT",
87 29392516 Iustin Pop
  "NOMODIFY_ETCHOSTS_OPT",
88 26023ecd Iustin Pop
  "NONICS_OPT",
89 f2a0828c Iustin Pop
  "NONLIVE_OPT",
90 14e9e7f3 Iustin Pop
  "NONPLUS1_OPT",
91 44c44832 Iustin Pop
  "NOSHUTDOWN_OPT",
92 edeb878a Iustin Pop
  "NOSTART_OPT",
93 fcdde7f2 Iustin Pop
  "NOSSH_KEYCHECK_OPT",
94 58371861 Iustin Pop
  "NOVOTING_OPT",
95 3f75b4f3 Iustin Pop
  "NWSYNC_OPT",
96 a72d0a79 Iustin Pop
  "ON_PRIMARY_OPT",
97 feb09e6a Iustin Pop
  "ON_SECONDARY_OPT",
98 771734c9 Iustin Pop
  "OFFLINE_OPT",
99 d3ed23ff Iustin Pop
  "OS_OPT",
100 ff00c1a7 Iustin Pop
  "OS_SIZE_OPT",
101 b8d0f938 Iustin Pop
  "READD_OPT",
102 12054861 Iustin Pop
  "REBOOT_TYPE_OPT",
103 8d823629 Iustin Pop
  "SECONDARY_IP_OPT",
104 67840b40 Iustin Pop
  "SELECT_OS_OPT",
105 4abc4f1e Iustin Pop
  "SEP_OPT",
106 fdcf4d84 Iustin Pop
  "SHOWCMD_OPT",
107 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 44c44832 Iustin Pop
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 771734c9 Iustin Pop
825 de47cf8f Guido Trotter
def _ParseArgs(argv, commands, aliases):
826 c41eea6e Iustin Pop
  """Parser for the command line arguments.
827 a8083063 Iustin Pop

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

831 c41eea6e Iustin Pop
  @param argv: the command line
832 c41eea6e Iustin Pop
  @param commands: dictionary with special contents, see the design
833 c41eea6e Iustin Pop
      doc for cmdline handling
834 c41eea6e Iustin Pop
  @param aliases: dictionary with command aliases {'alias': 'target, ...}
835 098c0958 Michael Hanselmann

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

906 a8005e17 Michael Hanselmann
  Algorithm:
907 a8005e17 Michael Hanselmann

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

910 a8005e17 Michael Hanselmann
    1. For each argument in definition
911 a8005e17 Michael Hanselmann

912 a8005e17 Michael Hanselmann
      1. Keep running count of minimum number of values (min_count)
913 a8005e17 Michael Hanselmann
      1. Keep running count of maximum number of values (max_count)
914 a8005e17 Michael Hanselmann
      1. If it has an unlimited number of values
915 a8005e17 Michael Hanselmann

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

918 a8005e17 Michael Hanselmann
    1. If last argument has limited number of values
919 a8005e17 Michael Hanselmann

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

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

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

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

987 07150497 Guido Trotter
  @type os_name: string
988 07150497 Guido Trotter
  @param os_name: base name of the os
989 07150497 Guido Trotter
  @type os_variants: list or None
990 07150497 Guido Trotter
  @param os_variants: list of supported variants
991 07150497 Guido Trotter
  @rtype: list
992 07150497 Guido Trotter
  @return: list of valid names
993 07150497 Guido Trotter

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

1014 c41eea6e Iustin Pop
  @param text: the question to ask
1015 a8083063 Iustin Pop

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

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

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

1071 e9d741b6 Iustin Pop
  This exception has one argument, the ID of the job that was
1072 e9d741b6 Iustin Pop
  submitted. The handler should print this ID.
1073 e9d741b6 Iustin Pop

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

1076 e9d741b6 Iustin Pop
  """
1077 e9d741b6 Iustin Pop
1078 e9d741b6 Iustin Pop
1079 0a1e74d9 Iustin Pop
def SendJob(ops, cl=None):
1080 0a1e74d9 Iustin Pop
  """Function to submit an opcode without waiting for the results.
1081 a8083063 Iustin Pop

1082 0a1e74d9 Iustin Pop
  @type ops: list
1083 0a1e74d9 Iustin Pop
  @param ops: list of opcodes
1084 0a1e74d9 Iustin Pop
  @type cl: luxi.Client
1085 0a1e74d9 Iustin Pop
  @param cl: the luxi client to use for communicating with the master;
1086 0a1e74d9 Iustin Pop
             if None, a new client will be created
1087 a8083063 Iustin Pop

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

1100 0a1e74d9 Iustin Pop
  @type job_id: job identified
1101 0a1e74d9 Iustin Pop
  @param job_id: the job to poll for results
1102 0a1e74d9 Iustin Pop
  @type cl: luxi.Client
1103 0a1e74d9 Iustin Pop
  @param cl: the luxi client to use for communicating with the master;
1104 0a1e74d9 Iustin Pop
             if None, a new client will be created
1105 0a1e74d9 Iustin Pop

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

1172 0a1e74d9 Iustin Pop
  This is just a simple wrapper over the construction of the processor
1173 0a1e74d9 Iustin Pop
  instance. It should be extended to better handle feedback and
1174 0a1e74d9 Iustin Pop
  interaction functions.
1175 0a1e74d9 Iustin Pop

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

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

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

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

1225 73702ee7 Iustin Pop
  This function takes an exception instance and returns a tuple
1226 73702ee7 Iustin Pop
  consisting of two values: first, the recommended exit code, and
1227 73702ee7 Iustin Pop
  second, a string describing the error message (not
1228 73702ee7 Iustin Pop
  newline-terminated).
1229 73702ee7 Iustin Pop

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

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

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

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

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

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

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

1569 3386e7a9 Iustin Pop
  @type ts: timestamp
1570 3386e7a9 Iustin Pop
  @param ts: a timeval-type timestamp, a tuple of seconds and microseconds
1571 3386e7a9 Iustin Pop

1572 3386e7a9 Iustin Pop
  @rtype: string
1573 5fcc718f Iustin Pop
  @return: a string with the formatted timestamp
1574 3386e7a9 Iustin Pop

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

1585 2241e2b9 Iustin Pop
  The following suffixed will be recognized:
1586 2241e2b9 Iustin Pop

1587 2241e2b9 Iustin Pop
    - s: seconds
1588 2241e2b9 Iustin Pop
    - m: minutes
1589 2241e2b9 Iustin Pop
    - h: hours
1590 2241e2b9 Iustin Pop
    - d: day
1591 2241e2b9 Iustin Pop
    - w: weeks
1592 2241e2b9 Iustin Pop

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

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

1627 4040a784 Iustin Pop
  This function will also log a warning on stderr with the names of
1628 4040a784 Iustin Pop
  the online nodes.
1629 4040a784 Iustin Pop

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

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

1653 46fbdd04 Iustin Pop
  @type stream: file object
1654 46fbdd04 Iustin Pop
  @param stream: the file to which we should write
1655 46fbdd04 Iustin Pop
  @type txt: str
1656 46fbdd04 Iustin Pop
  @param txt: the message
1657 46fbdd04 Iustin Pop

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

1671 46fbdd04 Iustin Pop
  This is just a wrapper over _ToStream.
1672 46fbdd04 Iustin Pop

1673 46fbdd04 Iustin Pop
  @type txt: str
1674 46fbdd04 Iustin Pop
  @param txt: the message
1675 46fbdd04 Iustin Pop

1676 46fbdd04 Iustin Pop
  """
1677 46fbdd04 Iustin Pop
  _ToStream(sys.stdout, txt, *args)
1678 46fbdd04 Iustin Pop
1679 46fbdd04 Iustin Pop
1680 46fbdd04 Iustin Pop
def ToStderr(txt, *args):
1681 46fbdd04 Iustin Pop
  """Write a message to stderr only, bypassing the logging system
1682 46fbdd04 Iustin Pop

1683 46fbdd04 Iustin Pop
  This is just a wrapper over _ToStream.
1684 46fbdd04 Iustin Pop

1685 46fbdd04 Iustin Pop
  @type txt: str
1686 46fbdd04 Iustin Pop
  @param txt: the message
1687 46fbdd04 Iustin Pop

1688 46fbdd04 Iustin Pop
  """
1689 46fbdd04 Iustin Pop
  _ToStream(sys.stderr, txt, *args)
1690 479636a3 Iustin Pop
1691 479636a3 Iustin Pop
1692 479636a3 Iustin Pop
class JobExecutor(object):
1693 479636a3 Iustin Pop
  """Class which manages the submission and execution of multiple jobs.
1694 479636a3 Iustin Pop

1695 479636a3 Iustin Pop
  Note that instances of this class should not be reused between
1696 479636a3 Iustin Pop
  GetResults() calls.
1697 479636a3 Iustin Pop

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

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

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

1726 479636a3 Iustin Pop
    @rtype: list
1727 479636a3 Iustin Pop
    @return: list of tuples (success, job results), in the same order
1728 479636a3 Iustin Pop
        as the submitted jobs; if a job has failed, instead of the result
1729 479636a3 Iustin Pop
        there will be the error message
1730 479636a3 Iustin Pop

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

1761 479636a3 Iustin Pop
    @type wait: boolean
1762 479636a3 Iustin Pop
    @param wait: whether to wait or not
1763 479636a3 Iustin Pop

1764 479636a3 Iustin Pop
    """
1765 479636a3 Iustin Pop
    if wait:
1766 479636a3 Iustin Pop
      return self.GetResults()
1767 479636a3 Iustin Pop
    else:
1768 23b4b983 Iustin Pop
      if not self.jobs:
1769 23b4b983 Iustin Pop
        self.SubmitPending()
1770 23b4b983 Iustin Pop
      for status, result, name in self.jobs:
1771 23b4b983 Iustin Pop
        if status:
1772 23b4b983 Iustin Pop
          ToStdout("%s: %s", result, name)
1773 23b4b983 Iustin Pop
        else:
1774 23b4b983 Iustin Pop
          ToStderr("Failure for %s: %s", name, result)