Statistics
| Branch: | Tag: | Revision:

root / lib / cli.py @ 26d3fd2f

History | View | Annotate | Download (80.4 kB)

1 2f31098c Iustin Pop
#
2 a8083063 Iustin Pop
#
3 a8083063 Iustin Pop
4 783a6c0b Iustin Pop
# Copyright (C) 2006, 2007, 2008, 2009, 2010 Google Inc.
5 a8083063 Iustin Pop
#
6 a8083063 Iustin Pop
# This program is free software; you can redistribute it and/or modify
7 a8083063 Iustin Pop
# it under the terms of the GNU General Public License as published by
8 a8083063 Iustin Pop
# the Free Software Foundation; either version 2 of the License, or
9 a8083063 Iustin Pop
# (at your option) any later version.
10 a8083063 Iustin Pop
#
11 a8083063 Iustin Pop
# This program is distributed in the hope that it will be useful, but
12 a8083063 Iustin Pop
# WITHOUT ANY WARRANTY; without even the implied warranty of
13 a8083063 Iustin Pop
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 a8083063 Iustin Pop
# General Public License for more details.
15 a8083063 Iustin Pop
#
16 a8083063 Iustin Pop
# You should have received a copy of the GNU General Public License
17 a8083063 Iustin Pop
# along with this program; if not, write to the Free Software
18 a8083063 Iustin Pop
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 a8083063 Iustin Pop
# 02110-1301, USA.
20 a8083063 Iustin Pop
21 a8083063 Iustin Pop
22 a8083063 Iustin Pop
"""Module dealing with command line parsing"""
23 a8083063 Iustin Pop
24 a8083063 Iustin Pop
25 a8083063 Iustin Pop
import sys
26 a8083063 Iustin Pop
import textwrap
27 a8083063 Iustin Pop
import os.path
28 685ee993 Iustin Pop
import time
29 46fbdd04 Iustin Pop
import logging
30 73702ee7 Iustin Pop
from cStringIO import StringIO
31 a8083063 Iustin Pop
32 a8083063 Iustin Pop
from ganeti import utils
33 a8083063 Iustin Pop
from ganeti import errors
34 a8083063 Iustin Pop
from ganeti import constants
35 846baef9 Iustin Pop
from ganeti import opcodes
36 ceab32dd Iustin Pop
from ganeti import luxi
37 b33e986b Iustin Pop
from ganeti import ssconf
38 4331f6cd Michael Hanselmann
from ganeti import rpc
39 7e49b6ce Michael Hanselmann
from ganeti import ssh
40 cea881e5 Michael Hanselmann
from ganeti import compat
41 a744b676 Manuel Franceschini
from ganeti import netutils
42 a8083063 Iustin Pop
43 c38c44ad Michael Hanselmann
from optparse import (OptionParser, TitledHelpFormatter,
44 38206f3c Iustin Pop
                      Option, OptionValueError)
45 a8083063 Iustin Pop
46 03298ebe Michael Hanselmann
47 4abc4f1e Iustin Pop
__all__ = [
48 4abc4f1e Iustin Pop
  # Command line options
49 fdad8c4d Balazs Lecz
  "ADD_UIDS_OPT",
50 e7e09483 Iustin Pop
  "ALLOCATABLE_OPT",
51 2d5e7ae1 Iustin Pop
  "ALL_OPT",
52 4c61d894 Iustin Pop
  "AUTO_PROMOTE_OPT",
53 e00f7a05 Iustin Pop
  "AUTO_REPLACE_OPT",
54 087ed2ed Iustin Pop
  "BACKEND_OPT",
55 baef337d Iustin Pop
  "CLEANUP_OPT",
56 3db3eb2a Michael Hanselmann
  "CLUSTER_DOMAIN_SECRET_OPT",
57 4abc4f1e Iustin Pop
  "CONFIRM_OPT",
58 e32df528 Iustin Pop
  "CP_SIZE_OPT",
59 4abc4f1e Iustin Pop
  "DEBUG_OPT",
60 a0c9776a Iustin Pop
  "DEBUG_SIMERR_OPT",
61 4b038a1e Iustin Pop
  "DISKIDX_OPT",
62 e3876ccb Iustin Pop
  "DISK_OPT",
63 4b038a1e Iustin Pop
  "DISK_TEMPLATE_OPT",
64 771734c9 Iustin Pop
  "DRAINED_OPT",
65 a0a6ff34 Iustin Pop
  "DRY_RUN_OPT",
66 26591bfd Luca Bigliardi
  "DRBD_HELPER_OPT",
67 7ea7bcf6 Iustin Pop
  "EARLY_RELEASE_OPT",
68 383a3591 Iustin Pop
  "ENABLED_HV_OPT",
69 14e9e7f3 Iustin Pop
  "ERROR_CODES_OPT",
70 4abc4f1e Iustin Pop
  "FIELDS_OPT",
71 4a25828c Iustin Pop
  "FILESTORE_DIR_OPT",
72 0f87c43e Iustin Pop
  "FILESTORE_DRIVER_OPT",
73 06073e85 Guido Trotter
  "FORCE_OPT",
74 06073e85 Guido Trotter
  "FORCE_VARIANT_OPT",
75 29392516 Iustin Pop
  "GLOBAL_FILEDIR_OPT",
76 073271f6 Iustin Pop
  "HVLIST_OPT",
77 48f212d7 Iustin Pop
  "HVOPTS_OPT",
78 236fd9c4 Iustin Pop
  "HYPERVISOR_OPT",
79 4eb62659 Iustin Pop
  "IALLOCATOR_OPT",
80 bf4af505 Apollon Oikonomopoulos
  "DEFAULT_IALLOCATOR_OPT",
81 e588764d Iustin Pop
  "IDENTIFY_DEFAULTS_OPT",
82 82a786d5 Iustin Pop
  "IGNORE_CONSIST_OPT",
83 b6e841a8 Iustin Pop
  "IGNORE_FAILURES_OPT",
84 8d8d650c Michael Hanselmann
  "IGNORE_REMOVE_FAILURES_OPT",
85 ee3f9578 Iustin Pop
  "IGNORE_SECONDARIES_OPT",
86 05586c90 Iustin Pop
  "IGNORE_SIZE_OPT",
87 19b9ba9a Michael Hanselmann
  "INTERVAL_OPT",
88 e3646f22 Iustin Pop
  "MAC_PREFIX_OPT",
89 3953242f Iustin Pop
  "MAINTAIN_NODE_HEALTH_OPT",
90 29392516 Iustin Pop
  "MASTER_NETDEV_OPT",
91 771734c9 Iustin Pop
  "MC_OPT",
92 783a6c0b Iustin Pop
  "MIGRATION_MODE_OPT",
93 7d3a9fab Iustin Pop
  "NET_OPT",
94 6d4a1656 Michael Hanselmann
  "NEW_CLUSTER_CERT_OPT",
95 3db3eb2a Michael Hanselmann
  "NEW_CLUSTER_DOMAIN_SECRET_OPT",
96 6b7d5878 Michael Hanselmann
  "NEW_CONFD_HMAC_KEY_OPT",
97 6d4a1656 Michael Hanselmann
  "NEW_RAPI_CERT_OPT",
98 a14db5ff Iustin Pop
  "NEW_SECONDARY_OPT",
99 4fbc93dd Iustin Pop
  "NIC_PARAMS_OPT",
100 7edc4637 Iustin Pop
  "NODE_LIST_OPT",
101 990b7886 Iustin Pop
  "NODE_PLACEMENT_OPT",
102 5fbbd028 Guido Trotter
  "NODEGROUP_OPT",
103 26591bfd Luca Bigliardi
  "NODRBD_STORAGE_OPT",
104 4abc4f1e Iustin Pop
  "NOHDR_OPT",
105 91e0748c Iustin Pop
  "NOIPCHECK_OPT",
106 25a8792c Iustin Pop
  "NO_INSTALL_OPT",
107 460d22be Iustin Pop
  "NONAMECHECK_OPT",
108 831040bf Iustin Pop
  "NOLVM_STORAGE_OPT",
109 29392516 Iustin Pop
  "NOMODIFY_ETCHOSTS_OPT",
110 b989b9d9 Ken Wehr
  "NOMODIFY_SSH_SETUP_OPT",
111 26023ecd Iustin Pop
  "NONICS_OPT",
112 f2a0828c Iustin Pop
  "NONLIVE_OPT",
113 14e9e7f3 Iustin Pop
  "NONPLUS1_OPT",
114 44c44832 Iustin Pop
  "NOSHUTDOWN_OPT",
115 edeb878a Iustin Pop
  "NOSTART_OPT",
116 fcdde7f2 Iustin Pop
  "NOSSH_KEYCHECK_OPT",
117 58371861 Iustin Pop
  "NOVOTING_OPT",
118 3f75b4f3 Iustin Pop
  "NWSYNC_OPT",
119 a72d0a79 Iustin Pop
  "ON_PRIMARY_OPT",
120 feb09e6a Iustin Pop
  "ON_SECONDARY_OPT",
121 771734c9 Iustin Pop
  "OFFLINE_OPT",
122 062a7100 Iustin Pop
  "OSPARAMS_OPT",
123 d3ed23ff Iustin Pop
  "OS_OPT",
124 ff00c1a7 Iustin Pop
  "OS_SIZE_OPT",
125 e7323b5e Manuel Franceschini
  "PRIMARY_IP_VERSION_OPT",
126 84a5b33c Michael Hanselmann
  "PRIORITY_OPT",
127 6d4a1656 Michael Hanselmann
  "RAPI_CERT_OPT",
128 b8d0f938 Iustin Pop
  "READD_OPT",
129 12054861 Iustin Pop
  "REBOOT_TYPE_OPT",
130 8d8d650c Michael Hanselmann
  "REMOVE_INSTANCE_OPT",
131 fdad8c4d Balazs Lecz
  "REMOVE_UIDS_OPT",
132 f38ea602 Iustin Pop
  "RESERVED_LVS_OPT",
133 31d97b2a Guido Trotter
  "ROMAN_OPT",
134 8d823629 Iustin Pop
  "SECONDARY_IP_OPT",
135 67840b40 Iustin Pop
  "SELECT_OS_OPT",
136 4abc4f1e Iustin Pop
  "SEP_OPT",
137 fdcf4d84 Iustin Pop
  "SHOWCMD_OPT",
138 7e5eaaa8 Guido Trotter
  "SHUTDOWN_TIMEOUT_OPT",
139 f36d7d81 Iustin Pop
  "SINGLE_NODE_OPT",
140 df62e5db Iustin Pop
  "SRC_DIR_OPT",
141 df62e5db Iustin Pop
  "SRC_NODE_OPT",
142 4abc4f1e Iustin Pop
  "SUBMIT_OPT",
143 99a8c799 Iustin Pop
  "STATIC_OPT",
144 4abc4f1e Iustin Pop
  "SYNC_OPT",
145 4abc4f1e Iustin Pop
  "TAG_SRC_OPT",
146 b5762e2a Guido Trotter
  "TIMEOUT_OPT",
147 1338f2b4 Balazs Lecz
  "UIDPOOL_OPT",
148 4abc4f1e Iustin Pop
  "USEUNITS_OPT",
149 74adc100 Iustin Pop
  "USE_REPL_NET_OPT",
150 9cdb9578 Iustin Pop
  "VERBOSE_OPT",
151 b58726e8 Iustin Pop
  "VG_NAME_OPT",
152 1f587d3d Iustin Pop
  "YES_DOIT_OPT",
153 4abc4f1e Iustin Pop
  # Generic functions for CLI programs
154 4abc4f1e Iustin Pop
  "GenericMain",
155 d77490c5 Iustin Pop
  "GenericInstanceCreate",
156 4abc4f1e Iustin Pop
  "GetClient",
157 4abc4f1e Iustin Pop
  "GetOnlineNodes",
158 4abc4f1e Iustin Pop
  "JobExecutor",
159 4abc4f1e Iustin Pop
  "JobSubmittedException",
160 4abc4f1e Iustin Pop
  "ParseTimespec",
161 7e49b6ce Michael Hanselmann
  "RunWhileClusterStopped",
162 4abc4f1e Iustin Pop
  "SubmitOpCode",
163 4abc4f1e Iustin Pop
  "SubmitOrSend",
164 4abc4f1e Iustin Pop
  "UsesRPC",
165 4abc4f1e Iustin Pop
  # Formatting functions
166 4abc4f1e Iustin Pop
  "ToStderr", "ToStdout",
167 4abc4f1e Iustin Pop
  "FormatError",
168 4abc4f1e Iustin Pop
  "GenerateTable",
169 4abc4f1e Iustin Pop
  "AskUser",
170 4abc4f1e Iustin Pop
  "FormatTimestamp",
171 8a7f1c61 Michael Hanselmann
  "FormatLogMessage",
172 4abc4f1e Iustin Pop
  # Tags functions
173 4abc4f1e Iustin Pop
  "ListTags",
174 4abc4f1e Iustin Pop
  "AddTags",
175 4abc4f1e Iustin Pop
  "RemoveTags",
176 4abc4f1e Iustin Pop
  # command line options support infrastructure
177 4abc4f1e Iustin Pop
  "ARGS_MANY_INSTANCES",
178 4abc4f1e Iustin Pop
  "ARGS_MANY_NODES",
179 4abc4f1e Iustin Pop
  "ARGS_NONE",
180 4abc4f1e Iustin Pop
  "ARGS_ONE_INSTANCE",
181 4abc4f1e Iustin Pop
  "ARGS_ONE_NODE",
182 f9faf9c3 Renรฉ Nussbaumer
  "ARGS_ONE_OS",
183 4abc4f1e Iustin Pop
  "ArgChoice",
184 4abc4f1e Iustin Pop
  "ArgCommand",
185 4abc4f1e Iustin Pop
  "ArgFile",
186 4abc4f1e Iustin Pop
  "ArgHost",
187 4abc4f1e Iustin Pop
  "ArgInstance",
188 4abc4f1e Iustin Pop
  "ArgJobId",
189 4abc4f1e Iustin Pop
  "ArgNode",
190 f9faf9c3 Renรฉ Nussbaumer
  "ArgOs",
191 4abc4f1e Iustin Pop
  "ArgSuggest",
192 4abc4f1e Iustin Pop
  "ArgUnknown",
193 4abc4f1e Iustin Pop
  "OPT_COMPL_INST_ADD_NODES",
194 4abc4f1e Iustin Pop
  "OPT_COMPL_MANY_NODES",
195 4abc4f1e Iustin Pop
  "OPT_COMPL_ONE_IALLOCATOR",
196 4abc4f1e Iustin Pop
  "OPT_COMPL_ONE_INSTANCE",
197 4abc4f1e Iustin Pop
  "OPT_COMPL_ONE_NODE",
198 36e247e1 Guido Trotter
  "OPT_COMPL_ONE_NODEGROUP",
199 4abc4f1e Iustin Pop
  "OPT_COMPL_ONE_OS",
200 4abc4f1e Iustin Pop
  "cli_option",
201 4abc4f1e Iustin Pop
  "SplitNodeOption",
202 07150497 Guido Trotter
  "CalculateOSNames",
203 a4ebd726 Michael Hanselmann
  "ParseFields",
204 4abc4f1e Iustin Pop
  ]
205 846baef9 Iustin Pop
206 8b46606c Guido Trotter
NO_PREFIX = "no_"
207 8b46606c Guido Trotter
UN_PREFIX = "-"
208 846baef9 Iustin Pop
209 84a5b33c Michael Hanselmann
#: Priorities (sorted)
210 84a5b33c Michael Hanselmann
_PRIORITY_NAMES = [
211 84a5b33c Michael Hanselmann
  ("low", constants.OP_PRIO_LOW),
212 84a5b33c Michael Hanselmann
  ("normal", constants.OP_PRIO_NORMAL),
213 84a5b33c Michael Hanselmann
  ("high", constants.OP_PRIO_HIGH),
214 84a5b33c Michael Hanselmann
  ]
215 84a5b33c Michael Hanselmann
216 84a5b33c Michael Hanselmann
#: Priority dictionary for easier lookup
217 84a5b33c Michael Hanselmann
# TODO: Replace this and _PRIORITY_NAMES with a single sorted dictionary once
218 84a5b33c Michael Hanselmann
# we migrate to Python 2.6
219 84a5b33c Michael Hanselmann
_PRIONAME_TO_VALUE = dict(_PRIORITY_NAMES)
220 84a5b33c Michael Hanselmann
221 03298ebe Michael Hanselmann
222 863d7f46 Michael Hanselmann
class _Argument:
223 7260cfbe Iustin Pop
  def __init__(self, min=0, max=None): # pylint: disable-msg=W0622
224 863d7f46 Michael Hanselmann
    self.min = min
225 863d7f46 Michael Hanselmann
    self.max = max
226 863d7f46 Michael Hanselmann
227 863d7f46 Michael Hanselmann
  def __repr__(self):
228 863d7f46 Michael Hanselmann
    return ("<%s min=%s max=%s>" %
229 863d7f46 Michael Hanselmann
            (self.__class__.__name__, self.min, self.max))
230 863d7f46 Michael Hanselmann
231 863d7f46 Michael Hanselmann
232 863d7f46 Michael Hanselmann
class ArgSuggest(_Argument):
233 863d7f46 Michael Hanselmann
  """Suggesting argument.
234 863d7f46 Michael Hanselmann

235 863d7f46 Michael Hanselmann
  Value can be any of the ones passed to the constructor.
236 863d7f46 Michael Hanselmann

237 863d7f46 Michael Hanselmann
  """
238 7260cfbe Iustin Pop
  # pylint: disable-msg=W0622
239 863d7f46 Michael Hanselmann
  def __init__(self, min=0, max=None, choices=None):
240 863d7f46 Michael Hanselmann
    _Argument.__init__(self, min=min, max=max)
241 863d7f46 Michael Hanselmann
    self.choices = choices
242 863d7f46 Michael Hanselmann
243 863d7f46 Michael Hanselmann
  def __repr__(self):
244 863d7f46 Michael Hanselmann
    return ("<%s min=%s max=%s choices=%r>" %
245 863d7f46 Michael Hanselmann
            (self.__class__.__name__, self.min, self.max, self.choices))
246 863d7f46 Michael Hanselmann
247 863d7f46 Michael Hanselmann
248 863d7f46 Michael Hanselmann
class ArgChoice(ArgSuggest):
249 863d7f46 Michael Hanselmann
  """Choice argument.
250 863d7f46 Michael Hanselmann

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

254 863d7f46 Michael Hanselmann
  """
255 863d7f46 Michael Hanselmann
256 863d7f46 Michael Hanselmann
257 863d7f46 Michael Hanselmann
class ArgUnknown(_Argument):
258 863d7f46 Michael Hanselmann
  """Unknown argument to program (e.g. determined at runtime).
259 863d7f46 Michael Hanselmann

260 863d7f46 Michael Hanselmann
  """
261 863d7f46 Michael Hanselmann
262 863d7f46 Michael Hanselmann
263 863d7f46 Michael Hanselmann
class ArgInstance(_Argument):
264 863d7f46 Michael Hanselmann
  """Instances argument.
265 863d7f46 Michael Hanselmann

266 863d7f46 Michael Hanselmann
  """
267 863d7f46 Michael Hanselmann
268 863d7f46 Michael Hanselmann
269 863d7f46 Michael Hanselmann
class ArgNode(_Argument):
270 863d7f46 Michael Hanselmann
  """Node argument.
271 863d7f46 Michael Hanselmann

272 863d7f46 Michael Hanselmann
  """
273 863d7f46 Michael Hanselmann
274 863d7f46 Michael Hanselmann
class ArgJobId(_Argument):
275 863d7f46 Michael Hanselmann
  """Job ID argument.
276 863d7f46 Michael Hanselmann

277 863d7f46 Michael Hanselmann
  """
278 863d7f46 Michael Hanselmann
279 863d7f46 Michael Hanselmann
280 863d7f46 Michael Hanselmann
class ArgFile(_Argument):
281 863d7f46 Michael Hanselmann
  """File path argument.
282 863d7f46 Michael Hanselmann

283 863d7f46 Michael Hanselmann
  """
284 863d7f46 Michael Hanselmann
285 863d7f46 Michael Hanselmann
286 863d7f46 Michael Hanselmann
class ArgCommand(_Argument):
287 863d7f46 Michael Hanselmann
  """Command argument.
288 863d7f46 Michael Hanselmann

289 863d7f46 Michael Hanselmann
  """
290 863d7f46 Michael Hanselmann
291 863d7f46 Michael Hanselmann
292 83ec7961 Michael Hanselmann
class ArgHost(_Argument):
293 83ec7961 Michael Hanselmann
  """Host argument.
294 83ec7961 Michael Hanselmann

295 83ec7961 Michael Hanselmann
  """
296 83ec7961 Michael Hanselmann
297 83ec7961 Michael Hanselmann
298 f9faf9c3 Renรฉ Nussbaumer
class ArgOs(_Argument):
299 f9faf9c3 Renรฉ Nussbaumer
  """OS argument.
300 f9faf9c3 Renรฉ Nussbaumer

301 f9faf9c3 Renรฉ Nussbaumer
  """
302 f9faf9c3 Renรฉ Nussbaumer
303 f9faf9c3 Renรฉ Nussbaumer
304 4a265c08 Michael Hanselmann
ARGS_NONE = []
305 4a265c08 Michael Hanselmann
ARGS_MANY_INSTANCES = [ArgInstance()]
306 4a265c08 Michael Hanselmann
ARGS_MANY_NODES = [ArgNode()]
307 4a265c08 Michael Hanselmann
ARGS_ONE_INSTANCE = [ArgInstance(min=1, max=1)]
308 4a265c08 Michael Hanselmann
ARGS_ONE_NODE = [ArgNode(min=1, max=1)]
309 f9faf9c3 Renรฉ Nussbaumer
ARGS_ONE_OS = [ArgOs(min=1, max=1)]
310 4a265c08 Michael Hanselmann
311 4a265c08 Michael Hanselmann
312 846baef9 Iustin Pop
def _ExtractTagsObject(opts, args):
313 846baef9 Iustin Pop
  """Extract the tag type object.
314 846baef9 Iustin Pop

315 846baef9 Iustin Pop
  Note that this function will modify its args parameter.
316 846baef9 Iustin Pop

317 846baef9 Iustin Pop
  """
318 846baef9 Iustin Pop
  if not hasattr(opts, "tag_type"):
319 846baef9 Iustin Pop
    raise errors.ProgrammerError("tag_type not passed to _ExtractTagsObject")
320 846baef9 Iustin Pop
  kind = opts.tag_type
321 846baef9 Iustin Pop
  if kind == constants.TAG_CLUSTER:
322 846baef9 Iustin Pop
    retval = kind, kind
323 846baef9 Iustin Pop
  elif kind == constants.TAG_NODE or kind == constants.TAG_INSTANCE:
324 846baef9 Iustin Pop
    if not args:
325 0c434948 Iustin Pop
      raise errors.OpPrereqError("no arguments passed to the command")
326 846baef9 Iustin Pop
    name = args.pop(0)
327 846baef9 Iustin Pop
    retval = kind, name
328 846baef9 Iustin Pop
  else:
329 846baef9 Iustin Pop
    raise errors.ProgrammerError("Unhandled tag type '%s'" % kind)
330 846baef9 Iustin Pop
  return retval
331 846baef9 Iustin Pop
332 846baef9 Iustin Pop
333 810c50b7 Iustin Pop
def _ExtendTags(opts, args):
334 810c50b7 Iustin Pop
  """Extend the args if a source file has been given.
335 810c50b7 Iustin Pop

336 810c50b7 Iustin Pop
  This function will extend the tags with the contents of the file
337 810c50b7 Iustin Pop
  passed in the 'tags_source' attribute of the opts parameter. A file
338 810c50b7 Iustin Pop
  named '-' will be replaced by stdin.
339 810c50b7 Iustin Pop

340 810c50b7 Iustin Pop
  """
341 810c50b7 Iustin Pop
  fname = opts.tags_source
342 810c50b7 Iustin Pop
  if fname is None:
343 810c50b7 Iustin Pop
    return
344 810c50b7 Iustin Pop
  if fname == "-":
345 810c50b7 Iustin Pop
    new_fh = sys.stdin
346 810c50b7 Iustin Pop
  else:
347 810c50b7 Iustin Pop
    new_fh = open(fname, "r")
348 810c50b7 Iustin Pop
  new_data = []
349 810c50b7 Iustin Pop
  try:
350 810c50b7 Iustin Pop
    # we don't use the nice 'new_data = [line.strip() for line in fh]'
351 810c50b7 Iustin Pop
    # because of python bug 1633941
352 810c50b7 Iustin Pop
    while True:
353 810c50b7 Iustin Pop
      line = new_fh.readline()
354 810c50b7 Iustin Pop
      if not line:
355 810c50b7 Iustin Pop
        break
356 810c50b7 Iustin Pop
      new_data.append(line.strip())
357 810c50b7 Iustin Pop
  finally:
358 810c50b7 Iustin Pop
    new_fh.close()
359 810c50b7 Iustin Pop
  args.extend(new_data)
360 810c50b7 Iustin Pop
361 810c50b7 Iustin Pop
362 846baef9 Iustin Pop
def ListTags(opts, args):
363 846baef9 Iustin Pop
  """List the tags on a given object.
364 846baef9 Iustin Pop

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

370 846baef9 Iustin Pop
  """
371 846baef9 Iustin Pop
  kind, name = _ExtractTagsObject(opts, args)
372 7699c3af Iustin Pop
  cl = GetClient()
373 7699c3af Iustin Pop
  result = cl.QueryTags(kind, name)
374 846baef9 Iustin Pop
  result = list(result)
375 846baef9 Iustin Pop
  result.sort()
376 846baef9 Iustin Pop
  for tag in result:
377 03298ebe Michael Hanselmann
    ToStdout(tag)
378 846baef9 Iustin Pop
379 846baef9 Iustin Pop
380 846baef9 Iustin Pop
def AddTags(opts, args):
381 846baef9 Iustin Pop
  """Add tags on a given object.
382 846baef9 Iustin Pop

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

388 846baef9 Iustin Pop
  """
389 846baef9 Iustin Pop
  kind, name = _ExtractTagsObject(opts, args)
390 810c50b7 Iustin Pop
  _ExtendTags(opts, args)
391 846baef9 Iustin Pop
  if not args:
392 846baef9 Iustin Pop
    raise errors.OpPrereqError("No tags to be added")
393 846baef9 Iustin Pop
  op = opcodes.OpAddTags(kind=kind, name=name, tags=args)
394 af1a81d1 Michael Hanselmann
  SubmitOpCode(op, opts=opts)
395 846baef9 Iustin Pop
396 846baef9 Iustin Pop
397 846baef9 Iustin Pop
def RemoveTags(opts, args):
398 846baef9 Iustin Pop
  """Remove tags from a given object.
399 846baef9 Iustin Pop

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

405 846baef9 Iustin Pop
  """
406 846baef9 Iustin Pop
  kind, name = _ExtractTagsObject(opts, args)
407 810c50b7 Iustin Pop
  _ExtendTags(opts, args)
408 846baef9 Iustin Pop
  if not args:
409 846baef9 Iustin Pop
    raise errors.OpPrereqError("No tags to be removed")
410 846baef9 Iustin Pop
  op = opcodes.OpDelTags(kind=kind, name=name, tags=args)
411 af1a81d1 Michael Hanselmann
  SubmitOpCode(op, opts=opts)
412 846baef9 Iustin Pop
413 a8083063 Iustin Pop
414 8929d28c Iustin Pop
def check_unit(option, opt, value): # pylint: disable-msg=W0613
415 65fe4693 Iustin Pop
  """OptParsers custom converter for units.
416 65fe4693 Iustin Pop

417 65fe4693 Iustin Pop
  """
418 a8083063 Iustin Pop
  try:
419 a8083063 Iustin Pop
    return utils.ParseUnit(value)
420 a8083063 Iustin Pop
  except errors.UnitParseError, err:
421 3ecf6786 Iustin Pop
    raise OptionValueError("option %s: %s" % (opt, err))
422 a8083063 Iustin Pop
423 a8083063 Iustin Pop
424 a8469393 Iustin Pop
def _SplitKeyVal(opt, data):
425 a8469393 Iustin Pop
  """Convert a KeyVal string into a dict.
426 a8469393 Iustin Pop

427 a8469393 Iustin Pop
  This function will convert a key=val[,...] string into a dict. Empty
428 a8469393 Iustin Pop
  values will be converted specially: keys which have the prefix 'no_'
429 a8469393 Iustin Pop
  will have the value=False and the prefix stripped, the others will
430 a8469393 Iustin Pop
  have value=True.
431 a8469393 Iustin Pop

432 a8469393 Iustin Pop
  @type opt: string
433 a8469393 Iustin Pop
  @param opt: a string holding the option name for which we process the
434 a8469393 Iustin Pop
      data, used in building error messages
435 a8469393 Iustin Pop
  @type data: string
436 a8469393 Iustin Pop
  @param data: a string of the format key=val,key=val,...
437 a8469393 Iustin Pop
  @rtype: dict
438 a8469393 Iustin Pop
  @return: {key=val, key=val}
439 a8469393 Iustin Pop
  @raises errors.ParameterError: if there are duplicate keys
440 a8469393 Iustin Pop

441 a8469393 Iustin Pop
  """
442 a8469393 Iustin Pop
  kv_dict = {}
443 4f31882e Guido Trotter
  if data:
444 1b3a7656 Iustin Pop
    for elem in utils.UnescapeAndSplit(data, sep=","):
445 4f31882e Guido Trotter
      if "=" in elem:
446 4f31882e Guido Trotter
        key, val = elem.split("=", 1)
447 a8469393 Iustin Pop
      else:
448 4f31882e Guido Trotter
        if elem.startswith(NO_PREFIX):
449 4f31882e Guido Trotter
          key, val = elem[len(NO_PREFIX):], False
450 4f31882e Guido Trotter
        elif elem.startswith(UN_PREFIX):
451 4f31882e Guido Trotter
          key, val = elem[len(UN_PREFIX):], None
452 4f31882e Guido Trotter
        else:
453 4f31882e Guido Trotter
          key, val = elem, True
454 4f31882e Guido Trotter
      if key in kv_dict:
455 4f31882e Guido Trotter
        raise errors.ParameterError("Duplicate key '%s' in option %s" %
456 4f31882e Guido Trotter
                                    (key, opt))
457 4f31882e Guido Trotter
      kv_dict[key] = val
458 a8469393 Iustin Pop
  return kv_dict
459 a8469393 Iustin Pop
460 a8469393 Iustin Pop
461 8929d28c Iustin Pop
def check_ident_key_val(option, opt, value):  # pylint: disable-msg=W0613
462 552c8dff Michael Hanselmann
  """Custom parser for ident:key=val,key=val options.
463 552c8dff Michael Hanselmann

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

467 a8469393 Iustin Pop
  """
468 a8469393 Iustin Pop
  if ":" not in value:
469 8b46606c Guido Trotter
    ident, rest = value, ''
470 a8469393 Iustin Pop
  else:
471 a8469393 Iustin Pop
    ident, rest = value.split(":", 1)
472 8b46606c Guido Trotter
473 8b46606c Guido Trotter
  if ident.startswith(NO_PREFIX):
474 8b46606c Guido Trotter
    if rest:
475 8b46606c Guido Trotter
      msg = "Cannot pass options when removing parameter groups: %s" % value
476 8b46606c Guido Trotter
      raise errors.ParameterError(msg)
477 8b46606c Guido Trotter
    retval = (ident[len(NO_PREFIX):], False)
478 8b46606c Guido Trotter
  elif ident.startswith(UN_PREFIX):
479 8b46606c Guido Trotter
    if rest:
480 8b46606c Guido Trotter
      msg = "Cannot pass options when removing parameter groups: %s" % value
481 8b46606c Guido Trotter
      raise errors.ParameterError(msg)
482 8b46606c Guido Trotter
    retval = (ident[len(UN_PREFIX):], None)
483 8b46606c Guido Trotter
  else:
484 a8469393 Iustin Pop
    kv_dict = _SplitKeyVal(opt, rest)
485 a8469393 Iustin Pop
    retval = (ident, kv_dict)
486 a8469393 Iustin Pop
  return retval
487 a8469393 Iustin Pop
488 a8469393 Iustin Pop
489 8929d28c Iustin Pop
def check_key_val(option, opt, value):  # pylint: disable-msg=W0613
490 552c8dff Michael Hanselmann
  """Custom parser class for key=val,key=val options.
491 552c8dff Michael Hanselmann

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

494 a8469393 Iustin Pop
  """
495 a8469393 Iustin Pop
  return _SplitKeyVal(opt, value)
496 a8469393 Iustin Pop
497 a8469393 Iustin Pop
498 e7b61bb0 Iustin Pop
def check_bool(option, opt, value): # pylint: disable-msg=W0613
499 e7b61bb0 Iustin Pop
  """Custom parser for yes/no options.
500 e7b61bb0 Iustin Pop

501 e7b61bb0 Iustin Pop
  This will store the parsed value as either True or False.
502 e7b61bb0 Iustin Pop

503 e7b61bb0 Iustin Pop
  """
504 e7b61bb0 Iustin Pop
  value = value.lower()
505 e7b61bb0 Iustin Pop
  if value == constants.VALUE_FALSE or value == "no":
506 e7b61bb0 Iustin Pop
    return False
507 e7b61bb0 Iustin Pop
  elif value == constants.VALUE_TRUE or value == "yes":
508 e7b61bb0 Iustin Pop
    return True
509 e7b61bb0 Iustin Pop
  else:
510 e7b61bb0 Iustin Pop
    raise errors.ParameterError("Invalid boolean value '%s'" % value)
511 e7b61bb0 Iustin Pop
512 e7b61bb0 Iustin Pop
513 63d44c55 Michael Hanselmann
# completion_suggestion is normally a list. Using numeric values not evaluating
514 63d44c55 Michael Hanselmann
# to False for dynamic completion.
515 63d44c55 Michael Hanselmann
(OPT_COMPL_MANY_NODES,
516 63d44c55 Michael Hanselmann
 OPT_COMPL_ONE_NODE,
517 63d44c55 Michael Hanselmann
 OPT_COMPL_ONE_INSTANCE,
518 63d44c55 Michael Hanselmann
 OPT_COMPL_ONE_OS,
519 2d3ed64b Michael Hanselmann
 OPT_COMPL_ONE_IALLOCATOR,
520 36e247e1 Guido Trotter
 OPT_COMPL_INST_ADD_NODES,
521 36e247e1 Guido Trotter
 OPT_COMPL_ONE_NODEGROUP) = range(100, 107)
522 63d44c55 Michael Hanselmann
523 63d44c55 Michael Hanselmann
OPT_COMPL_ALL = frozenset([
524 63d44c55 Michael Hanselmann
  OPT_COMPL_MANY_NODES,
525 63d44c55 Michael Hanselmann
  OPT_COMPL_ONE_NODE,
526 63d44c55 Michael Hanselmann
  OPT_COMPL_ONE_INSTANCE,
527 63d44c55 Michael Hanselmann
  OPT_COMPL_ONE_OS,
528 63d44c55 Michael Hanselmann
  OPT_COMPL_ONE_IALLOCATOR,
529 2d3ed64b Michael Hanselmann
  OPT_COMPL_INST_ADD_NODES,
530 36e247e1 Guido Trotter
  OPT_COMPL_ONE_NODEGROUP,
531 63d44c55 Michael Hanselmann
  ])
532 63d44c55 Michael Hanselmann
533 63d44c55 Michael Hanselmann
534 552c8dff Michael Hanselmann
class CliOption(Option):
535 552c8dff Michael Hanselmann
  """Custom option class for optparse.
536 a8469393 Iustin Pop

537 a8469393 Iustin Pop
  """
538 863d7f46 Michael Hanselmann
  ATTRS = Option.ATTRS + [
539 863d7f46 Michael Hanselmann
    "completion_suggest",
540 863d7f46 Michael Hanselmann
    ]
541 552c8dff Michael Hanselmann
  TYPES = Option.TYPES + (
542 552c8dff Michael Hanselmann
    "identkeyval",
543 552c8dff Michael Hanselmann
    "keyval",
544 552c8dff Michael Hanselmann
    "unit",
545 e7b61bb0 Iustin Pop
    "bool",
546 552c8dff Michael Hanselmann
    )
547 552c8dff Michael Hanselmann
  TYPE_CHECKER = Option.TYPE_CHECKER.copy()
548 552c8dff Michael Hanselmann
  TYPE_CHECKER["identkeyval"] = check_ident_key_val
549 a8469393 Iustin Pop
  TYPE_CHECKER["keyval"] = check_key_val
550 552c8dff Michael Hanselmann
  TYPE_CHECKER["unit"] = check_unit
551 e7b61bb0 Iustin Pop
  TYPE_CHECKER["bool"] = check_bool
552 a8469393 Iustin Pop
553 a8469393 Iustin Pop
554 a8083063 Iustin Pop
# optparse.py sets make_option, so we do it for our own option class, too
555 a8083063 Iustin Pop
cli_option = CliOption
556 a8083063 Iustin Pop
557 a8083063 Iustin Pop
558 771734c9 Iustin Pop
_YORNO = "yes|no"
559 771734c9 Iustin Pop
560 ea34193f Iustin Pop
DEBUG_OPT = cli_option("-d", "--debug", default=0, action="count",
561 ea34193f Iustin Pop
                       help="Increase debugging level")
562 c38c44ad Michael Hanselmann
563 c38c44ad Michael Hanselmann
NOHDR_OPT = cli_option("--no-headers", default=False,
564 c38c44ad Michael Hanselmann
                       action="store_true", dest="no_headers",
565 c38c44ad Michael Hanselmann
                       help="Don't display column headers")
566 c38c44ad Michael Hanselmann
567 c38c44ad Michael Hanselmann
SEP_OPT = cli_option("--separator", default=None,
568 c38c44ad Michael Hanselmann
                     action="store", dest="separator",
569 c38c44ad Michael Hanselmann
                     help=("Separator between output fields"
570 c38c44ad Michael Hanselmann
                           " (defaults to one space)"))
571 c38c44ad Michael Hanselmann
572 c38c44ad Michael Hanselmann
USEUNITS_OPT = cli_option("--units", default=None,
573 c38c44ad Michael Hanselmann
                          dest="units", choices=('h', 'm', 'g', 't'),
574 c38c44ad Michael Hanselmann
                          help="Specify units for output (one of hmgt)")
575 c38c44ad Michael Hanselmann
576 c38c44ad Michael Hanselmann
FIELDS_OPT = cli_option("-o", "--output", dest="output", action="store",
577 c38c44ad Michael Hanselmann
                        type="string", metavar="FIELDS",
578 c38c44ad Michael Hanselmann
                        help="Comma separated list of output fields")
579 c38c44ad Michael Hanselmann
580 c38c44ad Michael Hanselmann
FORCE_OPT = cli_option("-f", "--force", dest="force", action="store_true",
581 c38c44ad Michael Hanselmann
                       default=False, help="Force the operation")
582 c38c44ad Michael Hanselmann
583 c38c44ad Michael Hanselmann
CONFIRM_OPT = cli_option("--yes", dest="confirm", action="store_true",
584 c38c44ad Michael Hanselmann
                         default=False, help="Do not require confirmation")
585 c38c44ad Michael Hanselmann
586 c38c44ad Michael Hanselmann
TAG_SRC_OPT = cli_option("--from", dest="tags_source",
587 c38c44ad Michael Hanselmann
                         default=None, help="File with tag names")
588 c38c44ad Michael Hanselmann
589 c38c44ad Michael Hanselmann
SUBMIT_OPT = cli_option("--submit", dest="submit_only",
590 c38c44ad Michael Hanselmann
                        default=False, action="store_true",
591 c38c44ad Michael Hanselmann
                        help=("Submit the job and return the job ID, but"
592 c38c44ad Michael Hanselmann
                              " don't wait for the job to finish"))
593 c38c44ad Michael Hanselmann
594 c38c44ad Michael Hanselmann
SYNC_OPT = cli_option("--sync", dest="do_locking",
595 c38c44ad Michael Hanselmann
                      default=False, action="store_true",
596 c38c44ad Michael Hanselmann
                      help=("Grab locks while doing the queries"
597 c38c44ad Michael Hanselmann
                            " in order to ensure more consistent results"))
598 c38c44ad Michael Hanselmann
599 a0a6ff34 Iustin Pop
DRY_RUN_OPT = cli_option("--dry-run", default=False,
600 a0a6ff34 Iustin Pop
                         action="store_true",
601 a0a6ff34 Iustin Pop
                         help=("Do not execute the operation, just run the"
602 a0a6ff34 Iustin Pop
                               " check steps and verify it it could be"
603 a0a6ff34 Iustin Pop
                               " executed"))
604 c38c44ad Michael Hanselmann
605 9cdb9578 Iustin Pop
VERBOSE_OPT = cli_option("-v", "--verbose", default=False,
606 9cdb9578 Iustin Pop
                         action="store_true",
607 9cdb9578 Iustin Pop
                         help="Increase the verbosity of the operation")
608 9cdb9578 Iustin Pop
609 a0c9776a Iustin Pop
DEBUG_SIMERR_OPT = cli_option("--debug-simulate-errors", default=False,
610 a0c9776a Iustin Pop
                              action="store_true", dest="simulate_errors",
611 a0c9776a Iustin Pop
                              help="Debugging option that makes the operation"
612 a0c9776a Iustin Pop
                              " treat most runtime checks as failed")
613 a0c9776a Iustin Pop
614 3f75b4f3 Iustin Pop
NWSYNC_OPT = cli_option("--no-wait-for-sync", dest="wait_for_sync",
615 3f75b4f3 Iustin Pop
                        default=True, action="store_false",
616 3f75b4f3 Iustin Pop
                        help="Don't wait for sync (DANGEROUS!)")
617 3f75b4f3 Iustin Pop
618 4f365444 Iustin Pop
DISK_TEMPLATE_OPT = cli_option("-t", "--disk-template", dest="disk_template",
619 4f365444 Iustin Pop
                               help="Custom disk setup (diskless, file,"
620 4f365444 Iustin Pop
                               " plain or drbd)",
621 4f365444 Iustin Pop
                               default=None, metavar="TEMPL",
622 4f365444 Iustin Pop
                               choices=list(constants.DISK_TEMPLATES))
623 4f365444 Iustin Pop
624 26023ecd Iustin Pop
NONICS_OPT = cli_option("--no-nics", default=False, action="store_true",
625 26023ecd Iustin Pop
                        help="Do not create any network cards for"
626 26023ecd Iustin Pop
                        " the instance")
627 26023ecd Iustin Pop
628 4a25828c Iustin Pop
FILESTORE_DIR_OPT = cli_option("--file-storage-dir", dest="file_storage_dir",
629 4a25828c Iustin Pop
                               help="Relative path under default cluster-wide"
630 4a25828c Iustin Pop
                               " file storage dir to store file-based disks",
631 4a25828c Iustin Pop
                               default=None, metavar="<DIR>")
632 4a25828c Iustin Pop
633 0f87c43e Iustin Pop
FILESTORE_DRIVER_OPT = cli_option("--file-driver", dest="file_driver",
634 0f87c43e Iustin Pop
                                  help="Driver to use for image files",
635 0f87c43e Iustin Pop
                                  default="loop", metavar="<DRIVER>",
636 0f87c43e Iustin Pop
                                  choices=list(constants.FILE_DRIVER))
637 0f87c43e Iustin Pop
638 4eb62659 Iustin Pop
IALLOCATOR_OPT = cli_option("-I", "--iallocator", metavar="<NAME>",
639 4eb62659 Iustin Pop
                            help="Select nodes for the instance automatically"
640 4eb62659 Iustin Pop
                            " using the <NAME> iallocator plugin",
641 4eb62659 Iustin Pop
                            default=None, type="string",
642 4eb62659 Iustin Pop
                            completion_suggest=OPT_COMPL_ONE_IALLOCATOR)
643 4eb62659 Iustin Pop
644 bf4af505 Apollon Oikonomopoulos
DEFAULT_IALLOCATOR_OPT = cli_option("-I", "--default-iallocator",
645 bf4af505 Apollon Oikonomopoulos
                            metavar="<NAME>",
646 bf4af505 Apollon Oikonomopoulos
                            help="Set the default instance allocator plugin",
647 bf4af505 Apollon Oikonomopoulos
                            default=None, type="string",
648 bf4af505 Apollon Oikonomopoulos
                            completion_suggest=OPT_COMPL_ONE_IALLOCATOR)
649 bf4af505 Apollon Oikonomopoulos
650 d3ed23ff Iustin Pop
OS_OPT = cli_option("-o", "--os-type", dest="os", help="What OS to run",
651 d3ed23ff Iustin Pop
                    metavar="<os>",
652 d3ed23ff Iustin Pop
                    completion_suggest=OPT_COMPL_ONE_OS)
653 d3ed23ff Iustin Pop
654 062a7100 Iustin Pop
OSPARAMS_OPT = cli_option("-O", "--os-parameters", dest="osparams",
655 062a7100 Iustin Pop
                         type="keyval", default={},
656 062a7100 Iustin Pop
                         help="OS parameters")
657 062a7100 Iustin Pop
658 06073e85 Guido Trotter
FORCE_VARIANT_OPT = cli_option("--force-variant", dest="force_variant",
659 06073e85 Guido Trotter
                               action="store_true", default=False,
660 06073e85 Guido Trotter
                               help="Force an unknown variant")
661 06073e85 Guido Trotter
662 25a8792c Iustin Pop
NO_INSTALL_OPT = cli_option("--no-install", dest="no_install",
663 25a8792c Iustin Pop
                            action="store_true", default=False,
664 25a8792c Iustin Pop
                            help="Do not install the OS (will"
665 25a8792c Iustin Pop
                            " enable no-start)")
666 25a8792c Iustin Pop
667 087ed2ed Iustin Pop
BACKEND_OPT = cli_option("-B", "--backend-parameters", dest="beparams",
668 087ed2ed Iustin Pop
                         type="keyval", default={},
669 087ed2ed Iustin Pop
                         help="Backend parameters")
670 48f212d7 Iustin Pop
671 48f212d7 Iustin Pop
HVOPTS_OPT =  cli_option("-H", "--hypervisor-parameters", type="keyval",
672 48f212d7 Iustin Pop
                         default={}, dest="hvparams",
673 48f212d7 Iustin Pop
                         help="Hypervisor parameters")
674 087ed2ed Iustin Pop
675 236fd9c4 Iustin Pop
HYPERVISOR_OPT = cli_option("-H", "--hypervisor-parameters", dest="hypervisor",
676 236fd9c4 Iustin Pop
                            help="Hypervisor and hypervisor options, in the"
677 236fd9c4 Iustin Pop
                            " format hypervisor:option=value,option=value,...",
678 236fd9c4 Iustin Pop
                            default=None, type="identkeyval")
679 073271f6 Iustin Pop
680 073271f6 Iustin Pop
HVLIST_OPT = cli_option("-H", "--hypervisor-parameters", dest="hvparams",
681 073271f6 Iustin Pop
                        help="Hypervisor and hypervisor options, in the"
682 073271f6 Iustin Pop
                        " format hypervisor:option=value,option=value,...",
683 073271f6 Iustin Pop
                        default=[], action="append", type="identkeyval")
684 236fd9c4 Iustin Pop
685 91e0748c Iustin Pop
NOIPCHECK_OPT = cli_option("--no-ip-check", dest="ip_check", default=True,
686 91e0748c Iustin Pop
                           action="store_false",
687 91e0748c Iustin Pop
                           help="Don't check that the instance's IP"
688 91e0748c Iustin Pop
                           " is alive")
689 91e0748c Iustin Pop
690 460d22be Iustin Pop
NONAMECHECK_OPT = cli_option("--no-name-check", dest="name_check",
691 460d22be Iustin Pop
                             default=True, action="store_false",
692 460d22be Iustin Pop
                             help="Don't check that the instance's name"
693 460d22be Iustin Pop
                             " is resolvable")
694 460d22be Iustin Pop
695 7d3a9fab Iustin Pop
NET_OPT = cli_option("--net",
696 7d3a9fab Iustin Pop
                     help="NIC parameters", default=[],
697 7d3a9fab Iustin Pop
                     dest="nics", action="append", type="identkeyval")
698 e3876ccb Iustin Pop
699 e3876ccb Iustin Pop
DISK_OPT = cli_option("--disk", help="Disk parameters", default=[],
700 e3876ccb Iustin Pop
                      dest="disks", action="append", type="identkeyval")
701 91e0748c Iustin Pop
702 4b038a1e Iustin Pop
DISKIDX_OPT = cli_option("--disks", dest="disks", default=None,
703 4b038a1e Iustin Pop
                         help="Comma-separated list of disks"
704 4b038a1e Iustin Pop
                         " indices to act on (e.g. 0,2) (optional,"
705 4b038a1e Iustin Pop
                         " defaults to all disks)")
706 4b038a1e Iustin Pop
707 ff00c1a7 Iustin Pop
OS_SIZE_OPT = cli_option("-s", "--os-size", dest="sd_size",
708 ff00c1a7 Iustin Pop
                         help="Enforces a single-disk configuration using the"
709 ff00c1a7 Iustin Pop
                         " given disk size, in MiB unless a suffix is used",
710 ff00c1a7 Iustin Pop
                         default=None, type="unit", metavar="<size>")
711 ff00c1a7 Iustin Pop
712 82a786d5 Iustin Pop
IGNORE_CONSIST_OPT = cli_option("--ignore-consistency",
713 82a786d5 Iustin Pop
                                dest="ignore_consistency",
714 82a786d5 Iustin Pop
                                action="store_true", default=False,
715 82a786d5 Iustin Pop
                                help="Ignore the consistency of the disks on"
716 82a786d5 Iustin Pop
                                " the secondary")
717 82a786d5 Iustin Pop
718 f2a0828c Iustin Pop
NONLIVE_OPT = cli_option("--non-live", dest="live",
719 f2a0828c Iustin Pop
                         default=True, action="store_false",
720 f2a0828c Iustin Pop
                         help="Do a non-live migration (this usually means"
721 f2a0828c Iustin Pop
                         " freeze the instance, save the state, transfer and"
722 f2a0828c Iustin Pop
                         " only then resume running on the secondary node)")
723 f2a0828c Iustin Pop
724 783a6c0b Iustin Pop
MIGRATION_MODE_OPT = cli_option("--migration-mode", dest="migration_mode",
725 e71b9ef4 Iustin Pop
                                default=None,
726 783a6c0b Iustin Pop
                                choices=list(constants.HT_MIGRATION_MODES),
727 783a6c0b Iustin Pop
                                help="Override default migration mode (choose"
728 e71b9ef4 Iustin Pop
                                " either live or non-live")
729 e71b9ef4 Iustin Pop
730 990b7886 Iustin Pop
NODE_PLACEMENT_OPT = cli_option("-n", "--node", dest="node",
731 990b7886 Iustin Pop
                                help="Target node and optional secondary node",
732 990b7886 Iustin Pop
                                metavar="<pnode>[:<snode>]",
733 990b7886 Iustin Pop
                                completion_suggest=OPT_COMPL_INST_ADD_NODES)
734 990b7886 Iustin Pop
735 7edc4637 Iustin Pop
NODE_LIST_OPT = cli_option("-n", "--node", dest="nodes", default=[],
736 7edc4637 Iustin Pop
                           action="append", metavar="<node>",
737 7edc4637 Iustin Pop
                           help="Use only this node (can be used multiple"
738 7edc4637 Iustin Pop
                           " times, if not given defaults to all nodes)",
739 7edc4637 Iustin Pop
                           completion_suggest=OPT_COMPL_ONE_NODE)
740 f36d7d81 Iustin Pop
741 5fbbd028 Guido Trotter
NODEGROUP_OPT = cli_option("-g", "--nodegroup",
742 5fbbd028 Guido Trotter
                           dest="nodegroup",
743 5fbbd028 Guido Trotter
                           help="Node group (name or uuid)",
744 5fbbd028 Guido Trotter
                           metavar="<nodegroup>",
745 5fbbd028 Guido Trotter
                           default=None, type="string",
746 5fbbd028 Guido Trotter
                           completion_suggest=OPT_COMPL_ONE_NODEGROUP)
747 5fbbd028 Guido Trotter
748 f36d7d81 Iustin Pop
SINGLE_NODE_OPT = cli_option("-n", "--node", dest="node", help="Target node",
749 f36d7d81 Iustin Pop
                             metavar="<node>",
750 f36d7d81 Iustin Pop
                             completion_suggest=OPT_COMPL_ONE_NODE)
751 7edc4637 Iustin Pop
752 edeb878a Iustin Pop
NOSTART_OPT = cli_option("--no-start", dest="start", default=True,
753 edeb878a Iustin Pop
                         action="store_false",
754 edeb878a Iustin Pop
                         help="Don't start the instance after creation")
755 edeb878a Iustin Pop
756 fdcf4d84 Iustin Pop
SHOWCMD_OPT = cli_option("--show-cmd", dest="show_command",
757 fdcf4d84 Iustin Pop
                         action="store_true", default=False,
758 fdcf4d84 Iustin Pop
                         help="Show command instead of executing it")
759 fdcf4d84 Iustin Pop
760 baef337d Iustin Pop
CLEANUP_OPT = cli_option("--cleanup", dest="cleanup",
761 baef337d Iustin Pop
                         default=False, action="store_true",
762 baef337d Iustin Pop
                         help="Instead of performing the migration, try to"
763 baef337d Iustin Pop
                         " recover from a failed cleanup. This is safe"
764 baef337d Iustin Pop
                         " to run even if the instance is healthy, but it"
765 baef337d Iustin Pop
                         " will create extra replication traffic and "
766 baef337d Iustin Pop
                         " disrupt briefly the replication (like during the"
767 baef337d Iustin Pop
                         " migration")
768 baef337d Iustin Pop
769 99a8c799 Iustin Pop
STATIC_OPT = cli_option("-s", "--static", dest="static",
770 99a8c799 Iustin Pop
                        action="store_true", default=False,
771 99a8c799 Iustin Pop
                        help="Only show configuration data, not runtime data")
772 99a8c799 Iustin Pop
773 2d5e7ae1 Iustin Pop
ALL_OPT = cli_option("--all", dest="show_all",
774 2d5e7ae1 Iustin Pop
                     default=False, action="store_true",
775 2d5e7ae1 Iustin Pop
                     help="Show info on all instances on the cluster."
776 2d5e7ae1 Iustin Pop
                     " This can take a long time to run, use wisely")
777 2d5e7ae1 Iustin Pop
778 67840b40 Iustin Pop
SELECT_OS_OPT = cli_option("--select-os", dest="select_os",
779 67840b40 Iustin Pop
                           action="store_true", default=False,
780 67840b40 Iustin Pop
                           help="Interactive OS reinstall, lists available"
781 67840b40 Iustin Pop
                           " OS templates for selection")
782 2d5e7ae1 Iustin Pop
783 b6e841a8 Iustin Pop
IGNORE_FAILURES_OPT = cli_option("--ignore-failures", dest="ignore_failures",
784 b6e841a8 Iustin Pop
                                 action="store_true", default=False,
785 b6e841a8 Iustin Pop
                                 help="Remove the instance from the cluster"
786 b6e841a8 Iustin Pop
                                 " configuration even if there are failures"
787 b6e841a8 Iustin Pop
                                 " during the removal process")
788 b6e841a8 Iustin Pop
789 8d8d650c Michael Hanselmann
IGNORE_REMOVE_FAILURES_OPT = cli_option("--ignore-remove-failures",
790 8d8d650c Michael Hanselmann
                                        dest="ignore_remove_failures",
791 8d8d650c Michael Hanselmann
                                        action="store_true", default=False,
792 8d8d650c Michael Hanselmann
                                        help="Remove the instance from the"
793 8d8d650c Michael Hanselmann
                                        " cluster configuration even if there"
794 8d8d650c Michael Hanselmann
                                        " are failures during the removal"
795 8d8d650c Michael Hanselmann
                                        " process")
796 8d8d650c Michael Hanselmann
797 8d8d650c Michael Hanselmann
REMOVE_INSTANCE_OPT = cli_option("--remove-instance", dest="remove_instance",
798 8d8d650c Michael Hanselmann
                                 action="store_true", default=False,
799 8d8d650c Michael Hanselmann
                                 help="Remove the instance from the cluster")
800 8d8d650c Michael Hanselmann
801 a14db5ff Iustin Pop
NEW_SECONDARY_OPT = cli_option("-n", "--new-secondary", dest="dst_node",
802 a14db5ff Iustin Pop
                               help="Specifies the new secondary node",
803 a14db5ff Iustin Pop
                               metavar="NODE", default=None,
804 a14db5ff Iustin Pop
                               completion_suggest=OPT_COMPL_ONE_NODE)
805 a14db5ff Iustin Pop
806 a72d0a79 Iustin Pop
ON_PRIMARY_OPT = cli_option("-p", "--on-primary", dest="on_primary",
807 a72d0a79 Iustin Pop
                            default=False, action="store_true",
808 a72d0a79 Iustin Pop
                            help="Replace the disk(s) on the primary"
809 a72d0a79 Iustin Pop
                            " node (only for the drbd template)")
810 feb09e6a Iustin Pop
811 feb09e6a Iustin Pop
ON_SECONDARY_OPT = cli_option("-s", "--on-secondary", dest="on_secondary",
812 feb09e6a Iustin Pop
                              default=False, action="store_true",
813 feb09e6a Iustin Pop
                              help="Replace the disk(s) on the secondary"
814 feb09e6a Iustin Pop
                              " node (only for the drbd template)")
815 e00f7a05 Iustin Pop
816 4c61d894 Iustin Pop
AUTO_PROMOTE_OPT = cli_option("--auto-promote", dest="auto_promote",
817 4c61d894 Iustin Pop
                              default=False, action="store_true",
818 4c61d894 Iustin Pop
                              help="Lock all nodes and auto-promote as needed"
819 4c61d894 Iustin Pop
                              " to MC status")
820 4c61d894 Iustin Pop
821 e00f7a05 Iustin Pop
AUTO_REPLACE_OPT = cli_option("-a", "--auto", dest="auto",
822 e00f7a05 Iustin Pop
                              default=False, action="store_true",
823 e00f7a05 Iustin Pop
                              help="Automatically replace faulty disks"
824 e00f7a05 Iustin Pop
                              " (only for the drbd template)")
825 a72d0a79 Iustin Pop
826 05586c90 Iustin Pop
IGNORE_SIZE_OPT = cli_option("--ignore-size", dest="ignore_size",
827 05586c90 Iustin Pop
                             default=False, action="store_true",
828 05586c90 Iustin Pop
                             help="Ignore current recorded size"
829 05586c90 Iustin Pop
                             " (useful for forcing activation when"
830 05586c90 Iustin Pop
                             " the recorded size is wrong)")
831 05586c90 Iustin Pop
832 df62e5db Iustin Pop
SRC_NODE_OPT = cli_option("--src-node", dest="src_node", help="Source node",
833 df62e5db Iustin Pop
                          metavar="<node>",
834 df62e5db Iustin Pop
                          completion_suggest=OPT_COMPL_ONE_NODE)
835 df62e5db Iustin Pop
836 df62e5db Iustin Pop
SRC_DIR_OPT = cli_option("--src-dir", dest="src_dir", help="Source directory",
837 df62e5db Iustin Pop
                         metavar="<dir>")
838 df62e5db Iustin Pop
839 8d823629 Iustin Pop
SECONDARY_IP_OPT = cli_option("-s", "--secondary-ip", dest="secondary_ip",
840 8d823629 Iustin Pop
                              help="Specify the secondary ip for the node",
841 8d823629 Iustin Pop
                              metavar="ADDRESS", default=None)
842 8d823629 Iustin Pop
843 b8d0f938 Iustin Pop
READD_OPT = cli_option("--readd", dest="readd",
844 b8d0f938 Iustin Pop
                       default=False, action="store_true",
845 b8d0f938 Iustin Pop
                       help="Readd old node after replacing it")
846 b8d0f938 Iustin Pop
847 fcdde7f2 Iustin Pop
NOSSH_KEYCHECK_OPT = cli_option("--no-ssh-key-check", dest="ssh_key_check",
848 fcdde7f2 Iustin Pop
                                default=True, action="store_false",
849 fcdde7f2 Iustin Pop
                                help="Disable SSH key fingerprint checking")
850 fcdde7f2 Iustin Pop
851 c38c44ad Michael Hanselmann
852 771734c9 Iustin Pop
MC_OPT = cli_option("-C", "--master-candidate", dest="master_candidate",
853 e7b61bb0 Iustin Pop
                    type="bool", default=None, metavar=_YORNO,
854 771734c9 Iustin Pop
                    help="Set the master_candidate flag on the node")
855 771734c9 Iustin Pop
856 771734c9 Iustin Pop
OFFLINE_OPT = cli_option("-O", "--offline", dest="offline", metavar=_YORNO,
857 e7b61bb0 Iustin Pop
                         type="bool", default=None,
858 771734c9 Iustin Pop
                         help="Set the offline flag on the node")
859 771734c9 Iustin Pop
860 771734c9 Iustin Pop
DRAINED_OPT = cli_option("-D", "--drained", dest="drained", metavar=_YORNO,
861 e7b61bb0 Iustin Pop
                         type="bool", default=None,
862 771734c9 Iustin Pop
                         help="Set the drained flag on the node")
863 771734c9 Iustin Pop
864 e7e09483 Iustin Pop
ALLOCATABLE_OPT = cli_option("--allocatable", dest="allocatable",
865 e7b61bb0 Iustin Pop
                             type="bool", default=None, metavar=_YORNO,
866 e7e09483 Iustin Pop
                             help="Set the allocatable flag on a volume")
867 e7e09483 Iustin Pop
868 831040bf Iustin Pop
NOLVM_STORAGE_OPT = cli_option("--no-lvm-storage", dest="lvm_storage",
869 831040bf Iustin Pop
                               help="Disable support for lvm based instances"
870 831040bf Iustin Pop
                               " (cluster-wide)",
871 831040bf Iustin Pop
                               action="store_false", default=True)
872 831040bf Iustin Pop
873 383a3591 Iustin Pop
ENABLED_HV_OPT = cli_option("--enabled-hypervisors",
874 383a3591 Iustin Pop
                            dest="enabled_hypervisors",
875 383a3591 Iustin Pop
                            help="Comma-separated list of hypervisors",
876 383a3591 Iustin Pop
                            type="string", default=None)
877 383a3591 Iustin Pop
878 4fbc93dd Iustin Pop
NIC_PARAMS_OPT = cli_option("-N", "--nic-parameters", dest="nicparams",
879 4fbc93dd Iustin Pop
                            type="keyval", default={},
880 4fbc93dd Iustin Pop
                            help="NIC parameters")
881 4fbc93dd Iustin Pop
882 e32df528 Iustin Pop
CP_SIZE_OPT = cli_option("-C", "--candidate-pool-size", default=None,
883 e32df528 Iustin Pop
                         dest="candidate_pool_size", type="int",
884 e32df528 Iustin Pop
                         help="Set the candidate pool size")
885 e32df528 Iustin Pop
886 b58726e8 Iustin Pop
VG_NAME_OPT = cli_option("-g", "--vg-name", dest="vg_name",
887 b58726e8 Iustin Pop
                         help="Enables LVM and specifies the volume group"
888 b58726e8 Iustin Pop
                         " name (cluster-wide) for disk allocation [xenvg]",
889 b58726e8 Iustin Pop
                         metavar="VG", default=None)
890 b58726e8 Iustin Pop
891 1f587d3d Iustin Pop
YES_DOIT_OPT = cli_option("--yes-do-it", dest="yes_do_it",
892 1f587d3d Iustin Pop
                          help="Destroy cluster", action="store_true")
893 b58726e8 Iustin Pop
894 58371861 Iustin Pop
NOVOTING_OPT = cli_option("--no-voting", dest="no_voting",
895 58371861 Iustin Pop
                          help="Skip node agreement check (dangerous)",
896 58371861 Iustin Pop
                          action="store_true", default=False)
897 58371861 Iustin Pop
898 e3646f22 Iustin Pop
MAC_PREFIX_OPT = cli_option("-m", "--mac-prefix", dest="mac_prefix",
899 e3646f22 Iustin Pop
                            help="Specify the mac prefix for the instance IP"
900 e3646f22 Iustin Pop
                            " addresses, in the format XX:XX:XX",
901 e3646f22 Iustin Pop
                            metavar="PREFIX",
902 e3646f22 Iustin Pop
                            default=None)
903 e3646f22 Iustin Pop
904 29392516 Iustin Pop
MASTER_NETDEV_OPT = cli_option("--master-netdev", dest="master_netdev",
905 29392516 Iustin Pop
                               help="Specify the node interface (cluster-wide)"
906 29392516 Iustin Pop
                               " on which the master IP address will be added "
907 29392516 Iustin Pop
                               " [%s]" % constants.DEFAULT_BRIDGE,
908 29392516 Iustin Pop
                               metavar="NETDEV",
909 29392516 Iustin Pop
                               default=constants.DEFAULT_BRIDGE)
910 29392516 Iustin Pop
911 29392516 Iustin Pop
GLOBAL_FILEDIR_OPT = cli_option("--file-storage-dir", dest="file_storage_dir",
912 29392516 Iustin Pop
                                help="Specify the default directory (cluster-"
913 29392516 Iustin Pop
                                "wide) for storing the file-based disks [%s]" %
914 29392516 Iustin Pop
                                constants.DEFAULT_FILE_STORAGE_DIR,
915 29392516 Iustin Pop
                                metavar="DIR",
916 29392516 Iustin Pop
                                default=constants.DEFAULT_FILE_STORAGE_DIR)
917 29392516 Iustin Pop
918 29392516 Iustin Pop
NOMODIFY_ETCHOSTS_OPT = cli_option("--no-etc-hosts", dest="modify_etc_hosts",
919 29392516 Iustin Pop
                                   help="Don't modify /etc/hosts",
920 29392516 Iustin Pop
                                   action="store_false", default=True)
921 29392516 Iustin Pop
922 b989b9d9 Ken Wehr
NOMODIFY_SSH_SETUP_OPT = cli_option("--no-ssh-init", dest="modify_ssh_setup",
923 b989b9d9 Ken Wehr
                                    help="Don't initialize SSH keys",
924 b989b9d9 Ken Wehr
                                    action="store_false", default=True)
925 b989b9d9 Ken Wehr
926 14e9e7f3 Iustin Pop
ERROR_CODES_OPT = cli_option("--error-codes", dest="error_codes",
927 14e9e7f3 Iustin Pop
                             help="Enable parseable error messages",
928 14e9e7f3 Iustin Pop
                             action="store_true", default=False)
929 14e9e7f3 Iustin Pop
930 14e9e7f3 Iustin Pop
NONPLUS1_OPT = cli_option("--no-nplus1-mem", dest="skip_nplusone_mem",
931 14e9e7f3 Iustin Pop
                          help="Skip N+1 memory redundancy tests",
932 14e9e7f3 Iustin Pop
                          action="store_true", default=False)
933 14e9e7f3 Iustin Pop
934 12054861 Iustin Pop
REBOOT_TYPE_OPT = cli_option("-t", "--type", dest="reboot_type",
935 12054861 Iustin Pop
                             help="Type of reboot: soft/hard/full",
936 12054861 Iustin Pop
                             default=constants.INSTANCE_REBOOT_HARD,
937 12054861 Iustin Pop
                             metavar="<REBOOT>",
938 12054861 Iustin Pop
                             choices=list(constants.REBOOT_TYPES))
939 12054861 Iustin Pop
940 ee3f9578 Iustin Pop
IGNORE_SECONDARIES_OPT = cli_option("--ignore-secondaries",
941 ee3f9578 Iustin Pop
                                    dest="ignore_secondaries",
942 ee3f9578 Iustin Pop
                                    default=False, action="store_true",
943 ee3f9578 Iustin Pop
                                    help="Ignore errors from secondaries")
944 ee3f9578 Iustin Pop
945 69b99987 Michael Hanselmann
NOSHUTDOWN_OPT = cli_option("--noshutdown", dest="shutdown",
946 44c44832 Iustin Pop
                            action="store_false", default=True,
947 44c44832 Iustin Pop
                            help="Don't shutdown the instance (unsafe)")
948 44c44832 Iustin Pop
949 b5762e2a Guido Trotter
TIMEOUT_OPT = cli_option("--timeout", dest="timeout", type="int",
950 b5762e2a Guido Trotter
                         default=constants.DEFAULT_SHUTDOWN_TIMEOUT,
951 b5762e2a Guido Trotter
                         help="Maximum time to wait")
952 44c44832 Iustin Pop
953 4d98c565 Guido Trotter
SHUTDOWN_TIMEOUT_OPT = cli_option("--shutdown-timeout",
954 4d98c565 Guido Trotter
                         dest="shutdown_timeout", type="int",
955 7e5eaaa8 Guido Trotter
                         default=constants.DEFAULT_SHUTDOWN_TIMEOUT,
956 7e5eaaa8 Guido Trotter
                         help="Maximum time to wait for instance shutdown")
957 7e5eaaa8 Guido Trotter
958 19b9ba9a Michael Hanselmann
INTERVAL_OPT = cli_option("--interval", dest="interval", type="int",
959 19b9ba9a Michael Hanselmann
                          default=None,
960 19b9ba9a Michael Hanselmann
                          help=("Number of seconds between repetions of the"
961 19b9ba9a Michael Hanselmann
                                " command"))
962 19b9ba9a Michael Hanselmann
963 7ea7bcf6 Iustin Pop
EARLY_RELEASE_OPT = cli_option("--early-release",
964 7ea7bcf6 Iustin Pop
                               dest="early_release", default=False,
965 7ea7bcf6 Iustin Pop
                               action="store_true",
966 7ea7bcf6 Iustin Pop
                               help="Release the locks on the secondary"
967 7ea7bcf6 Iustin Pop
                               " node(s) early")
968 7ea7bcf6 Iustin Pop
969 6d4a1656 Michael Hanselmann
NEW_CLUSTER_CERT_OPT = cli_option("--new-cluster-certificate",
970 6d4a1656 Michael Hanselmann
                                  dest="new_cluster_cert",
971 6d4a1656 Michael Hanselmann
                                  default=False, action="store_true",
972 6d4a1656 Michael Hanselmann
                                  help="Generate a new cluster certificate")
973 6d4a1656 Michael Hanselmann
974 6d4a1656 Michael Hanselmann
RAPI_CERT_OPT = cli_option("--rapi-certificate", dest="rapi_cert",
975 6d4a1656 Michael Hanselmann
                           default=None,
976 6d4a1656 Michael Hanselmann
                           help="File containing new RAPI certificate")
977 6d4a1656 Michael Hanselmann
978 6d4a1656 Michael Hanselmann
NEW_RAPI_CERT_OPT = cli_option("--new-rapi-certificate", dest="new_rapi_cert",
979 6d4a1656 Michael Hanselmann
                               default=None, action="store_true",
980 6d4a1656 Michael Hanselmann
                               help=("Generate a new self-signed RAPI"
981 6d4a1656 Michael Hanselmann
                                     " certificate"))
982 6d4a1656 Michael Hanselmann
983 6b7d5878 Michael Hanselmann
NEW_CONFD_HMAC_KEY_OPT = cli_option("--new-confd-hmac-key",
984 6b7d5878 Michael Hanselmann
                                    dest="new_confd_hmac_key",
985 6b7d5878 Michael Hanselmann
                                    default=False, action="store_true",
986 6b7d5878 Michael Hanselmann
                                    help=("Create a new HMAC key for %s" %
987 6b7d5878 Michael Hanselmann
                                          constants.CONFD))
988 6d4a1656 Michael Hanselmann
989 3db3eb2a Michael Hanselmann
CLUSTER_DOMAIN_SECRET_OPT = cli_option("--cluster-domain-secret",
990 3db3eb2a Michael Hanselmann
                                       dest="cluster_domain_secret",
991 3db3eb2a Michael Hanselmann
                                       default=None,
992 3db3eb2a Michael Hanselmann
                                       help=("Load new new cluster domain"
993 3db3eb2a Michael Hanselmann
                                             " secret from file"))
994 3db3eb2a Michael Hanselmann
995 3db3eb2a Michael Hanselmann
NEW_CLUSTER_DOMAIN_SECRET_OPT = cli_option("--new-cluster-domain-secret",
996 3db3eb2a Michael Hanselmann
                                           dest="new_cluster_domain_secret",
997 3db3eb2a Michael Hanselmann
                                           default=False, action="store_true",
998 3db3eb2a Michael Hanselmann
                                           help=("Create a new cluster domain"
999 3db3eb2a Michael Hanselmann
                                                 " secret"))
1000 3db3eb2a Michael Hanselmann
1001 74adc100 Iustin Pop
USE_REPL_NET_OPT = cli_option("--use-replication-network",
1002 74adc100 Iustin Pop
                              dest="use_replication_network",
1003 74adc100 Iustin Pop
                              help="Whether to use the replication network"
1004 74adc100 Iustin Pop
                              " for talking to the nodes",
1005 74adc100 Iustin Pop
                              action="store_true", default=False)
1006 74adc100 Iustin Pop
1007 3953242f Iustin Pop
MAINTAIN_NODE_HEALTH_OPT = \
1008 3953242f Iustin Pop
    cli_option("--maintain-node-health", dest="maintain_node_health",
1009 3953242f Iustin Pop
               metavar=_YORNO, default=None, type="bool",
1010 3953242f Iustin Pop
               help="Configure the cluster to automatically maintain node"
1011 3953242f Iustin Pop
               " health, by shutting down unknown instances, shutting down"
1012 3953242f Iustin Pop
               " unknown DRBD devices, etc.")
1013 3953242f Iustin Pop
1014 e588764d Iustin Pop
IDENTIFY_DEFAULTS_OPT = \
1015 e588764d Iustin Pop
    cli_option("--identify-defaults", dest="identify_defaults",
1016 e588764d Iustin Pop
               default=False, action="store_true",
1017 e588764d Iustin Pop
               help="Identify which saved instance parameters are equal to"
1018 e588764d Iustin Pop
               " the current cluster defaults and set them as such, instead"
1019 e588764d Iustin Pop
               " of marking them as overridden")
1020 e588764d Iustin Pop
1021 1338f2b4 Balazs Lecz
UIDPOOL_OPT = cli_option("--uid-pool", default=None,
1022 1338f2b4 Balazs Lecz
                         action="store", dest="uid_pool",
1023 1338f2b4 Balazs Lecz
                         help=("A list of user-ids or user-id"
1024 1338f2b4 Balazs Lecz
                               " ranges separated by commas"))
1025 1338f2b4 Balazs Lecz
1026 fdad8c4d Balazs Lecz
ADD_UIDS_OPT = cli_option("--add-uids", default=None,
1027 fdad8c4d Balazs Lecz
                          action="store", dest="add_uids",
1028 fdad8c4d Balazs Lecz
                          help=("A list of user-ids or user-id"
1029 fdad8c4d Balazs Lecz
                                " ranges separated by commas, to be"
1030 fdad8c4d Balazs Lecz
                                " added to the user-id pool"))
1031 fdad8c4d Balazs Lecz
1032 fdad8c4d Balazs Lecz
REMOVE_UIDS_OPT = cli_option("--remove-uids", default=None,
1033 fdad8c4d Balazs Lecz
                             action="store", dest="remove_uids",
1034 fdad8c4d Balazs Lecz
                             help=("A list of user-ids or user-id"
1035 fdad8c4d Balazs Lecz
                                   " ranges separated by commas, to be"
1036 fdad8c4d Balazs Lecz
                                   " removed from the user-id pool"))
1037 fdad8c4d Balazs Lecz
1038 f38ea602 Iustin Pop
RESERVED_LVS_OPT = cli_option("--reserved-lvs", default=None,
1039 f38ea602 Iustin Pop
                             action="store", dest="reserved_lvs",
1040 f38ea602 Iustin Pop
                             help=("A comma-separated list of reserved"
1041 f38ea602 Iustin Pop
                                   " logical volumes names, that will be"
1042 f38ea602 Iustin Pop
                                   " ignored by cluster verify"))
1043 f38ea602 Iustin Pop
1044 31d97b2a Guido Trotter
ROMAN_OPT = cli_option("--roman",
1045 31d97b2a Guido Trotter
                       dest="roman_integers", default=False,
1046 31d97b2a Guido Trotter
                       action="store_true",
1047 31d97b2a Guido Trotter
                       help="Use roman numbers for positive integers")
1048 31d97b2a Guido Trotter
1049 26591bfd Luca Bigliardi
DRBD_HELPER_OPT = cli_option("--drbd-usermode-helper", dest="drbd_helper",
1050 26591bfd Luca Bigliardi
                             action="store", default=None,
1051 26591bfd Luca Bigliardi
                             help="Specifies usermode helper for DRBD")
1052 26591bfd Luca Bigliardi
1053 26591bfd Luca Bigliardi
NODRBD_STORAGE_OPT = cli_option("--no-drbd-storage", dest="drbd_storage",
1054 26591bfd Luca Bigliardi
                                action="store_false", default=True,
1055 26591bfd Luca Bigliardi
                                help="Disable support for DRBD")
1056 31d97b2a Guido Trotter
1057 e7323b5e Manuel Franceschini
PRIMARY_IP_VERSION_OPT = \
1058 e7323b5e Manuel Franceschini
    cli_option("--primary-ip-version", default=constants.IP4_VERSION,
1059 e7323b5e Manuel Franceschini
               action="store", dest="primary_ip_version",
1060 e7323b5e Manuel Franceschini
               metavar="%d|%d" % (constants.IP4_VERSION,
1061 e7323b5e Manuel Franceschini
                                  constants.IP6_VERSION),
1062 e7323b5e Manuel Franceschini
               help="Cluster-wide IP version for primary IP")
1063 e7323b5e Manuel Franceschini
1064 84a5b33c Michael Hanselmann
PRIORITY_OPT = cli_option("--priority", default=None, dest="priority",
1065 84a5b33c Michael Hanselmann
                          metavar="|".join(name for name, _ in _PRIORITY_NAMES),
1066 84a5b33c Michael Hanselmann
                          choices=_PRIONAME_TO_VALUE.keys(),
1067 aa06f8c6 Michael Hanselmann
                          help="Priority for opcode processing")
1068 84a5b33c Michael Hanselmann
1069 5786c087 Michael Hanselmann
#: Options provided by all commands
1070 5786c087 Michael Hanselmann
COMMON_OPTS = [DEBUG_OPT]
1071 5786c087 Michael Hanselmann
1072 771734c9 Iustin Pop
1073 de47cf8f Guido Trotter
def _ParseArgs(argv, commands, aliases):
1074 c41eea6e Iustin Pop
  """Parser for the command line arguments.
1075 a8083063 Iustin Pop

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

1079 c41eea6e Iustin Pop
  @param argv: the command line
1080 c41eea6e Iustin Pop
  @param commands: dictionary with special contents, see the design
1081 c41eea6e Iustin Pop
      doc for cmdline handling
1082 c41eea6e Iustin Pop
  @param aliases: dictionary with command aliases {'alias': 'target, ...}
1083 098c0958 Michael Hanselmann

1084 a8083063 Iustin Pop
  """
1085 a8083063 Iustin Pop
  if len(argv) == 0:
1086 a8083063 Iustin Pop
    binary = "<command>"
1087 a8083063 Iustin Pop
  else:
1088 a8083063 Iustin Pop
    binary = argv[0].split("/")[-1]
1089 a8083063 Iustin Pop
1090 a8083063 Iustin Pop
  if len(argv) > 1 and argv[1] == "--version":
1091 84a12e40 Iustin Pop
    ToStdout("%s (ganeti %s) %s", binary, constants.VCS_VERSION,
1092 84a12e40 Iustin Pop
             constants.RELEASE_VERSION)
1093 a8083063 Iustin Pop
    # Quit right away. That way we don't have to care about this special
1094 a8083063 Iustin Pop
    # argument. optparse.py does it the same.
1095 a8083063 Iustin Pop
    sys.exit(0)
1096 a8083063 Iustin Pop
1097 de47cf8f Guido Trotter
  if len(argv) < 2 or not (argv[1] in commands or
1098 70a35b6f Guido Trotter
                           argv[1] in aliases):
1099 a8083063 Iustin Pop
    # let's do a nice thing
1100 a8083063 Iustin Pop
    sortedcmds = commands.keys()
1101 a8083063 Iustin Pop
    sortedcmds.sort()
1102 03298ebe Michael Hanselmann
1103 03298ebe Michael Hanselmann
    ToStdout("Usage: %s {command} [options...] [argument...]", binary)
1104 03298ebe Michael Hanselmann
    ToStdout("%s <command> --help to see details, or man %s", binary, binary)
1105 03298ebe Michael Hanselmann
    ToStdout("")
1106 03298ebe Michael Hanselmann
1107 a8083063 Iustin Pop
    # compute the max line length for cmd + usage
1108 4e713df6 Iustin Pop
    mlen = max([len(" %s" % cmd) for cmd in commands])
1109 a8083063 Iustin Pop
    mlen = min(60, mlen) # should not get here...
1110 03298ebe Michael Hanselmann
1111 a8083063 Iustin Pop
    # and format a nice command list
1112 03298ebe Michael Hanselmann
    ToStdout("Commands:")
1113 a8083063 Iustin Pop
    for cmd in sortedcmds:
1114 4e713df6 Iustin Pop
      cmdstr = " %s" % (cmd,)
1115 9a033156 Iustin Pop
      help_text = commands[cmd][4]
1116 03298ebe Michael Hanselmann
      help_lines = textwrap.wrap(help_text, 79 - 3 - mlen)
1117 03298ebe Michael Hanselmann
      ToStdout("%-*s - %s", mlen, cmdstr, help_lines.pop(0))
1118 a8083063 Iustin Pop
      for line in help_lines:
1119 03298ebe Michael Hanselmann
        ToStdout("%-*s   %s", mlen, "", line)
1120 03298ebe Michael Hanselmann
1121 03298ebe Michael Hanselmann
    ToStdout("")
1122 03298ebe Michael Hanselmann
1123 a8083063 Iustin Pop
    return None, None, None
1124 de47cf8f Guido Trotter
1125 de47cf8f Guido Trotter
  # get command, unalias it, and look it up in commands
1126 a8083063 Iustin Pop
  cmd = argv.pop(1)
1127 de47cf8f Guido Trotter
  if cmd in aliases:
1128 de47cf8f Guido Trotter
    if cmd in commands:
1129 de47cf8f Guido Trotter
      raise errors.ProgrammerError("Alias '%s' overrides an existing"
1130 de47cf8f Guido Trotter
                                   " command" % cmd)
1131 de47cf8f Guido Trotter
1132 de47cf8f Guido Trotter
    if aliases[cmd] not in commands:
1133 de47cf8f Guido Trotter
      raise errors.ProgrammerError("Alias '%s' maps to non-existing"
1134 de47cf8f Guido Trotter
                                   " command '%s'" % (cmd, aliases[cmd]))
1135 de47cf8f Guido Trotter
1136 de47cf8f Guido Trotter
    cmd = aliases[cmd]
1137 de47cf8f Guido Trotter
1138 a8005e17 Michael Hanselmann
  func, args_def, parser_opts, usage, description = commands[cmd]
1139 5786c087 Michael Hanselmann
  parser = OptionParser(option_list=parser_opts + COMMON_OPTS,
1140 a8083063 Iustin Pop
                        description=description,
1141 a8083063 Iustin Pop
                        formatter=TitledHelpFormatter(),
1142 a8083063 Iustin Pop
                        usage="%%prog %s %s" % (cmd, usage))
1143 a8083063 Iustin Pop
  parser.disable_interspersed_args()
1144 a8083063 Iustin Pop
  options, args = parser.parse_args()
1145 a8005e17 Michael Hanselmann
1146 a8005e17 Michael Hanselmann
  if not _CheckArguments(cmd, args_def, args):
1147 a8083063 Iustin Pop
    return None, None, None
1148 a8083063 Iustin Pop
1149 a8083063 Iustin Pop
  return func, options, args
1150 a8083063 Iustin Pop
1151 a8083063 Iustin Pop
1152 a8005e17 Michael Hanselmann
def _CheckArguments(cmd, args_def, args):
1153 a8005e17 Michael Hanselmann
  """Verifies the arguments using the argument definition.
1154 a8005e17 Michael Hanselmann

1155 a8005e17 Michael Hanselmann
  Algorithm:
1156 a8005e17 Michael Hanselmann

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

1159 a8005e17 Michael Hanselmann
    1. For each argument in definition
1160 a8005e17 Michael Hanselmann

1161 a8005e17 Michael Hanselmann
      1. Keep running count of minimum number of values (min_count)
1162 a8005e17 Michael Hanselmann
      1. Keep running count of maximum number of values (max_count)
1163 a8005e17 Michael Hanselmann
      1. If it has an unlimited number of values
1164 a8005e17 Michael Hanselmann

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

1167 a8005e17 Michael Hanselmann
    1. If last argument has limited number of values
1168 a8005e17 Michael Hanselmann

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

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

1173 a8005e17 Michael Hanselmann
  """
1174 a8005e17 Michael Hanselmann
  if args and not args_def:
1175 a8005e17 Michael Hanselmann
    ToStderr("Error: Command %s expects no arguments", cmd)
1176 a8005e17 Michael Hanselmann
    return False
1177 a8005e17 Michael Hanselmann
1178 a8005e17 Michael Hanselmann
  min_count = None
1179 a8005e17 Michael Hanselmann
  max_count = None
1180 a8005e17 Michael Hanselmann
  check_max = None
1181 a8005e17 Michael Hanselmann
1182 a8005e17 Michael Hanselmann
  last_idx = len(args_def) - 1
1183 a8005e17 Michael Hanselmann
1184 a8005e17 Michael Hanselmann
  for idx, arg in enumerate(args_def):
1185 a8005e17 Michael Hanselmann
    if min_count is None:
1186 a8005e17 Michael Hanselmann
      min_count = arg.min
1187 a8005e17 Michael Hanselmann
    elif arg.min is not None:
1188 a8005e17 Michael Hanselmann
      min_count += arg.min
1189 a8005e17 Michael Hanselmann
1190 a8005e17 Michael Hanselmann
    if max_count is None:
1191 a8005e17 Michael Hanselmann
      max_count = arg.max
1192 a8005e17 Michael Hanselmann
    elif arg.max is not None:
1193 a8005e17 Michael Hanselmann
      max_count += arg.max
1194 a8005e17 Michael Hanselmann
1195 a8005e17 Michael Hanselmann
    if idx == last_idx:
1196 a8005e17 Michael Hanselmann
      check_max = (arg.max is not None)
1197 a8005e17 Michael Hanselmann
1198 a8005e17 Michael Hanselmann
    elif arg.max is None:
1199 a8005e17 Michael Hanselmann
      raise errors.ProgrammerError("Only the last argument can have max=None")
1200 a8005e17 Michael Hanselmann
1201 a8005e17 Michael Hanselmann
  if check_max:
1202 a8005e17 Michael Hanselmann
    # Command with exact number of arguments
1203 a8005e17 Michael Hanselmann
    if (min_count is not None and max_count is not None and
1204 a8005e17 Michael Hanselmann
        min_count == max_count and len(args) != min_count):
1205 a8005e17 Michael Hanselmann
      ToStderr("Error: Command %s expects %d argument(s)", cmd, min_count)
1206 a8005e17 Michael Hanselmann
      return False
1207 a8005e17 Michael Hanselmann
1208 a8005e17 Michael Hanselmann
    # Command with limited number of arguments
1209 a8005e17 Michael Hanselmann
    if max_count is not None and len(args) > max_count:
1210 a8005e17 Michael Hanselmann
      ToStderr("Error: Command %s expects only %d argument(s)",
1211 a8005e17 Michael Hanselmann
               cmd, max_count)
1212 a8005e17 Michael Hanselmann
      return False
1213 a8005e17 Michael Hanselmann
1214 a8005e17 Michael Hanselmann
  # Command with some required arguments
1215 a8005e17 Michael Hanselmann
  if min_count is not None and len(args) < min_count:
1216 a8005e17 Michael Hanselmann
    ToStderr("Error: Command %s expects at least %d argument(s)",
1217 a8005e17 Michael Hanselmann
             cmd, min_count)
1218 a8005e17 Michael Hanselmann
    return False
1219 a8005e17 Michael Hanselmann
1220 a8005e17 Michael Hanselmann
  return True
1221 a8005e17 Michael Hanselmann
1222 a8005e17 Michael Hanselmann
1223 60d49723 Michael Hanselmann
def SplitNodeOption(value):
1224 60d49723 Michael Hanselmann
  """Splits the value of a --node option.
1225 60d49723 Michael Hanselmann

1226 60d49723 Michael Hanselmann
  """
1227 60d49723 Michael Hanselmann
  if value and ':' in value:
1228 60d49723 Michael Hanselmann
    return value.split(':', 1)
1229 60d49723 Michael Hanselmann
  else:
1230 60d49723 Michael Hanselmann
    return (value, None)
1231 60d49723 Michael Hanselmann
1232 60d49723 Michael Hanselmann
1233 07150497 Guido Trotter
def CalculateOSNames(os_name, os_variants):
1234 07150497 Guido Trotter
  """Calculates all the names an OS can be called, according to its variants.
1235 07150497 Guido Trotter

1236 07150497 Guido Trotter
  @type os_name: string
1237 07150497 Guido Trotter
  @param os_name: base name of the os
1238 07150497 Guido Trotter
  @type os_variants: list or None
1239 07150497 Guido Trotter
  @param os_variants: list of supported variants
1240 07150497 Guido Trotter
  @rtype: list
1241 07150497 Guido Trotter
  @return: list of valid names
1242 07150497 Guido Trotter

1243 07150497 Guido Trotter
  """
1244 07150497 Guido Trotter
  if os_variants:
1245 07150497 Guido Trotter
    return ['%s+%s' % (os_name, v) for v in os_variants]
1246 07150497 Guido Trotter
  else:
1247 07150497 Guido Trotter
    return [os_name]
1248 07150497 Guido Trotter
1249 07150497 Guido Trotter
1250 a4ebd726 Michael Hanselmann
def ParseFields(selected, default):
1251 a4ebd726 Michael Hanselmann
  """Parses the values of "--field"-like options.
1252 a4ebd726 Michael Hanselmann

1253 a4ebd726 Michael Hanselmann
  @type selected: string or None
1254 a4ebd726 Michael Hanselmann
  @param selected: User-selected options
1255 a4ebd726 Michael Hanselmann
  @type default: list
1256 a4ebd726 Michael Hanselmann
  @param default: Default fields
1257 a4ebd726 Michael Hanselmann

1258 a4ebd726 Michael Hanselmann
  """
1259 a4ebd726 Michael Hanselmann
  if selected is None:
1260 a4ebd726 Michael Hanselmann
    return default
1261 a4ebd726 Michael Hanselmann
1262 a4ebd726 Michael Hanselmann
  if selected.startswith("+"):
1263 a4ebd726 Michael Hanselmann
    return default + selected[1:].split(",")
1264 a4ebd726 Michael Hanselmann
1265 a4ebd726 Michael Hanselmann
  return selected.split(",")
1266 a4ebd726 Michael Hanselmann
1267 a4ebd726 Michael Hanselmann
1268 e0e916fe Iustin Pop
UsesRPC = rpc.RunWithRPC
1269 4331f6cd Michael Hanselmann
1270 4331f6cd Michael Hanselmann
1271 47988778 Iustin Pop
def AskUser(text, choices=None):
1272 47988778 Iustin Pop
  """Ask the user a question.
1273 a8083063 Iustin Pop

1274 c41eea6e Iustin Pop
  @param text: the question to ask
1275 a8083063 Iustin Pop

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

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

1285 a8083063 Iustin Pop
  """
1286 47988778 Iustin Pop
  if choices is None:
1287 47988778 Iustin Pop
    choices = [('y', True, 'Perform the operation'),
1288 47988778 Iustin Pop
               ('n', False, 'Do not perform the operation')]
1289 47988778 Iustin Pop
  if not choices or not isinstance(choices, list):
1290 5bbd3f7f Michael Hanselmann
    raise errors.ProgrammerError("Invalid choices argument to AskUser")
1291 47988778 Iustin Pop
  for entry in choices:
1292 47988778 Iustin Pop
    if not isinstance(entry, tuple) or len(entry) < 3 or entry[0] == '?':
1293 5bbd3f7f Michael Hanselmann
      raise errors.ProgrammerError("Invalid choices element to AskUser")
1294 47988778 Iustin Pop
1295 47988778 Iustin Pop
  answer = choices[-1][1]
1296 47988778 Iustin Pop
  new_text = []
1297 47988778 Iustin Pop
  for line in text.splitlines():
1298 47988778 Iustin Pop
    new_text.append(textwrap.fill(line, 70, replace_whitespace=False))
1299 47988778 Iustin Pop
  text = "\n".join(new_text)
1300 a8083063 Iustin Pop
  try:
1301 3023170f Iustin Pop
    f = file("/dev/tty", "a+")
1302 a8083063 Iustin Pop
  except IOError:
1303 47988778 Iustin Pop
    return answer
1304 a8083063 Iustin Pop
  try:
1305 47988778 Iustin Pop
    chars = [entry[0] for entry in choices]
1306 47988778 Iustin Pop
    chars[-1] = "[%s]" % chars[-1]
1307 47988778 Iustin Pop
    chars.append('?')
1308 47988778 Iustin Pop
    maps = dict([(entry[0], entry[1]) for entry in choices])
1309 47988778 Iustin Pop
    while True:
1310 47988778 Iustin Pop
      f.write(text)
1311 47988778 Iustin Pop
      f.write('\n')
1312 47988778 Iustin Pop
      f.write("/".join(chars))
1313 47988778 Iustin Pop
      f.write(": ")
1314 47988778 Iustin Pop
      line = f.readline(2).strip().lower()
1315 47988778 Iustin Pop
      if line in maps:
1316 47988778 Iustin Pop
        answer = maps[line]
1317 47988778 Iustin Pop
        break
1318 47988778 Iustin Pop
      elif line == '?':
1319 47988778 Iustin Pop
        for entry in choices:
1320 47988778 Iustin Pop
          f.write(" %s - %s\n" % (entry[0], entry[2]))
1321 47988778 Iustin Pop
        f.write("\n")
1322 47988778 Iustin Pop
        continue
1323 a8083063 Iustin Pop
  finally:
1324 a8083063 Iustin Pop
    f.close()
1325 a8083063 Iustin Pop
  return answer
1326 a8083063 Iustin Pop
1327 a8083063 Iustin Pop
1328 e9d741b6 Iustin Pop
class JobSubmittedException(Exception):
1329 e9d741b6 Iustin Pop
  """Job was submitted, client should exit.
1330 e9d741b6 Iustin Pop

1331 e9d741b6 Iustin Pop
  This exception has one argument, the ID of the job that was
1332 e9d741b6 Iustin Pop
  submitted. The handler should print this ID.
1333 e9d741b6 Iustin Pop

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

1336 e9d741b6 Iustin Pop
  """
1337 e9d741b6 Iustin Pop
1338 e9d741b6 Iustin Pop
1339 0a1e74d9 Iustin Pop
def SendJob(ops, cl=None):
1340 0a1e74d9 Iustin Pop
  """Function to submit an opcode without waiting for the results.
1341 a8083063 Iustin Pop

1342 0a1e74d9 Iustin Pop
  @type ops: list
1343 0a1e74d9 Iustin Pop
  @param ops: list of opcodes
1344 0a1e74d9 Iustin Pop
  @type cl: luxi.Client
1345 0a1e74d9 Iustin Pop
  @param cl: the luxi client to use for communicating with the master;
1346 0a1e74d9 Iustin Pop
             if None, a new client will be created
1347 a8083063 Iustin Pop

1348 a8083063 Iustin Pop
  """
1349 e2212007 Iustin Pop
  if cl is None:
1350 b33e986b Iustin Pop
    cl = GetClient()
1351 685ee993 Iustin Pop
1352 0a1e74d9 Iustin Pop
  job_id = cl.SubmitJob(ops)
1353 0a1e74d9 Iustin Pop
1354 0a1e74d9 Iustin Pop
  return job_id
1355 0a1e74d9 Iustin Pop
1356 0a1e74d9 Iustin Pop
1357 4e338533 Michael Hanselmann
def GenericPollJob(job_id, cbs, report_cbs):
1358 4e338533 Michael Hanselmann
  """Generic job-polling function.
1359 0a1e74d9 Iustin Pop

1360 4e338533 Michael Hanselmann
  @type job_id: number
1361 4e338533 Michael Hanselmann
  @param job_id: Job ID
1362 4e338533 Michael Hanselmann
  @type cbs: Instance of L{JobPollCbBase}
1363 4e338533 Michael Hanselmann
  @param cbs: Data callbacks
1364 4e338533 Michael Hanselmann
  @type report_cbs: Instance of L{JobPollReportCbBase}
1365 4e338533 Michael Hanselmann
  @param report_cbs: Reporting callbacks
1366 0a1e74d9 Iustin Pop

1367 0a1e74d9 Iustin Pop
  """
1368 6c5a7090 Michael Hanselmann
  prev_job_info = None
1369 6c5a7090 Michael Hanselmann
  prev_logmsg_serial = None
1370 6c5a7090 Michael Hanselmann
1371 f4484122 Michael Hanselmann
  status = None
1372 f4484122 Michael Hanselmann
1373 685ee993 Iustin Pop
  while True:
1374 4e338533 Michael Hanselmann
    result = cbs.WaitForJobChangeOnce(job_id, ["status"], prev_job_info,
1375 4e338533 Michael Hanselmann
                                      prev_logmsg_serial)
1376 6c5a7090 Michael Hanselmann
    if not result:
1377 685ee993 Iustin Pop
      # job not found, go away!
1378 0bbe448c Michael Hanselmann
      raise errors.JobLost("Job with id %s lost" % job_id)
1379 4e338533 Michael Hanselmann
1380 4e338533 Michael Hanselmann
    if result == constants.JOB_NOTCHANGED:
1381 4e338533 Michael Hanselmann
      report_cbs.ReportNotChanged(job_id, status)
1382 f4484122 Michael Hanselmann
1383 f4484122 Michael Hanselmann
      # Wait again
1384 f4484122 Michael Hanselmann
      continue
1385 685ee993 Iustin Pop
1386 6c5a7090 Michael Hanselmann
    # Split result, a tuple of (field values, log entries)
1387 6c5a7090 Michael Hanselmann
    (job_info, log_entries) = result
1388 6c5a7090 Michael Hanselmann
    (status, ) = job_info
1389 6c5a7090 Michael Hanselmann
1390 6c5a7090 Michael Hanselmann
    if log_entries:
1391 6c5a7090 Michael Hanselmann
      for log_entry in log_entries:
1392 4e338533 Michael Hanselmann
        (serial, timestamp, log_type, message) = log_entry
1393 4e338533 Michael Hanselmann
        report_cbs.ReportLogMessage(job_id, serial, timestamp,
1394 4e338533 Michael Hanselmann
                                    log_type, message)
1395 6c5a7090 Michael Hanselmann
        prev_logmsg_serial = max(prev_logmsg_serial, serial)
1396 6c5a7090 Michael Hanselmann
1397 0bbe448c Michael Hanselmann
    # TODO: Handle canceled and archived jobs
1398 fbf0262f Michael Hanselmann
    elif status in (constants.JOB_STATUS_SUCCESS,
1399 fbf0262f Michael Hanselmann
                    constants.JOB_STATUS_ERROR,
1400 fbf0262f Michael Hanselmann
                    constants.JOB_STATUS_CANCELING,
1401 fbf0262f Michael Hanselmann
                    constants.JOB_STATUS_CANCELED):
1402 685ee993 Iustin Pop
      break
1403 6c5a7090 Michael Hanselmann
1404 6c5a7090 Michael Hanselmann
    prev_job_info = job_info
1405 685ee993 Iustin Pop
1406 4e338533 Michael Hanselmann
  jobs = cbs.QueryJobs([job_id], ["status", "opstatus", "opresult"])
1407 0bbe448c Michael Hanselmann
  if not jobs:
1408 0bbe448c Michael Hanselmann
    raise errors.JobLost("Job with id %s lost" % job_id)
1409 685ee993 Iustin Pop
1410 0e050889 Iustin Pop
  status, opstatus, result = jobs[0]
1411 4e338533 Michael Hanselmann
1412 0bbe448c Michael Hanselmann
  if status == constants.JOB_STATUS_SUCCESS:
1413 53c04d04 Iustin Pop
    return result
1414 4e338533 Michael Hanselmann
1415 4e338533 Michael Hanselmann
  if status in (constants.JOB_STATUS_CANCELING, constants.JOB_STATUS_CANCELED):
1416 fbf0262f Michael Hanselmann
    raise errors.OpExecError("Job was canceled")
1417 4e338533 Michael Hanselmann
1418 4e338533 Michael Hanselmann
  has_ok = False
1419 4e338533 Michael Hanselmann
  for idx, (status, msg) in enumerate(zip(opstatus, result)):
1420 4e338533 Michael Hanselmann
    if status == constants.OP_STATUS_SUCCESS:
1421 4e338533 Michael Hanselmann
      has_ok = True
1422 4e338533 Michael Hanselmann
    elif status == constants.OP_STATUS_ERROR:
1423 4e338533 Michael Hanselmann
      errors.MaybeRaise(msg)
1424 4e338533 Michael Hanselmann
1425 4e338533 Michael Hanselmann
      if has_ok:
1426 4e338533 Michael Hanselmann
        raise errors.OpExecError("partial failure (opcode %d): %s" %
1427 4e338533 Michael Hanselmann
                                 (idx, msg))
1428 4e338533 Michael Hanselmann
1429 4e338533 Michael Hanselmann
      raise errors.OpExecError(str(msg))
1430 4e338533 Michael Hanselmann
1431 4e338533 Michael Hanselmann
  # default failure mode
1432 4e338533 Michael Hanselmann
  raise errors.OpExecError(result)
1433 4e338533 Michael Hanselmann
1434 4e338533 Michael Hanselmann
1435 4e338533 Michael Hanselmann
class JobPollCbBase:
1436 4e338533 Michael Hanselmann
  """Base class for L{GenericPollJob} callbacks.
1437 4e338533 Michael Hanselmann

1438 4e338533 Michael Hanselmann
  """
1439 4e338533 Michael Hanselmann
  def __init__(self):
1440 4e338533 Michael Hanselmann
    """Initializes this class.
1441 4e338533 Michael Hanselmann

1442 4e338533 Michael Hanselmann
    """
1443 4e338533 Michael Hanselmann
1444 4e338533 Michael Hanselmann
  def WaitForJobChangeOnce(self, job_id, fields,
1445 4e338533 Michael Hanselmann
                           prev_job_info, prev_log_serial):
1446 4e338533 Michael Hanselmann
    """Waits for changes on a job.
1447 4e338533 Michael Hanselmann

1448 4e338533 Michael Hanselmann
    """
1449 4e338533 Michael Hanselmann
    raise NotImplementedError()
1450 4e338533 Michael Hanselmann
1451 4e338533 Michael Hanselmann
  def QueryJobs(self, job_ids, fields):
1452 4e338533 Michael Hanselmann
    """Returns the selected fields for the selected job IDs.
1453 4e338533 Michael Hanselmann

1454 4e338533 Michael Hanselmann
    @type job_ids: list of numbers
1455 4e338533 Michael Hanselmann
    @param job_ids: Job IDs
1456 4e338533 Michael Hanselmann
    @type fields: list of strings
1457 4e338533 Michael Hanselmann
    @param fields: Fields
1458 4e338533 Michael Hanselmann

1459 4e338533 Michael Hanselmann
    """
1460 4e338533 Michael Hanselmann
    raise NotImplementedError()
1461 4e338533 Michael Hanselmann
1462 4e338533 Michael Hanselmann
1463 4e338533 Michael Hanselmann
class JobPollReportCbBase:
1464 4e338533 Michael Hanselmann
  """Base class for L{GenericPollJob} reporting callbacks.
1465 4e338533 Michael Hanselmann

1466 4e338533 Michael Hanselmann
  """
1467 4e338533 Michael Hanselmann
  def __init__(self):
1468 4e338533 Michael Hanselmann
    """Initializes this class.
1469 4e338533 Michael Hanselmann

1470 4e338533 Michael Hanselmann
    """
1471 4e338533 Michael Hanselmann
1472 4e338533 Michael Hanselmann
  def ReportLogMessage(self, job_id, serial, timestamp, log_type, log_msg):
1473 4e338533 Michael Hanselmann
    """Handles a log message.
1474 4e338533 Michael Hanselmann

1475 4e338533 Michael Hanselmann
    """
1476 4e338533 Michael Hanselmann
    raise NotImplementedError()
1477 4e338533 Michael Hanselmann
1478 4e338533 Michael Hanselmann
  def ReportNotChanged(self, job_id, status):
1479 4e338533 Michael Hanselmann
    """Called for if a job hasn't changed in a while.
1480 4e338533 Michael Hanselmann

1481 4e338533 Michael Hanselmann
    @type job_id: number
1482 4e338533 Michael Hanselmann
    @param job_id: Job ID
1483 4e338533 Michael Hanselmann
    @type status: string or None
1484 4e338533 Michael Hanselmann
    @param status: Job status if available
1485 4e338533 Michael Hanselmann

1486 4e338533 Michael Hanselmann
    """
1487 4e338533 Michael Hanselmann
    raise NotImplementedError()
1488 4e338533 Michael Hanselmann
1489 4e338533 Michael Hanselmann
1490 4e338533 Michael Hanselmann
class _LuxiJobPollCb(JobPollCbBase):
1491 4e338533 Michael Hanselmann
  def __init__(self, cl):
1492 4e338533 Michael Hanselmann
    """Initializes this class.
1493 4e338533 Michael Hanselmann

1494 4e338533 Michael Hanselmann
    """
1495 4e338533 Michael Hanselmann
    JobPollCbBase.__init__(self)
1496 4e338533 Michael Hanselmann
    self.cl = cl
1497 4e338533 Michael Hanselmann
1498 4e338533 Michael Hanselmann
  def WaitForJobChangeOnce(self, job_id, fields,
1499 4e338533 Michael Hanselmann
                           prev_job_info, prev_log_serial):
1500 4e338533 Michael Hanselmann
    """Waits for changes on a job.
1501 4e338533 Michael Hanselmann

1502 4e338533 Michael Hanselmann
    """
1503 4e338533 Michael Hanselmann
    return self.cl.WaitForJobChangeOnce(job_id, fields,
1504 4e338533 Michael Hanselmann
                                        prev_job_info, prev_log_serial)
1505 4e338533 Michael Hanselmann
1506 4e338533 Michael Hanselmann
  def QueryJobs(self, job_ids, fields):
1507 4e338533 Michael Hanselmann
    """Returns the selected fields for the selected job IDs.
1508 4e338533 Michael Hanselmann

1509 4e338533 Michael Hanselmann
    """
1510 4e338533 Michael Hanselmann
    return self.cl.QueryJobs(job_ids, fields)
1511 4e338533 Michael Hanselmann
1512 4e338533 Michael Hanselmann
1513 4e338533 Michael Hanselmann
class FeedbackFnJobPollReportCb(JobPollReportCbBase):
1514 4e338533 Michael Hanselmann
  def __init__(self, feedback_fn):
1515 4e338533 Michael Hanselmann
    """Initializes this class.
1516 4e338533 Michael Hanselmann

1517 4e338533 Michael Hanselmann
    """
1518 4e338533 Michael Hanselmann
    JobPollReportCbBase.__init__(self)
1519 4e338533 Michael Hanselmann
1520 4e338533 Michael Hanselmann
    self.feedback_fn = feedback_fn
1521 4e338533 Michael Hanselmann
1522 4e338533 Michael Hanselmann
    assert callable(feedback_fn)
1523 4e338533 Michael Hanselmann
1524 4e338533 Michael Hanselmann
  def ReportLogMessage(self, job_id, serial, timestamp, log_type, log_msg):
1525 4e338533 Michael Hanselmann
    """Handles a log message.
1526 4e338533 Michael Hanselmann

1527 4e338533 Michael Hanselmann
    """
1528 4e338533 Michael Hanselmann
    self.feedback_fn((timestamp, log_type, log_msg))
1529 4e338533 Michael Hanselmann
1530 4e338533 Michael Hanselmann
  def ReportNotChanged(self, job_id, status):
1531 4e338533 Michael Hanselmann
    """Called if a job hasn't changed in a while.
1532 4e338533 Michael Hanselmann

1533 4e338533 Michael Hanselmann
    """
1534 4e338533 Michael Hanselmann
    # Ignore
1535 4e338533 Michael Hanselmann
1536 4e338533 Michael Hanselmann
1537 4e338533 Michael Hanselmann
class StdioJobPollReportCb(JobPollReportCbBase):
1538 4e338533 Michael Hanselmann
  def __init__(self):
1539 4e338533 Michael Hanselmann
    """Initializes this class.
1540 4e338533 Michael Hanselmann

1541 4e338533 Michael Hanselmann
    """
1542 4e338533 Michael Hanselmann
    JobPollReportCbBase.__init__(self)
1543 4e338533 Michael Hanselmann
1544 4e338533 Michael Hanselmann
    self.notified_queued = False
1545 4e338533 Michael Hanselmann
    self.notified_waitlock = False
1546 4e338533 Michael Hanselmann
1547 4e338533 Michael Hanselmann
  def ReportLogMessage(self, job_id, serial, timestamp, log_type, log_msg):
1548 4e338533 Michael Hanselmann
    """Handles a log message.
1549 4e338533 Michael Hanselmann

1550 4e338533 Michael Hanselmann
    """
1551 4e338533 Michael Hanselmann
    ToStdout("%s %s", time.ctime(utils.MergeTime(timestamp)),
1552 8a7f1c61 Michael Hanselmann
             FormatLogMessage(log_type, log_msg))
1553 4e338533 Michael Hanselmann
1554 4e338533 Michael Hanselmann
  def ReportNotChanged(self, job_id, status):
1555 4e338533 Michael Hanselmann
    """Called if a job hasn't changed in a while.
1556 4e338533 Michael Hanselmann

1557 4e338533 Michael Hanselmann
    """
1558 4e338533 Michael Hanselmann
    if status is None:
1559 4e338533 Michael Hanselmann
      return
1560 4e338533 Michael Hanselmann
1561 4e338533 Michael Hanselmann
    if status == constants.JOB_STATUS_QUEUED and not self.notified_queued:
1562 4e338533 Michael Hanselmann
      ToStderr("Job %s is waiting in queue", job_id)
1563 4e338533 Michael Hanselmann
      self.notified_queued = True
1564 4e338533 Michael Hanselmann
1565 4e338533 Michael Hanselmann
    elif status == constants.JOB_STATUS_WAITLOCK and not self.notified_waitlock:
1566 4e338533 Michael Hanselmann
      ToStderr("Job %s is trying to acquire all necessary locks", job_id)
1567 4e338533 Michael Hanselmann
      self.notified_waitlock = True
1568 4e338533 Michael Hanselmann
1569 4e338533 Michael Hanselmann
1570 8a7f1c61 Michael Hanselmann
def FormatLogMessage(log_type, log_msg):
1571 8a7f1c61 Michael Hanselmann
  """Formats a job message according to its type.
1572 8a7f1c61 Michael Hanselmann

1573 8a7f1c61 Michael Hanselmann
  """
1574 8a7f1c61 Michael Hanselmann
  if log_type != constants.ELOG_MESSAGE:
1575 8a7f1c61 Michael Hanselmann
    log_msg = str(log_msg)
1576 8a7f1c61 Michael Hanselmann
1577 8a7f1c61 Michael Hanselmann
  return utils.SafeEncode(log_msg)
1578 8a7f1c61 Michael Hanselmann
1579 8a7f1c61 Michael Hanselmann
1580 583163a6 Michael Hanselmann
def PollJob(job_id, cl=None, feedback_fn=None, reporter=None):
1581 4e338533 Michael Hanselmann
  """Function to poll for the result of a job.
1582 4e338533 Michael Hanselmann

1583 4e338533 Michael Hanselmann
  @type job_id: job identified
1584 4e338533 Michael Hanselmann
  @param job_id: the job to poll for results
1585 4e338533 Michael Hanselmann
  @type cl: luxi.Client
1586 4e338533 Michael Hanselmann
  @param cl: the luxi client to use for communicating with the master;
1587 4e338533 Michael Hanselmann
             if None, a new client will be created
1588 4e338533 Michael Hanselmann

1589 4e338533 Michael Hanselmann
  """
1590 4e338533 Michael Hanselmann
  if cl is None:
1591 4e338533 Michael Hanselmann
    cl = GetClient()
1592 4e338533 Michael Hanselmann
1593 583163a6 Michael Hanselmann
  if reporter is None:
1594 583163a6 Michael Hanselmann
    if feedback_fn:
1595 583163a6 Michael Hanselmann
      reporter = FeedbackFnJobPollReportCb(feedback_fn)
1596 583163a6 Michael Hanselmann
    else:
1597 583163a6 Michael Hanselmann
      reporter = StdioJobPollReportCb()
1598 583163a6 Michael Hanselmann
  elif feedback_fn:
1599 583163a6 Michael Hanselmann
    raise errors.ProgrammerError("Can't specify reporter and feedback function")
1600 4e338533 Michael Hanselmann
1601 4e338533 Michael Hanselmann
  return GenericPollJob(job_id, _LuxiJobPollCb(cl), reporter)
1602 ceab32dd Iustin Pop
1603 ceab32dd Iustin Pop
1604 583163a6 Michael Hanselmann
def SubmitOpCode(op, cl=None, feedback_fn=None, opts=None, reporter=None):
1605 0a1e74d9 Iustin Pop
  """Legacy function to submit an opcode.
1606 0a1e74d9 Iustin Pop

1607 0a1e74d9 Iustin Pop
  This is just a simple wrapper over the construction of the processor
1608 0a1e74d9 Iustin Pop
  instance. It should be extended to better handle feedback and
1609 0a1e74d9 Iustin Pop
  interaction functions.
1610 0a1e74d9 Iustin Pop

1611 0a1e74d9 Iustin Pop
  """
1612 0a1e74d9 Iustin Pop
  if cl is None:
1613 0a1e74d9 Iustin Pop
    cl = GetClient()
1614 0a1e74d9 Iustin Pop
1615 293ba2d8 Iustin Pop
  SetGenericOpcodeOpts([op], opts)
1616 293ba2d8 Iustin Pop
1617 5d297d8a Michael Hanselmann
  job_id = SendJob([op], cl=cl)
1618 0a1e74d9 Iustin Pop
1619 583163a6 Michael Hanselmann
  op_results = PollJob(job_id, cl=cl, feedback_fn=feedback_fn,
1620 583163a6 Michael Hanselmann
                       reporter=reporter)
1621 53c04d04 Iustin Pop
1622 53c04d04 Iustin Pop
  return op_results[0]
1623 0a1e74d9 Iustin Pop
1624 0a1e74d9 Iustin Pop
1625 94428652 Iustin Pop
def SubmitOrSend(op, opts, cl=None, feedback_fn=None):
1626 94428652 Iustin Pop
  """Wrapper around SubmitOpCode or SendJob.
1627 94428652 Iustin Pop

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

1633 293ba2d8 Iustin Pop
  It will also process the opcodes if we're sending the via SendJob
1634 293ba2d8 Iustin Pop
  (otherwise SubmitOpCode does it).
1635 64c65a2a Iustin Pop

1636 94428652 Iustin Pop
  """
1637 94428652 Iustin Pop
  if opts and opts.submit_only:
1638 293ba2d8 Iustin Pop
    job = [op]
1639 293ba2d8 Iustin Pop
    SetGenericOpcodeOpts(job, opts)
1640 293ba2d8 Iustin Pop
    job_id = SendJob(job, cl=cl)
1641 e9d741b6 Iustin Pop
    raise JobSubmittedException(job_id)
1642 94428652 Iustin Pop
  else:
1643 293ba2d8 Iustin Pop
    return SubmitOpCode(op, cl=cl, feedback_fn=feedback_fn, opts=opts)
1644 293ba2d8 Iustin Pop
1645 293ba2d8 Iustin Pop
1646 293ba2d8 Iustin Pop
def SetGenericOpcodeOpts(opcode_list, options):
1647 293ba2d8 Iustin Pop
  """Processor for generic options.
1648 293ba2d8 Iustin Pop

1649 293ba2d8 Iustin Pop
  This function updates the given opcodes based on generic command
1650 293ba2d8 Iustin Pop
  line options (like debug, dry-run, etc.).
1651 293ba2d8 Iustin Pop

1652 293ba2d8 Iustin Pop
  @param opcode_list: list of opcodes
1653 293ba2d8 Iustin Pop
  @param options: command line options or None
1654 293ba2d8 Iustin Pop
  @return: None (in-place modification)
1655 293ba2d8 Iustin Pop

1656 293ba2d8 Iustin Pop
  """
1657 293ba2d8 Iustin Pop
  if not options:
1658 293ba2d8 Iustin Pop
    return
1659 293ba2d8 Iustin Pop
  for op in opcode_list:
1660 aa06f8c6 Michael Hanselmann
    op.debug_level = options.debug
1661 a0a6ff34 Iustin Pop
    if hasattr(options, "dry_run"):
1662 a0a6ff34 Iustin Pop
      op.dry_run = options.dry_run
1663 aa06f8c6 Michael Hanselmann
    if getattr(options, "priority", None) is not None:
1664 aa06f8c6 Michael Hanselmann
      op.priority = _PRIONAME_TO_VALUE[options.priority]
1665 94428652 Iustin Pop
1666 94428652 Iustin Pop
1667 af30b2fd Michael Hanselmann
def GetClient():
1668 af30b2fd Michael Hanselmann
  # TODO: Cache object?
1669 b33e986b Iustin Pop
  try:
1670 b33e986b Iustin Pop
    client = luxi.Client()
1671 b33e986b Iustin Pop
  except luxi.NoMasterError:
1672 d9a51679 Michael Hanselmann
    ss = ssconf.SimpleStore()
1673 d9a51679 Michael Hanselmann
1674 d9a51679 Michael Hanselmann
    # Try to read ssconf file
1675 d9a51679 Michael Hanselmann
    try:
1676 d9a51679 Michael Hanselmann
      ss.GetMasterNode()
1677 d9a51679 Michael Hanselmann
    except errors.ConfigurationError:
1678 d9a51679 Michael Hanselmann
      raise errors.OpPrereqError("Cluster not initialized or this machine is"
1679 d9a51679 Michael Hanselmann
                                 " not part of a cluster")
1680 d9a51679 Michael Hanselmann
1681 d9a51679 Michael Hanselmann
    master, myself = ssconf.GetMasterAndMyself(ss=ss)
1682 b33e986b Iustin Pop
    if master != myself:
1683 b33e986b Iustin Pop
      raise errors.OpPrereqError("This is not the master node, please connect"
1684 b33e986b Iustin Pop
                                 " to node '%s' and rerun the command" %
1685 b33e986b Iustin Pop
                                 master)
1686 d9a51679 Michael Hanselmann
    raise
1687 b33e986b Iustin Pop
  return client
1688 af30b2fd Michael Hanselmann
1689 af30b2fd Michael Hanselmann
1690 73702ee7 Iustin Pop
def FormatError(err):
1691 73702ee7 Iustin Pop
  """Return a formatted error message for a given error.
1692 73702ee7 Iustin Pop

1693 73702ee7 Iustin Pop
  This function takes an exception instance and returns a tuple
1694 73702ee7 Iustin Pop
  consisting of two values: first, the recommended exit code, and
1695 73702ee7 Iustin Pop
  second, a string describing the error message (not
1696 73702ee7 Iustin Pop
  newline-terminated).
1697 73702ee7 Iustin Pop

1698 73702ee7 Iustin Pop
  """
1699 73702ee7 Iustin Pop
  retcode = 1
1700 73702ee7 Iustin Pop
  obuf = StringIO()
1701 e2e521d0 Iustin Pop
  msg = str(err)
1702 73702ee7 Iustin Pop
  if isinstance(err, errors.ConfigurationError):
1703 e2e521d0 Iustin Pop
    txt = "Corrupt configuration file: %s" % msg
1704 46fbdd04 Iustin Pop
    logging.error(txt)
1705 e2e521d0 Iustin Pop
    obuf.write(txt + "\n")
1706 73702ee7 Iustin Pop
    obuf.write("Aborting.")
1707 73702ee7 Iustin Pop
    retcode = 2
1708 73702ee7 Iustin Pop
  elif isinstance(err, errors.HooksAbort):
1709 73702ee7 Iustin Pop
    obuf.write("Failure: hooks execution failed:\n")
1710 73702ee7 Iustin Pop
    for node, script, out in err.args[0]:
1711 73702ee7 Iustin Pop
      if out:
1712 73702ee7 Iustin Pop
        obuf.write("  node: %s, script: %s, output: %s\n" %
1713 73702ee7 Iustin Pop
                   (node, script, out))
1714 73702ee7 Iustin Pop
      else:
1715 73702ee7 Iustin Pop
        obuf.write("  node: %s, script: %s (no output)\n" %
1716 73702ee7 Iustin Pop
                   (node, script))
1717 73702ee7 Iustin Pop
  elif isinstance(err, errors.HooksFailure):
1718 e2e521d0 Iustin Pop
    obuf.write("Failure: hooks general failure: %s" % msg)
1719 73702ee7 Iustin Pop
  elif isinstance(err, errors.ResolverError):
1720 b705c7a6 Manuel Franceschini
    this_host = netutils.Hostname.GetSysName()
1721 73702ee7 Iustin Pop
    if err.args[0] == this_host:
1722 73702ee7 Iustin Pop
      msg = "Failure: can't resolve my own hostname ('%s')"
1723 73702ee7 Iustin Pop
    else:
1724 73702ee7 Iustin Pop
      msg = "Failure: can't resolve hostname '%s'"
1725 73702ee7 Iustin Pop
    obuf.write(msg % err.args[0])
1726 73702ee7 Iustin Pop
  elif isinstance(err, errors.OpPrereqError):
1727 5c983ee5 Iustin Pop
    if len(err.args) == 2:
1728 5c983ee5 Iustin Pop
      obuf.write("Failure: prerequisites not met for this"
1729 5c983ee5 Iustin Pop
               " operation:\nerror type: %s, error details:\n%s" %
1730 5c983ee5 Iustin Pop
                 (err.args[1], err.args[0]))
1731 5c983ee5 Iustin Pop
    else:
1732 5c983ee5 Iustin Pop
      obuf.write("Failure: prerequisites not met for this"
1733 5c983ee5 Iustin Pop
                 " operation:\n%s" % msg)
1734 73702ee7 Iustin Pop
  elif isinstance(err, errors.OpExecError):
1735 e2e521d0 Iustin Pop
    obuf.write("Failure: command execution error:\n%s" % msg)
1736 73702ee7 Iustin Pop
  elif isinstance(err, errors.TagError):
1737 e2e521d0 Iustin Pop
    obuf.write("Failure: invalid tag(s) given:\n%s" % msg)
1738 686d7433 Iustin Pop
  elif isinstance(err, errors.JobQueueDrainError):
1739 686d7433 Iustin Pop
    obuf.write("Failure: the job queue is marked for drain and doesn't"
1740 686d7433 Iustin Pop
               " accept new requests\n")
1741 f87b405e Michael Hanselmann
  elif isinstance(err, errors.JobQueueFull):
1742 f87b405e Michael Hanselmann
    obuf.write("Failure: the job queue is full and doesn't accept new"
1743 f87b405e Michael Hanselmann
               " job submissions until old jobs are archived\n")
1744 a5728081 Guido Trotter
  elif isinstance(err, errors.TypeEnforcementError):
1745 a5728081 Guido Trotter
    obuf.write("Parameter Error: %s" % msg)
1746 c1ce76bb Iustin Pop
  elif isinstance(err, errors.ParameterError):
1747 c1ce76bb Iustin Pop
    obuf.write("Failure: unknown/wrong parameter name '%s'" % msg)
1748 03a8dbdc Iustin Pop
  elif isinstance(err, luxi.NoMasterError):
1749 03a8dbdc Iustin Pop
    obuf.write("Cannot communicate with the master daemon.\nIs it running"
1750 082c5adb Michael Hanselmann
               " and listening for connections?")
1751 03a8dbdc Iustin Pop
  elif isinstance(err, luxi.TimeoutError):
1752 03a8dbdc Iustin Pop
    obuf.write("Timeout while talking to the master daemon. Error:\n"
1753 03a8dbdc Iustin Pop
               "%s" % msg)
1754 5a1c22fe Iustin Pop
  elif isinstance(err, luxi.PermissionError):
1755 5a1c22fe Iustin Pop
    obuf.write("It seems you don't have permissions to connect to the"
1756 5a1c22fe Iustin Pop
               " master daemon.\nPlease retry as a different user.")
1757 03a8dbdc Iustin Pop
  elif isinstance(err, luxi.ProtocolError):
1758 03a8dbdc Iustin Pop
    obuf.write("Unhandled protocol error while talking to the master daemon:\n"
1759 03a8dbdc Iustin Pop
               "%s" % msg)
1760 91c622a8 Iustin Pop
  elif isinstance(err, errors.JobLost):
1761 91c622a8 Iustin Pop
    obuf.write("Error checking job status: %s" % msg)
1762 797506fc Michael Hanselmann
  elif isinstance(err, errors.GenericError):
1763 797506fc Michael Hanselmann
    obuf.write("Unhandled Ganeti error: %s" % msg)
1764 e9d741b6 Iustin Pop
  elif isinstance(err, JobSubmittedException):
1765 e9d741b6 Iustin Pop
    obuf.write("JobID: %s\n" % err.args[0])
1766 e9d741b6 Iustin Pop
    retcode = 0
1767 73702ee7 Iustin Pop
  else:
1768 e2e521d0 Iustin Pop
    obuf.write("Unhandled exception: %s" % msg)
1769 73702ee7 Iustin Pop
  return retcode, obuf.getvalue().rstrip('\n')
1770 73702ee7 Iustin Pop
1771 73702ee7 Iustin Pop
1772 de47cf8f Guido Trotter
def GenericMain(commands, override=None, aliases=None):
1773 a8083063 Iustin Pop
  """Generic main function for all the gnt-* commands.
1774 a8083063 Iustin Pop

1775 334d1483 Iustin Pop
  Arguments:
1776 334d1483 Iustin Pop
    - commands: a dictionary with a special structure, see the design doc
1777 334d1483 Iustin Pop
                for command line handling.
1778 334d1483 Iustin Pop
    - override: if not None, we expect a dictionary with keys that will
1779 334d1483 Iustin Pop
                override command line options; this can be used to pass
1780 334d1483 Iustin Pop
                options from the scripts to generic functions
1781 de47cf8f Guido Trotter
    - aliases: dictionary with command aliases {'alias': 'target, ...}
1782 a8083063 Iustin Pop

1783 a8083063 Iustin Pop
  """
1784 a8083063 Iustin Pop
  # save the program name and the entire command line for later logging
1785 a8083063 Iustin Pop
  if sys.argv:
1786 a8083063 Iustin Pop
    binary = os.path.basename(sys.argv[0]) or sys.argv[0]
1787 a8083063 Iustin Pop
    if len(sys.argv) >= 2:
1788 a8083063 Iustin Pop
      binary += " " + sys.argv[1]
1789 a8083063 Iustin Pop
      old_cmdline = " ".join(sys.argv[2:])
1790 a8083063 Iustin Pop
    else:
1791 a8083063 Iustin Pop
      old_cmdline = ""
1792 a8083063 Iustin Pop
  else:
1793 a8083063 Iustin Pop
    binary = "<unknown program>"
1794 a8083063 Iustin Pop
    old_cmdline = ""
1795 a8083063 Iustin Pop
1796 de47cf8f Guido Trotter
  if aliases is None:
1797 de47cf8f Guido Trotter
    aliases = {}
1798 de47cf8f Guido Trotter
1799 3126878d Guido Trotter
  try:
1800 3126878d Guido Trotter
    func, options, args = _ParseArgs(sys.argv, commands, aliases)
1801 3126878d Guido Trotter
  except errors.ParameterError, err:
1802 3126878d Guido Trotter
    result, err_msg = FormatError(err)
1803 3126878d Guido Trotter
    ToStderr(err_msg)
1804 3126878d Guido Trotter
    return 1
1805 3126878d Guido Trotter
1806 a8083063 Iustin Pop
  if func is None: # parse error
1807 a8083063 Iustin Pop
    return 1
1808 a8083063 Iustin Pop
1809 334d1483 Iustin Pop
  if override is not None:
1810 334d1483 Iustin Pop
    for key, val in override.iteritems():
1811 334d1483 Iustin Pop
      setattr(options, key, val)
1812 334d1483 Iustin Pop
1813 82d9caef Iustin Pop
  utils.SetupLogging(constants.LOG_COMMANDS, debug=options.debug,
1814 82d9caef Iustin Pop
                     stderr_logging=True, program=binary)
1815 a8083063 Iustin Pop
1816 a8083063 Iustin Pop
  if old_cmdline:
1817 46fbdd04 Iustin Pop
    logging.info("run with arguments '%s'", old_cmdline)
1818 a8083063 Iustin Pop
  else:
1819 46fbdd04 Iustin Pop
    logging.info("run with no arguments")
1820 a8083063 Iustin Pop
1821 a8083063 Iustin Pop
  try:
1822 a4af651e Iustin Pop
    result = func(options, args)
1823 d8353c3a Iustin Pop
  except (errors.GenericError, luxi.ProtocolError,
1824 d8353c3a Iustin Pop
          JobSubmittedException), err:
1825 a4af651e Iustin Pop
    result, err_msg = FormatError(err)
1826 5bbd3f7f Michael Hanselmann
    logging.exception("Error during command processing")
1827 46fbdd04 Iustin Pop
    ToStderr(err_msg)
1828 a8083063 Iustin Pop
1829 a8083063 Iustin Pop
  return result
1830 137161c9 Michael Hanselmann
1831 137161c9 Michael Hanselmann
1832 d77490c5 Iustin Pop
def GenericInstanceCreate(mode, opts, args):
1833 d77490c5 Iustin Pop
  """Add an instance to the cluster via either creation or import.
1834 d77490c5 Iustin Pop

1835 d77490c5 Iustin Pop
  @param mode: constants.INSTANCE_CREATE or constants.INSTANCE_IMPORT
1836 d77490c5 Iustin Pop
  @param opts: the command line options selected by the user
1837 d77490c5 Iustin Pop
  @type args: list
1838 d77490c5 Iustin Pop
  @param args: should contain only one element, the new instance name
1839 d77490c5 Iustin Pop
  @rtype: int
1840 d77490c5 Iustin Pop
  @return: the desired exit code
1841 d77490c5 Iustin Pop

1842 d77490c5 Iustin Pop
  """
1843 d77490c5 Iustin Pop
  instance = args[0]
1844 d77490c5 Iustin Pop
1845 d77490c5 Iustin Pop
  (pnode, snode) = SplitNodeOption(opts.node)
1846 d77490c5 Iustin Pop
1847 d77490c5 Iustin Pop
  hypervisor = None
1848 d77490c5 Iustin Pop
  hvparams = {}
1849 d77490c5 Iustin Pop
  if opts.hypervisor:
1850 d77490c5 Iustin Pop
    hypervisor, hvparams = opts.hypervisor
1851 d77490c5 Iustin Pop
1852 d77490c5 Iustin Pop
  if opts.nics:
1853 d77490c5 Iustin Pop
    try:
1854 21bcb9aa Michael Hanselmann
      nic_max = max(int(nidx[0]) + 1 for nidx in opts.nics)
1855 d77490c5 Iustin Pop
    except ValueError, err:
1856 d77490c5 Iustin Pop
      raise errors.OpPrereqError("Invalid NIC index passed: %s" % str(err))
1857 d77490c5 Iustin Pop
    nics = [{}] * nic_max
1858 d77490c5 Iustin Pop
    for nidx, ndict in opts.nics:
1859 d77490c5 Iustin Pop
      nidx = int(nidx)
1860 d77490c5 Iustin Pop
      if not isinstance(ndict, dict):
1861 d77490c5 Iustin Pop
        msg = "Invalid nic/%d value: expected dict, got %s" % (nidx, ndict)
1862 d77490c5 Iustin Pop
        raise errors.OpPrereqError(msg)
1863 d77490c5 Iustin Pop
      nics[nidx] = ndict
1864 d77490c5 Iustin Pop
  elif opts.no_nics:
1865 d77490c5 Iustin Pop
    # no nics
1866 d77490c5 Iustin Pop
    nics = []
1867 0af0f641 Iustin Pop
  elif mode == constants.INSTANCE_CREATE:
1868 d77490c5 Iustin Pop
    # default of one nic, all auto
1869 d77490c5 Iustin Pop
    nics = [{}]
1870 0af0f641 Iustin Pop
  else:
1871 0af0f641 Iustin Pop
    # mode == import
1872 0af0f641 Iustin Pop
    nics = []
1873 d77490c5 Iustin Pop
1874 d77490c5 Iustin Pop
  if opts.disk_template == constants.DT_DISKLESS:
1875 d77490c5 Iustin Pop
    if opts.disks or opts.sd_size is not None:
1876 d77490c5 Iustin Pop
      raise errors.OpPrereqError("Diskless instance but disk"
1877 d77490c5 Iustin Pop
                                 " information passed")
1878 d77490c5 Iustin Pop
    disks = []
1879 d77490c5 Iustin Pop
  else:
1880 9b12ed0f Iustin Pop
    if (not opts.disks and not opts.sd_size
1881 9b12ed0f Iustin Pop
        and mode == constants.INSTANCE_CREATE):
1882 d77490c5 Iustin Pop
      raise errors.OpPrereqError("No disk information specified")
1883 d77490c5 Iustin Pop
    if opts.disks and opts.sd_size is not None:
1884 d77490c5 Iustin Pop
      raise errors.OpPrereqError("Please use either the '--disk' or"
1885 d77490c5 Iustin Pop
                                 " '-s' option")
1886 d77490c5 Iustin Pop
    if opts.sd_size is not None:
1887 d77490c5 Iustin Pop
      opts.disks = [(0, {"size": opts.sd_size})]
1888 9b12ed0f Iustin Pop
1889 9b12ed0f Iustin Pop
    if opts.disks:
1890 9b12ed0f Iustin Pop
      try:
1891 9b12ed0f Iustin Pop
        disk_max = max(int(didx[0]) + 1 for didx in opts.disks)
1892 9b12ed0f Iustin Pop
      except ValueError, err:
1893 9b12ed0f Iustin Pop
        raise errors.OpPrereqError("Invalid disk index passed: %s" % str(err))
1894 9b12ed0f Iustin Pop
      disks = [{}] * disk_max
1895 9b12ed0f Iustin Pop
    else:
1896 9b12ed0f Iustin Pop
      disks = []
1897 d77490c5 Iustin Pop
    for didx, ddict in opts.disks:
1898 d77490c5 Iustin Pop
      didx = int(didx)
1899 d77490c5 Iustin Pop
      if not isinstance(ddict, dict):
1900 d77490c5 Iustin Pop
        msg = "Invalid disk/%d value: expected dict, got %s" % (didx, ddict)
1901 d77490c5 Iustin Pop
        raise errors.OpPrereqError(msg)
1902 5029db65 Iustin Pop
      elif "size" in ddict:
1903 5029db65 Iustin Pop
        if "adopt" in ddict:
1904 5029db65 Iustin Pop
          raise errors.OpPrereqError("Only one of 'size' and 'adopt' allowed"
1905 5029db65 Iustin Pop
                                     " (disk %d)" % didx)
1906 5029db65 Iustin Pop
        try:
1907 5029db65 Iustin Pop
          ddict["size"] = utils.ParseUnit(ddict["size"])
1908 5029db65 Iustin Pop
        except ValueError, err:
1909 5029db65 Iustin Pop
          raise errors.OpPrereqError("Invalid disk size for disk %d: %s" %
1910 5029db65 Iustin Pop
                                     (didx, err))
1911 5029db65 Iustin Pop
      elif "adopt" in ddict:
1912 5029db65 Iustin Pop
        if mode == constants.INSTANCE_IMPORT:
1913 5029db65 Iustin Pop
          raise errors.OpPrereqError("Disk adoption not allowed for instance"
1914 5029db65 Iustin Pop
                                     " import")
1915 5029db65 Iustin Pop
        ddict["size"] = 0
1916 5029db65 Iustin Pop
      else:
1917 5029db65 Iustin Pop
        raise errors.OpPrereqError("Missing size or adoption source for"
1918 5029db65 Iustin Pop
                                   " disk %d" % didx)
1919 d77490c5 Iustin Pop
      disks[didx] = ddict
1920 d77490c5 Iustin Pop
1921 d77490c5 Iustin Pop
  utils.ForceDictType(opts.beparams, constants.BES_PARAMETER_TYPES)
1922 d77490c5 Iustin Pop
  utils.ForceDictType(hvparams, constants.HVS_PARAMETER_TYPES)
1923 d77490c5 Iustin Pop
1924 d77490c5 Iustin Pop
  if mode == constants.INSTANCE_CREATE:
1925 d77490c5 Iustin Pop
    start = opts.start
1926 d77490c5 Iustin Pop
    os_type = opts.os
1927 1ee8e01a Guido Trotter
    force_variant = opts.force_variant
1928 d77490c5 Iustin Pop
    src_node = None
1929 d77490c5 Iustin Pop
    src_path = None
1930 25a8792c Iustin Pop
    no_install = opts.no_install
1931 e588764d Iustin Pop
    identify_defaults = False
1932 d77490c5 Iustin Pop
  elif mode == constants.INSTANCE_IMPORT:
1933 d77490c5 Iustin Pop
    start = False
1934 d77490c5 Iustin Pop
    os_type = None
1935 1ee8e01a Guido Trotter
    force_variant = False
1936 d77490c5 Iustin Pop
    src_node = opts.src_node
1937 d77490c5 Iustin Pop
    src_path = opts.src_dir
1938 25a8792c Iustin Pop
    no_install = None
1939 e588764d Iustin Pop
    identify_defaults = opts.identify_defaults
1940 d77490c5 Iustin Pop
  else:
1941 d77490c5 Iustin Pop
    raise errors.ProgrammerError("Invalid creation mode %s" % mode)
1942 d77490c5 Iustin Pop
1943 d77490c5 Iustin Pop
  op = opcodes.OpCreateInstance(instance_name=instance,
1944 d77490c5 Iustin Pop
                                disks=disks,
1945 d77490c5 Iustin Pop
                                disk_template=opts.disk_template,
1946 d77490c5 Iustin Pop
                                nics=nics,
1947 d77490c5 Iustin Pop
                                pnode=pnode, snode=snode,
1948 d77490c5 Iustin Pop
                                ip_check=opts.ip_check,
1949 460d22be Iustin Pop
                                name_check=opts.name_check,
1950 d77490c5 Iustin Pop
                                wait_for_sync=opts.wait_for_sync,
1951 d77490c5 Iustin Pop
                                file_storage_dir=opts.file_storage_dir,
1952 d77490c5 Iustin Pop
                                file_driver=opts.file_driver,
1953 d77490c5 Iustin Pop
                                iallocator=opts.iallocator,
1954 d77490c5 Iustin Pop
                                hypervisor=hypervisor,
1955 d77490c5 Iustin Pop
                                hvparams=hvparams,
1956 d77490c5 Iustin Pop
                                beparams=opts.beparams,
1957 062a7100 Iustin Pop
                                osparams=opts.osparams,
1958 d77490c5 Iustin Pop
                                mode=mode,
1959 d77490c5 Iustin Pop
                                start=start,
1960 d77490c5 Iustin Pop
                                os_type=os_type,
1961 1ee8e01a Guido Trotter
                                force_variant=force_variant,
1962 d77490c5 Iustin Pop
                                src_node=src_node,
1963 25a8792c Iustin Pop
                                src_path=src_path,
1964 e588764d Iustin Pop
                                no_install=no_install,
1965 e588764d Iustin Pop
                                identify_defaults=identify_defaults)
1966 d77490c5 Iustin Pop
1967 d77490c5 Iustin Pop
  SubmitOrSend(op, opts)
1968 d77490c5 Iustin Pop
  return 0
1969 d77490c5 Iustin Pop
1970 d77490c5 Iustin Pop
1971 7e49b6ce Michael Hanselmann
class _RunWhileClusterStoppedHelper:
1972 7e49b6ce Michael Hanselmann
  """Helper class for L{RunWhileClusterStopped} to simplify state management
1973 7e49b6ce Michael Hanselmann

1974 7e49b6ce Michael Hanselmann
  """
1975 7e49b6ce Michael Hanselmann
  def __init__(self, feedback_fn, cluster_name, master_node, online_nodes):
1976 7e49b6ce Michael Hanselmann
    """Initializes this class.
1977 7e49b6ce Michael Hanselmann

1978 7e49b6ce Michael Hanselmann
    @type feedback_fn: callable
1979 7e49b6ce Michael Hanselmann
    @param feedback_fn: Feedback function
1980 7e49b6ce Michael Hanselmann
    @type cluster_name: string
1981 7e49b6ce Michael Hanselmann
    @param cluster_name: Cluster name
1982 7e49b6ce Michael Hanselmann
    @type master_node: string
1983 7e49b6ce Michael Hanselmann
    @param master_node Master node name
1984 7e49b6ce Michael Hanselmann
    @type online_nodes: list
1985 7e49b6ce Michael Hanselmann
    @param online_nodes: List of names of online nodes
1986 7e49b6ce Michael Hanselmann

1987 7e49b6ce Michael Hanselmann
    """
1988 7e49b6ce Michael Hanselmann
    self.feedback_fn = feedback_fn
1989 7e49b6ce Michael Hanselmann
    self.cluster_name = cluster_name
1990 7e49b6ce Michael Hanselmann
    self.master_node = master_node
1991 7e49b6ce Michael Hanselmann
    self.online_nodes = online_nodes
1992 7e49b6ce Michael Hanselmann
1993 7e49b6ce Michael Hanselmann
    self.ssh = ssh.SshRunner(self.cluster_name)
1994 7e49b6ce Michael Hanselmann
1995 7e49b6ce Michael Hanselmann
    self.nonmaster_nodes = [name for name in online_nodes
1996 7e49b6ce Michael Hanselmann
                            if name != master_node]
1997 7e49b6ce Michael Hanselmann
1998 7e49b6ce Michael Hanselmann
    assert self.master_node not in self.nonmaster_nodes
1999 7e49b6ce Michael Hanselmann
2000 7e49b6ce Michael Hanselmann
  def _RunCmd(self, node_name, cmd):
2001 7e49b6ce Michael Hanselmann
    """Runs a command on the local or a remote machine.
2002 7e49b6ce Michael Hanselmann

2003 7e49b6ce Michael Hanselmann
    @type node_name: string
2004 7e49b6ce Michael Hanselmann
    @param node_name: Machine name
2005 7e49b6ce Michael Hanselmann
    @type cmd: list
2006 7e49b6ce Michael Hanselmann
    @param cmd: Command
2007 7e49b6ce Michael Hanselmann

2008 7e49b6ce Michael Hanselmann
    """
2009 7e49b6ce Michael Hanselmann
    if node_name is None or node_name == self.master_node:
2010 7e49b6ce Michael Hanselmann
      # No need to use SSH
2011 7e49b6ce Michael Hanselmann
      result = utils.RunCmd(cmd)
2012 7e49b6ce Michael Hanselmann
    else:
2013 7e49b6ce Michael Hanselmann
      result = self.ssh.Run(node_name, "root", utils.ShellQuoteArgs(cmd))
2014 7e49b6ce Michael Hanselmann
2015 7e49b6ce Michael Hanselmann
    if result.failed:
2016 7e49b6ce Michael Hanselmann
      errmsg = ["Failed to run command %s" % result.cmd]
2017 7e49b6ce Michael Hanselmann
      if node_name:
2018 7e49b6ce Michael Hanselmann
        errmsg.append("on node %s" % node_name)
2019 7e49b6ce Michael Hanselmann
      errmsg.append(": exitcode %s and error %s" %
2020 7e49b6ce Michael Hanselmann
                    (result.exit_code, result.output))
2021 7e49b6ce Michael Hanselmann
      raise errors.OpExecError(" ".join(errmsg))
2022 7e49b6ce Michael Hanselmann
2023 7e49b6ce Michael Hanselmann
  def Call(self, fn, *args):
2024 7e49b6ce Michael Hanselmann
    """Call function while all daemons are stopped.
2025 7e49b6ce Michael Hanselmann

2026 7e49b6ce Michael Hanselmann
    @type fn: callable
2027 7e49b6ce Michael Hanselmann
    @param fn: Function to be called
2028 7e49b6ce Michael Hanselmann

2029 7e49b6ce Michael Hanselmann
    """
2030 7e49b6ce Michael Hanselmann
    # Pause watcher by acquiring an exclusive lock on watcher state file
2031 7e49b6ce Michael Hanselmann
    self.feedback_fn("Blocking watcher")
2032 7e49b6ce Michael Hanselmann
    watcher_block = utils.FileLock.Open(constants.WATCHER_STATEFILE)
2033 7e49b6ce Michael Hanselmann
    try:
2034 7e49b6ce Michael Hanselmann
      # TODO: Currently, this just blocks. There's no timeout.
2035 7e49b6ce Michael Hanselmann
      # TODO: Should it be a shared lock?
2036 7e49b6ce Michael Hanselmann
      watcher_block.Exclusive(blocking=True)
2037 7e49b6ce Michael Hanselmann
2038 7e49b6ce Michael Hanselmann
      # Stop master daemons, so that no new jobs can come in and all running
2039 7e49b6ce Michael Hanselmann
      # ones are finished
2040 7e49b6ce Michael Hanselmann
      self.feedback_fn("Stopping master daemons")
2041 7e49b6ce Michael Hanselmann
      self._RunCmd(None, [constants.DAEMON_UTIL, "stop-master"])
2042 7e49b6ce Michael Hanselmann
      try:
2043 7e49b6ce Michael Hanselmann
        # Stop daemons on all nodes
2044 7e49b6ce Michael Hanselmann
        for node_name in self.online_nodes:
2045 7e49b6ce Michael Hanselmann
          self.feedback_fn("Stopping daemons on %s" % node_name)
2046 7e49b6ce Michael Hanselmann
          self._RunCmd(node_name, [constants.DAEMON_UTIL, "stop-all"])
2047 7e49b6ce Michael Hanselmann
2048 7e49b6ce Michael Hanselmann
        # All daemons are shut down now
2049 7e49b6ce Michael Hanselmann
        try:
2050 7e49b6ce Michael Hanselmann
          return fn(self, *args)
2051 d512e84b Michael Hanselmann
        except Exception, err:
2052 d512e84b Michael Hanselmann
          _, errmsg = FormatError(err)
2053 7e49b6ce Michael Hanselmann
          logging.exception("Caught exception")
2054 d512e84b Michael Hanselmann
          self.feedback_fn(errmsg)
2055 7e49b6ce Michael Hanselmann
          raise
2056 7e49b6ce Michael Hanselmann
      finally:
2057 7e49b6ce Michael Hanselmann
        # Start cluster again, master node last
2058 7e49b6ce Michael Hanselmann
        for node_name in self.nonmaster_nodes + [self.master_node]:
2059 7e49b6ce Michael Hanselmann
          self.feedback_fn("Starting daemons on %s" % node_name)
2060 7e49b6ce Michael Hanselmann
          self._RunCmd(node_name, [constants.DAEMON_UTIL, "start-all"])
2061 7e49b6ce Michael Hanselmann
    finally:
2062 7e49b6ce Michael Hanselmann
      # Resume watcher
2063 7e49b6ce Michael Hanselmann
      watcher_block.Close()
2064 7e49b6ce Michael Hanselmann
2065 7e49b6ce Michael Hanselmann
2066 7e49b6ce Michael Hanselmann
def RunWhileClusterStopped(feedback_fn, fn, *args):
2067 7e49b6ce Michael Hanselmann
  """Calls a function while all cluster daemons are stopped.
2068 7e49b6ce Michael Hanselmann

2069 7e49b6ce Michael Hanselmann
  @type feedback_fn: callable
2070 7e49b6ce Michael Hanselmann
  @param feedback_fn: Feedback function
2071 7e49b6ce Michael Hanselmann
  @type fn: callable
2072 7e49b6ce Michael Hanselmann
  @param fn: Function to be called when daemons are stopped
2073 7e49b6ce Michael Hanselmann

2074 7e49b6ce Michael Hanselmann
  """
2075 7e49b6ce Michael Hanselmann
  feedback_fn("Gathering cluster information")
2076 7e49b6ce Michael Hanselmann
2077 7e49b6ce Michael Hanselmann
  # This ensures we're running on the master daemon
2078 7e49b6ce Michael Hanselmann
  cl = GetClient()
2079 7e49b6ce Michael Hanselmann
2080 7e49b6ce Michael Hanselmann
  (cluster_name, master_node) = \
2081 7e49b6ce Michael Hanselmann
    cl.QueryConfigValues(["cluster_name", "master_node"])
2082 7e49b6ce Michael Hanselmann
2083 7e49b6ce Michael Hanselmann
  online_nodes = GetOnlineNodes([], cl=cl)
2084 7e49b6ce Michael Hanselmann
2085 7e49b6ce Michael Hanselmann
  # Don't keep a reference to the client. The master daemon will go away.
2086 7e49b6ce Michael Hanselmann
  del cl
2087 7e49b6ce Michael Hanselmann
2088 7e49b6ce Michael Hanselmann
  assert master_node in online_nodes
2089 7e49b6ce Michael Hanselmann
2090 7e49b6ce Michael Hanselmann
  return _RunWhileClusterStoppedHelper(feedback_fn, cluster_name, master_node,
2091 7e49b6ce Michael Hanselmann
                                       online_nodes).Call(fn, *args)
2092 7e49b6ce Michael Hanselmann
2093 7e49b6ce Michael Hanselmann
2094 16be8703 Iustin Pop
def GenerateTable(headers, fields, separator, data,
2095 9fbfbb7b Iustin Pop
                  numfields=None, unitfields=None,
2096 9fbfbb7b Iustin Pop
                  units=None):
2097 137161c9 Michael Hanselmann
  """Prints a table with headers and different fields.
2098 137161c9 Michael Hanselmann

2099 9fbfbb7b Iustin Pop
  @type headers: dict
2100 9fbfbb7b Iustin Pop
  @param headers: dictionary mapping field names to headers for
2101 9fbfbb7b Iustin Pop
      the table
2102 9fbfbb7b Iustin Pop
  @type fields: list
2103 9fbfbb7b Iustin Pop
  @param fields: the field names corresponding to each row in
2104 9fbfbb7b Iustin Pop
      the data field
2105 9fbfbb7b Iustin Pop
  @param separator: the separator to be used; if this is None,
2106 9fbfbb7b Iustin Pop
      the default 'smart' algorithm is used which computes optimal
2107 9fbfbb7b Iustin Pop
      field width, otherwise just the separator is used between
2108 9fbfbb7b Iustin Pop
      each field
2109 9fbfbb7b Iustin Pop
  @type data: list
2110 9fbfbb7b Iustin Pop
  @param data: a list of lists, each sublist being one row to be output
2111 9fbfbb7b Iustin Pop
  @type numfields: list
2112 9fbfbb7b Iustin Pop
  @param numfields: a list with the fields that hold numeric
2113 9fbfbb7b Iustin Pop
      values and thus should be right-aligned
2114 9fbfbb7b Iustin Pop
  @type unitfields: list
2115 9fbfbb7b Iustin Pop
  @param unitfields: a list with the fields that hold numeric
2116 9fbfbb7b Iustin Pop
      values that should be formatted with the units field
2117 9fbfbb7b Iustin Pop
  @type units: string or None
2118 9fbfbb7b Iustin Pop
  @param units: the units we should use for formatting, or None for
2119 9fbfbb7b Iustin Pop
      automatic choice (human-readable for non-separator usage, otherwise
2120 9fbfbb7b Iustin Pop
      megabytes); this is a one-letter string
2121 137161c9 Michael Hanselmann

2122 137161c9 Michael Hanselmann
  """
2123 9fbfbb7b Iustin Pop
  if units is None:
2124 9fbfbb7b Iustin Pop
    if separator:
2125 9fbfbb7b Iustin Pop
      units = "m"
2126 9fbfbb7b Iustin Pop
    else:
2127 9fbfbb7b Iustin Pop
      units = "h"
2128 9fbfbb7b Iustin Pop
2129 137161c9 Michael Hanselmann
  if numfields is None:
2130 137161c9 Michael Hanselmann
    numfields = []
2131 137161c9 Michael Hanselmann
  if unitfields is None:
2132 137161c9 Michael Hanselmann
    unitfields = []
2133 137161c9 Michael Hanselmann
2134 fe267188 Iustin Pop
  numfields = utils.FieldSet(*numfields)   # pylint: disable-msg=W0142
2135 fe267188 Iustin Pop
  unitfields = utils.FieldSet(*unitfields) # pylint: disable-msg=W0142
2136 00430f8e Iustin Pop
2137 137161c9 Michael Hanselmann
  format_fields = []
2138 137161c9 Michael Hanselmann
  for field in fields:
2139 01ca31ae Iustin Pop
    if headers and field not in headers:
2140 ea5a5b74 Guido Trotter
      # TODO: handle better unknown fields (either revert to old
2141 71c1af58 Iustin Pop
      # style of raising exception, or deal more intelligently with
2142 71c1af58 Iustin Pop
      # variable fields)
2143 71c1af58 Iustin Pop
      headers[field] = field
2144 137161c9 Michael Hanselmann
    if separator is not None:
2145 137161c9 Michael Hanselmann
      format_fields.append("%s")
2146 00430f8e Iustin Pop
    elif numfields.Matches(field):
2147 137161c9 Michael Hanselmann
      format_fields.append("%*s")
2148 137161c9 Michael Hanselmann
    else:
2149 137161c9 Michael Hanselmann
      format_fields.append("%-*s")
2150 137161c9 Michael Hanselmann
2151 137161c9 Michael Hanselmann
  if separator is None:
2152 137161c9 Michael Hanselmann
    mlens = [0 for name in fields]
2153 c04bc777 Iustin Pop
    format_str = ' '.join(format_fields)
2154 137161c9 Michael Hanselmann
  else:
2155 c04bc777 Iustin Pop
    format_str = separator.replace("%", "%%").join(format_fields)
2156 137161c9 Michael Hanselmann
2157 137161c9 Michael Hanselmann
  for row in data:
2158 dcbd6288 Guido Trotter
    if row is None:
2159 dcbd6288 Guido Trotter
      continue
2160 137161c9 Michael Hanselmann
    for idx, val in enumerate(row):
2161 00430f8e Iustin Pop
      if unitfields.Matches(fields[idx]):
2162 137161c9 Michael Hanselmann
        try:
2163 137161c9 Michael Hanselmann
          val = int(val)
2164 691744c4 Iustin Pop
        except (TypeError, ValueError):
2165 137161c9 Michael Hanselmann
          pass
2166 137161c9 Michael Hanselmann
        else:
2167 9fbfbb7b Iustin Pop
          val = row[idx] = utils.FormatUnit(val, units)
2168 01ca31ae Iustin Pop
      val = row[idx] = str(val)
2169 137161c9 Michael Hanselmann
      if separator is None:
2170 137161c9 Michael Hanselmann
        mlens[idx] = max(mlens[idx], len(val))
2171 137161c9 Michael Hanselmann
2172 16be8703 Iustin Pop
  result = []
2173 137161c9 Michael Hanselmann
  if headers:
2174 137161c9 Michael Hanselmann
    args = []
2175 137161c9 Michael Hanselmann
    for idx, name in enumerate(fields):
2176 137161c9 Michael Hanselmann
      hdr = headers[name]
2177 137161c9 Michael Hanselmann
      if separator is None:
2178 137161c9 Michael Hanselmann
        mlens[idx] = max(mlens[idx], len(hdr))
2179 137161c9 Michael Hanselmann
        args.append(mlens[idx])
2180 137161c9 Michael Hanselmann
      args.append(hdr)
2181 c04bc777 Iustin Pop
    result.append(format_str % tuple(args))
2182 137161c9 Michael Hanselmann
2183 ec39d63c Michael Hanselmann
  if separator is None:
2184 ec39d63c Michael Hanselmann
    assert len(mlens) == len(fields)
2185 ec39d63c Michael Hanselmann
2186 ec39d63c Michael Hanselmann
    if fields and not numfields.Matches(fields[-1]):
2187 ec39d63c Michael Hanselmann
      mlens[-1] = 0
2188 ec39d63c Michael Hanselmann
2189 137161c9 Michael Hanselmann
  for line in data:
2190 137161c9 Michael Hanselmann
    args = []
2191 dcbd6288 Guido Trotter
    if line is None:
2192 dcbd6288 Guido Trotter
      line = ['-' for _ in fields]
2193 f1501b3f Michael Hanselmann
    for idx in range(len(fields)):
2194 137161c9 Michael Hanselmann
      if separator is None:
2195 137161c9 Michael Hanselmann
        args.append(mlens[idx])
2196 137161c9 Michael Hanselmann
      args.append(line[idx])
2197 c04bc777 Iustin Pop
    result.append(format_str % tuple(args))
2198 16be8703 Iustin Pop
2199 16be8703 Iustin Pop
  return result
2200 3386e7a9 Iustin Pop
2201 3386e7a9 Iustin Pop
2202 3386e7a9 Iustin Pop
def FormatTimestamp(ts):
2203 3386e7a9 Iustin Pop
  """Formats a given timestamp.
2204 3386e7a9 Iustin Pop

2205 3386e7a9 Iustin Pop
  @type ts: timestamp
2206 3386e7a9 Iustin Pop
  @param ts: a timeval-type timestamp, a tuple of seconds and microseconds
2207 3386e7a9 Iustin Pop

2208 3386e7a9 Iustin Pop
  @rtype: string
2209 5fcc718f Iustin Pop
  @return: a string with the formatted timestamp
2210 3386e7a9 Iustin Pop

2211 3386e7a9 Iustin Pop
  """
2212 e0ec0ff6 Iustin Pop
  if not isinstance (ts, (tuple, list)) or len(ts) != 2:
2213 e0ec0ff6 Iustin Pop
    return '?'
2214 3386e7a9 Iustin Pop
  sec, usec = ts
2215 3386e7a9 Iustin Pop
  return time.strftime("%F %T", time.localtime(sec)) + ".%06d" % usec
2216 2241e2b9 Iustin Pop
2217 2241e2b9 Iustin Pop
2218 2241e2b9 Iustin Pop
def ParseTimespec(value):
2219 2241e2b9 Iustin Pop
  """Parse a time specification.
2220 2241e2b9 Iustin Pop

2221 2241e2b9 Iustin Pop
  The following suffixed will be recognized:
2222 2241e2b9 Iustin Pop

2223 2241e2b9 Iustin Pop
    - s: seconds
2224 2241e2b9 Iustin Pop
    - m: minutes
2225 2241e2b9 Iustin Pop
    - h: hours
2226 2241e2b9 Iustin Pop
    - d: day
2227 2241e2b9 Iustin Pop
    - w: weeks
2228 2241e2b9 Iustin Pop

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

2231 2241e2b9 Iustin Pop
  """
2232 2241e2b9 Iustin Pop
  value = str(value)
2233 2241e2b9 Iustin Pop
  if not value:
2234 2241e2b9 Iustin Pop
    raise errors.OpPrereqError("Empty time specification passed")
2235 2241e2b9 Iustin Pop
  suffix_map = {
2236 2241e2b9 Iustin Pop
    's': 1,
2237 2241e2b9 Iustin Pop
    'm': 60,
2238 2241e2b9 Iustin Pop
    'h': 3600,
2239 2241e2b9 Iustin Pop
    'd': 86400,
2240 2241e2b9 Iustin Pop
    'w': 604800,
2241 2241e2b9 Iustin Pop
    }
2242 2241e2b9 Iustin Pop
  if value[-1] not in suffix_map:
2243 2241e2b9 Iustin Pop
    try:
2244 2241e2b9 Iustin Pop
      value = int(value)
2245 691744c4 Iustin Pop
    except (TypeError, ValueError):
2246 2241e2b9 Iustin Pop
      raise errors.OpPrereqError("Invalid time specification '%s'" % value)
2247 2241e2b9 Iustin Pop
  else:
2248 2241e2b9 Iustin Pop
    multiplier = suffix_map[value[-1]]
2249 2241e2b9 Iustin Pop
    value = value[:-1]
2250 2241e2b9 Iustin Pop
    if not value: # no data left after stripping the suffix
2251 2241e2b9 Iustin Pop
      raise errors.OpPrereqError("Invalid time specification (only"
2252 2241e2b9 Iustin Pop
                                 " suffix passed)")
2253 2241e2b9 Iustin Pop
    try:
2254 2241e2b9 Iustin Pop
      value = int(value) * multiplier
2255 691744c4 Iustin Pop
    except (TypeError, ValueError):
2256 2241e2b9 Iustin Pop
      raise errors.OpPrereqError("Invalid time specification '%s'" % value)
2257 2241e2b9 Iustin Pop
  return value
2258 46fbdd04 Iustin Pop
2259 46fbdd04 Iustin Pop
2260 e9e26bb3 Iustin Pop
def GetOnlineNodes(nodes, cl=None, nowarn=False, secondary_ips=False,
2261 e9e26bb3 Iustin Pop
                   filter_master=False):
2262 4040a784 Iustin Pop
  """Returns the names of online nodes.
2263 4040a784 Iustin Pop

2264 4040a784 Iustin Pop
  This function will also log a warning on stderr with the names of
2265 4040a784 Iustin Pop
  the online nodes.
2266 4040a784 Iustin Pop

2267 4040a784 Iustin Pop
  @param nodes: if not empty, use only this subset of nodes (minus the
2268 4040a784 Iustin Pop
      offline ones)
2269 4040a784 Iustin Pop
  @param cl: if not None, luxi client to use
2270 4040a784 Iustin Pop
  @type nowarn: boolean
2271 4040a784 Iustin Pop
  @param nowarn: by default, this function will output a note with the
2272 4040a784 Iustin Pop
      offline nodes that are skipped; if this parameter is True the
2273 4040a784 Iustin Pop
      note is not displayed
2274 e9e26bb3 Iustin Pop
  @type secondary_ips: boolean
2275 e9e26bb3 Iustin Pop
  @param secondary_ips: if True, return the secondary IPs instead of the
2276 e9e26bb3 Iustin Pop
      names, useful for doing network traffic over the replication interface
2277 e9e26bb3 Iustin Pop
      (if any)
2278 e9e26bb3 Iustin Pop
  @type filter_master: boolean
2279 e9e26bb3 Iustin Pop
  @param filter_master: if True, do not return the master node in the list
2280 e9e26bb3 Iustin Pop
      (useful in coordination with secondary_ips where we cannot check our
2281 e9e26bb3 Iustin Pop
      node name against the list)
2282 4040a784 Iustin Pop

2283 4040a784 Iustin Pop
  """
2284 4040a784 Iustin Pop
  if cl is None:
2285 4040a784 Iustin Pop
    cl = GetClient()
2286 4040a784 Iustin Pop
2287 e9e26bb3 Iustin Pop
  if secondary_ips:
2288 e9e26bb3 Iustin Pop
    name_idx = 2
2289 e9e26bb3 Iustin Pop
  else:
2290 e9e26bb3 Iustin Pop
    name_idx = 0
2291 e9e26bb3 Iustin Pop
2292 e9e26bb3 Iustin Pop
  if filter_master:
2293 e9e26bb3 Iustin Pop
    master_node = cl.QueryConfigValues(["master_node"])[0]
2294 e9e26bb3 Iustin Pop
    filter_fn = lambda x: x != master_node
2295 e9e26bb3 Iustin Pop
  else:
2296 e9e26bb3 Iustin Pop
    filter_fn = lambda _: True
2297 e9e26bb3 Iustin Pop
2298 e9e26bb3 Iustin Pop
  result = cl.QueryNodes(names=nodes, fields=["name", "offline", "sip"],
2299 2e7b8369 Iustin Pop
                         use_locking=False)
2300 4040a784 Iustin Pop
  offline = [row[0] for row in result if row[1]]
2301 4040a784 Iustin Pop
  if offline and not nowarn:
2302 1f864b60 Iustin Pop
    ToStderr("Note: skipping offline node(s): %s" % utils.CommaJoin(offline))
2303 e9e26bb3 Iustin Pop
  return [row[name_idx] for row in result if not row[1] and filter_fn(row[0])]
2304 4040a784 Iustin Pop
2305 4040a784 Iustin Pop
2306 46fbdd04 Iustin Pop
def _ToStream(stream, txt, *args):
2307 46fbdd04 Iustin Pop
  """Write a message to a stream, bypassing the logging system
2308 46fbdd04 Iustin Pop

2309 46fbdd04 Iustin Pop
  @type stream: file object
2310 46fbdd04 Iustin Pop
  @param stream: the file to which we should write
2311 46fbdd04 Iustin Pop
  @type txt: str
2312 46fbdd04 Iustin Pop
  @param txt: the message
2313 46fbdd04 Iustin Pop

2314 46fbdd04 Iustin Pop
  """
2315 46fbdd04 Iustin Pop
  if args:
2316 46fbdd04 Iustin Pop
    args = tuple(args)
2317 46fbdd04 Iustin Pop
    stream.write(txt % args)
2318 46fbdd04 Iustin Pop
  else:
2319 46fbdd04 Iustin Pop
    stream.write(txt)
2320 46fbdd04 Iustin Pop
  stream.write('\n')
2321 46fbdd04 Iustin Pop
  stream.flush()
2322 46fbdd04 Iustin Pop
2323 46fbdd04 Iustin Pop
2324 46fbdd04 Iustin Pop
def ToStdout(txt, *args):
2325 46fbdd04 Iustin Pop
  """Write a message to stdout only, bypassing the logging system
2326 46fbdd04 Iustin Pop

2327 46fbdd04 Iustin Pop
  This is just a wrapper over _ToStream.
2328 46fbdd04 Iustin Pop

2329 46fbdd04 Iustin Pop
  @type txt: str
2330 46fbdd04 Iustin Pop
  @param txt: the message
2331 46fbdd04 Iustin Pop

2332 46fbdd04 Iustin Pop
  """
2333 46fbdd04 Iustin Pop
  _ToStream(sys.stdout, txt, *args)
2334 46fbdd04 Iustin Pop
2335 46fbdd04 Iustin Pop
2336 46fbdd04 Iustin Pop
def ToStderr(txt, *args):
2337 46fbdd04 Iustin Pop
  """Write a message to stderr only, bypassing the logging system
2338 46fbdd04 Iustin Pop

2339 46fbdd04 Iustin Pop
  This is just a wrapper over _ToStream.
2340 46fbdd04 Iustin Pop

2341 46fbdd04 Iustin Pop
  @type txt: str
2342 46fbdd04 Iustin Pop
  @param txt: the message
2343 46fbdd04 Iustin Pop

2344 46fbdd04 Iustin Pop
  """
2345 46fbdd04 Iustin Pop
  _ToStream(sys.stderr, txt, *args)
2346 479636a3 Iustin Pop
2347 479636a3 Iustin Pop
2348 479636a3 Iustin Pop
class JobExecutor(object):
2349 479636a3 Iustin Pop
  """Class which manages the submission and execution of multiple jobs.
2350 479636a3 Iustin Pop

2351 479636a3 Iustin Pop
  Note that instances of this class should not be reused between
2352 479636a3 Iustin Pop
  GetResults() calls.
2353 479636a3 Iustin Pop

2354 479636a3 Iustin Pop
  """
2355 919ca415 Iustin Pop
  def __init__(self, cl=None, verbose=True, opts=None, feedback_fn=None):
2356 479636a3 Iustin Pop
    self.queue = []
2357 479636a3 Iustin Pop
    if cl is None:
2358 479636a3 Iustin Pop
      cl = GetClient()
2359 479636a3 Iustin Pop
    self.cl = cl
2360 479636a3 Iustin Pop
    self.verbose = verbose
2361 23b4b983 Iustin Pop
    self.jobs = []
2362 cff5fa7f Iustin Pop
    self.opts = opts
2363 919ca415 Iustin Pop
    self.feedback_fn = feedback_fn
2364 479636a3 Iustin Pop
2365 479636a3 Iustin Pop
  def QueueJob(self, name, *ops):
2366 23b4b983 Iustin Pop
    """Record a job for later submit.
2367 479636a3 Iustin Pop

2368 479636a3 Iustin Pop
    @type name: string
2369 479636a3 Iustin Pop
    @param name: a description of the job, will be used in WaitJobSet
2370 479636a3 Iustin Pop
    """
2371 cff5fa7f Iustin Pop
    SetGenericOpcodeOpts(ops, self.opts)
2372 23b4b983 Iustin Pop
    self.queue.append((name, ops))
2373 23b4b983 Iustin Pop
2374 66ecc479 Guido Trotter
  def SubmitPending(self, each=False):
2375 23b4b983 Iustin Pop
    """Submit all pending jobs.
2376 23b4b983 Iustin Pop

2377 23b4b983 Iustin Pop
    """
2378 66ecc479 Guido Trotter
    if each:
2379 66ecc479 Guido Trotter
      results = []
2380 66ecc479 Guido Trotter
      for row in self.queue:
2381 66ecc479 Guido Trotter
        # SubmitJob will remove the success status, but raise an exception if
2382 66ecc479 Guido Trotter
        # the submission fails, so we'll notice that anyway.
2383 66ecc479 Guido Trotter
        results.append([True, self.cl.SubmitJob(row[1])])
2384 66ecc479 Guido Trotter
    else:
2385 66ecc479 Guido Trotter
      results = self.cl.SubmitManyJobs([row[1] for row in self.queue])
2386 5299e61f Iustin Pop
    for (idx, ((status, data), (name, _))) in enumerate(zip(results,
2387 5299e61f Iustin Pop
                                                            self.queue)):
2388 5299e61f Iustin Pop
      self.jobs.append((idx, status, data, name))
2389 5299e61f Iustin Pop
2390 5299e61f Iustin Pop
  def _ChooseJob(self):
2391 5299e61f Iustin Pop
    """Choose a non-waiting/queued job to poll next.
2392 5299e61f Iustin Pop

2393 5299e61f Iustin Pop
    """
2394 5299e61f Iustin Pop
    assert self.jobs, "_ChooseJob called with empty job list"
2395 5299e61f Iustin Pop
2396 5299e61f Iustin Pop
    result = self.cl.QueryJobs([i[2] for i in self.jobs], ["status"])
2397 5299e61f Iustin Pop
    assert result
2398 5299e61f Iustin Pop
2399 5299e61f Iustin Pop
    for job_data, status in zip(self.jobs, result):
2400 91c622a8 Iustin Pop
      if (isinstance(status, list) and status and
2401 91c622a8 Iustin Pop
          status[0] in (constants.JOB_STATUS_QUEUED,
2402 91c622a8 Iustin Pop
                        constants.JOB_STATUS_WAITLOCK,
2403 91c622a8 Iustin Pop
                        constants.JOB_STATUS_CANCELING)):
2404 91c622a8 Iustin Pop
        # job is still present and waiting
2405 5299e61f Iustin Pop
        continue
2406 91c622a8 Iustin Pop
      # good candidate found (either running job or lost job)
2407 5299e61f Iustin Pop
      self.jobs.remove(job_data)
2408 5299e61f Iustin Pop
      return job_data
2409 5299e61f Iustin Pop
2410 5299e61f Iustin Pop
    # no job found
2411 5299e61f Iustin Pop
    return self.jobs.pop(0)
2412 479636a3 Iustin Pop
2413 479636a3 Iustin Pop
  def GetResults(self):
2414 479636a3 Iustin Pop
    """Wait for and return the results of all jobs.
2415 479636a3 Iustin Pop

2416 479636a3 Iustin Pop
    @rtype: list
2417 479636a3 Iustin Pop
    @return: list of tuples (success, job results), in the same order
2418 479636a3 Iustin Pop
        as the submitted jobs; if a job has failed, instead of the result
2419 479636a3 Iustin Pop
        there will be the error message
2420 479636a3 Iustin Pop

2421 479636a3 Iustin Pop
    """
2422 23b4b983 Iustin Pop
    if not self.jobs:
2423 23b4b983 Iustin Pop
      self.SubmitPending()
2424 479636a3 Iustin Pop
    results = []
2425 479636a3 Iustin Pop
    if self.verbose:
2426 5299e61f Iustin Pop
      ok_jobs = [row[2] for row in self.jobs if row[1]]
2427 23b4b983 Iustin Pop
      if ok_jobs:
2428 1f864b60 Iustin Pop
        ToStdout("Submitted jobs %s", utils.CommaJoin(ok_jobs))
2429 5299e61f Iustin Pop
2430 5299e61f Iustin Pop
    # first, remove any non-submitted jobs
2431 cea881e5 Michael Hanselmann
    self.jobs, failures = compat.partition(self.jobs, lambda x: x[1])
2432 5299e61f Iustin Pop
    for idx, _, jid, name in failures:
2433 c63355f2 Iustin Pop
      ToStderr("Failed to submit job for %s: %s", name, jid)
2434 c63355f2 Iustin Pop
      results.append((idx, False, jid))
2435 5299e61f Iustin Pop
2436 5299e61f Iustin Pop
    while self.jobs:
2437 5299e61f Iustin Pop
      (idx, _, jid, name) = self._ChooseJob()
2438 5299e61f Iustin Pop
      ToStdout("Waiting for job %s for %s...", jid, name)
2439 479636a3 Iustin Pop
      try:
2440 919ca415 Iustin Pop
        job_result = PollJob(jid, cl=self.cl, feedback_fn=self.feedback_fn)
2441 479636a3 Iustin Pop
        success = True
2442 91c622a8 Iustin Pop
      except errors.JobLost, err:
2443 91c622a8 Iustin Pop
        _, job_result = FormatError(err)
2444 91c622a8 Iustin Pop
        ToStderr("Job %s for %s has been archived, cannot check its result",
2445 91c622a8 Iustin Pop
                 jid, name)
2446 91c622a8 Iustin Pop
        success = False
2447 479636a3 Iustin Pop
      except (errors.GenericError, luxi.ProtocolError), err:
2448 479636a3 Iustin Pop
        _, job_result = FormatError(err)
2449 479636a3 Iustin Pop
        success = False
2450 479636a3 Iustin Pop
        # the error message will always be shown, verbose or not
2451 479636a3 Iustin Pop
        ToStderr("Job %s for %s has failed: %s", jid, name, job_result)
2452 479636a3 Iustin Pop
2453 5299e61f Iustin Pop
      results.append((idx, success, job_result))
2454 5299e61f Iustin Pop
2455 5299e61f Iustin Pop
    # sort based on the index, then drop it
2456 5299e61f Iustin Pop
    results.sort()
2457 5299e61f Iustin Pop
    results = [i[1:] for i in results]
2458 5299e61f Iustin Pop
2459 479636a3 Iustin Pop
    return results
2460 479636a3 Iustin Pop
2461 479636a3 Iustin Pop
  def WaitOrShow(self, wait):
2462 479636a3 Iustin Pop
    """Wait for job results or only print the job IDs.
2463 479636a3 Iustin Pop

2464 479636a3 Iustin Pop
    @type wait: boolean
2465 479636a3 Iustin Pop
    @param wait: whether to wait or not
2466 479636a3 Iustin Pop

2467 479636a3 Iustin Pop
    """
2468 479636a3 Iustin Pop
    if wait:
2469 479636a3 Iustin Pop
      return self.GetResults()
2470 479636a3 Iustin Pop
    else:
2471 23b4b983 Iustin Pop
      if not self.jobs:
2472 23b4b983 Iustin Pop
        self.SubmitPending()
2473 71834b2a Guido Trotter
      for _, status, result, name in self.jobs:
2474 23b4b983 Iustin Pop
        if status:
2475 23b4b983 Iustin Pop
          ToStdout("%s: %s", result, name)
2476 23b4b983 Iustin Pop
        else:
2477 23b4b983 Iustin Pop
          ToStderr("Failure for %s: %s", name, result)
2478 53a8a54d Iustin Pop
      return [row[1:3] for row in self.jobs]