Statistics
| Branch: | Tag: | Revision:

root / lib / cli.py @ 499eb088

History | View | Annotate | Download (108.4 kB)

1 2f31098c Iustin Pop
#
2 a8083063 Iustin Pop
#
3 a8083063 Iustin Pop
4 18009c1e Iustin Pop
# Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011 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 225e2544 Iustin Pop
import errno
31 60452edf Michael Hanselmann
import itertools
32 ef9fa5b9 René Nussbaumer
import shlex
33 73702ee7 Iustin Pop
from cStringIO import StringIO
34 a8083063 Iustin Pop
35 a8083063 Iustin Pop
from ganeti import utils
36 a8083063 Iustin Pop
from ganeti import errors
37 a8083063 Iustin Pop
from ganeti import constants
38 846baef9 Iustin Pop
from ganeti import opcodes
39 ceab32dd Iustin Pop
from ganeti import luxi
40 b33e986b Iustin Pop
from ganeti import ssconf
41 4331f6cd Michael Hanselmann
from ganeti import rpc
42 7e49b6ce Michael Hanselmann
from ganeti import ssh
43 cea881e5 Michael Hanselmann
from ganeti import compat
44 a744b676 Manuel Franceschini
from ganeti import netutils
45 ee3aedff Michael Hanselmann
from ganeti import qlang
46 a8083063 Iustin Pop
47 c38c44ad Michael Hanselmann
from optparse import (OptionParser, TitledHelpFormatter,
48 38206f3c Iustin Pop
                      Option, OptionValueError)
49 a8083063 Iustin Pop
50 03298ebe Michael Hanselmann
51 4abc4f1e Iustin Pop
__all__ = [
52 4abc4f1e Iustin Pop
  # Command line options
53 fdad8c4d Balazs Lecz
  "ADD_UIDS_OPT",
54 e7e09483 Iustin Pop
  "ALLOCATABLE_OPT",
55 90e99856 Adeodato Simo
  "ALLOC_POLICY_OPT",
56 2d5e7ae1 Iustin Pop
  "ALL_OPT",
57 e9c487be René Nussbaumer
  "ALLOW_FAILOVER_OPT",
58 4c61d894 Iustin Pop
  "AUTO_PROMOTE_OPT",
59 e00f7a05 Iustin Pop
  "AUTO_REPLACE_OPT",
60 087ed2ed Iustin Pop
  "BACKEND_OPT",
61 61a14bb3 Iustin Pop
  "BLK_OS_OPT",
62 f91e255a Iustin Pop
  "CAPAB_MASTER_OPT",
63 53919782 Iustin Pop
  "CAPAB_VM_OPT",
64 baef337d Iustin Pop
  "CLEANUP_OPT",
65 3db3eb2a Michael Hanselmann
  "CLUSTER_DOMAIN_SECRET_OPT",
66 4abc4f1e Iustin Pop
  "CONFIRM_OPT",
67 e32df528 Iustin Pop
  "CP_SIZE_OPT",
68 4abc4f1e Iustin Pop
  "DEBUG_OPT",
69 a0c9776a Iustin Pop
  "DEBUG_SIMERR_OPT",
70 4b038a1e Iustin Pop
  "DISKIDX_OPT",
71 e3876ccb Iustin Pop
  "DISK_OPT",
72 bc5d0215 Andrea Spadaccini
  "DISK_PARAMS_OPT",
73 4b038a1e Iustin Pop
  "DISK_TEMPLATE_OPT",
74 771734c9 Iustin Pop
  "DRAINED_OPT",
75 a0a6ff34 Iustin Pop
  "DRY_RUN_OPT",
76 26591bfd Luca Bigliardi
  "DRBD_HELPER_OPT",
77 1b7761fd Apollon Oikonomopoulos
  "DST_NODE_OPT",
78 7ea7bcf6 Iustin Pop
  "EARLY_RELEASE_OPT",
79 383a3591 Iustin Pop
  "ENABLED_HV_OPT",
80 14e9e7f3 Iustin Pop
  "ERROR_CODES_OPT",
81 4abc4f1e Iustin Pop
  "FIELDS_OPT",
82 4a25828c Iustin Pop
  "FILESTORE_DIR_OPT",
83 0f87c43e Iustin Pop
  "FILESTORE_DRIVER_OPT",
84 442587bf Michael Hanselmann
  "FORCE_FILTER_OPT",
85 06073e85 Guido Trotter
  "FORCE_OPT",
86 06073e85 Guido Trotter
  "FORCE_VARIANT_OPT",
87 29392516 Iustin Pop
  "GLOBAL_FILEDIR_OPT",
88 61a14bb3 Iustin Pop
  "HID_OS_OPT",
89 4b97f902 Apollon Oikonomopoulos
  "GLOBAL_SHARED_FILEDIR_OPT",
90 073271f6 Iustin Pop
  "HVLIST_OPT",
91 48f212d7 Iustin Pop
  "HVOPTS_OPT",
92 236fd9c4 Iustin Pop
  "HYPERVISOR_OPT",
93 4eb62659 Iustin Pop
  "IALLOCATOR_OPT",
94 bf4af505 Apollon Oikonomopoulos
  "DEFAULT_IALLOCATOR_OPT",
95 e588764d Iustin Pop
  "IDENTIFY_DEFAULTS_OPT",
96 82a786d5 Iustin Pop
  "IGNORE_CONSIST_OPT",
97 93f2399e Andrea Spadaccini
  "IGNORE_ERRORS_OPT",
98 b6e841a8 Iustin Pop
  "IGNORE_FAILURES_OPT",
99 b44bd844 Michael Hanselmann
  "IGNORE_OFFLINE_OPT",
100 8d8d650c Michael Hanselmann
  "IGNORE_REMOVE_FAILURES_OPT",
101 ee3f9578 Iustin Pop
  "IGNORE_SECONDARIES_OPT",
102 05586c90 Iustin Pop
  "IGNORE_SIZE_OPT",
103 19b9ba9a Michael Hanselmann
  "INTERVAL_OPT",
104 e3646f22 Iustin Pop
  "MAC_PREFIX_OPT",
105 3953242f Iustin Pop
  "MAINTAIN_NODE_HEALTH_OPT",
106 29392516 Iustin Pop
  "MASTER_NETDEV_OPT",
107 5a8648eb Andrea Spadaccini
  "MASTER_NETMASK_OPT",
108 771734c9 Iustin Pop
  "MC_OPT",
109 783a6c0b Iustin Pop
  "MIGRATION_MODE_OPT",
110 7d3a9fab Iustin Pop
  "NET_OPT",
111 6d4a1656 Michael Hanselmann
  "NEW_CLUSTER_CERT_OPT",
112 3db3eb2a Michael Hanselmann
  "NEW_CLUSTER_DOMAIN_SECRET_OPT",
113 6b7d5878 Michael Hanselmann
  "NEW_CONFD_HMAC_KEY_OPT",
114 6d4a1656 Michael Hanselmann
  "NEW_RAPI_CERT_OPT",
115 a14db5ff Iustin Pop
  "NEW_SECONDARY_OPT",
116 b6267745 Andrea Spadaccini
  "NEW_SPICE_CERT_OPT",
117 4fbc93dd Iustin Pop
  "NIC_PARAMS_OPT",
118 61413377 Stephen Shirley
  "NODE_FORCE_JOIN_OPT",
119 7edc4637 Iustin Pop
  "NODE_LIST_OPT",
120 990b7886 Iustin Pop
  "NODE_PLACEMENT_OPT",
121 5fbbd028 Guido Trotter
  "NODEGROUP_OPT",
122 a535cef7 René Nussbaumer
  "NODE_PARAMS_OPT",
123 dd94e9f6 René Nussbaumer
  "NODE_POWERED_OPT",
124 26591bfd Luca Bigliardi
  "NODRBD_STORAGE_OPT",
125 4abc4f1e Iustin Pop
  "NOHDR_OPT",
126 91e0748c Iustin Pop
  "NOIPCHECK_OPT",
127 25a8792c Iustin Pop
  "NO_INSTALL_OPT",
128 460d22be Iustin Pop
  "NONAMECHECK_OPT",
129 831040bf Iustin Pop
  "NOLVM_STORAGE_OPT",
130 29392516 Iustin Pop
  "NOMODIFY_ETCHOSTS_OPT",
131 b989b9d9 Ken Wehr
  "NOMODIFY_SSH_SETUP_OPT",
132 26023ecd Iustin Pop
  "NONICS_OPT",
133 f2a0828c Iustin Pop
  "NONLIVE_OPT",
134 14e9e7f3 Iustin Pop
  "NONPLUS1_OPT",
135 44c44832 Iustin Pop
  "NOSHUTDOWN_OPT",
136 edeb878a Iustin Pop
  "NOSTART_OPT",
137 fcdde7f2 Iustin Pop
  "NOSSH_KEYCHECK_OPT",
138 58371861 Iustin Pop
  "NOVOTING_OPT",
139 885a0fc4 Iustin Pop
  "NO_REMEMBER_OPT",
140 3f75b4f3 Iustin Pop
  "NWSYNC_OPT",
141 57de31c0 Agata Murawska
  "OFFLINE_INST_OPT",
142 57de31c0 Agata Murawska
  "ONLINE_INST_OPT",
143 a72d0a79 Iustin Pop
  "ON_PRIMARY_OPT",
144 feb09e6a Iustin Pop
  "ON_SECONDARY_OPT",
145 771734c9 Iustin Pop
  "OFFLINE_OPT",
146 062a7100 Iustin Pop
  "OSPARAMS_OPT",
147 d3ed23ff Iustin Pop
  "OS_OPT",
148 ff00c1a7 Iustin Pop
  "OS_SIZE_OPT",
149 41543d8b René Nussbaumer
  "OOB_TIMEOUT_OPT",
150 0c086a13 René Nussbaumer
  "POWER_DELAY_OPT",
151 b883637f René Nussbaumer
  "PREALLOC_WIPE_DISKS_OPT",
152 e7323b5e Manuel Franceschini
  "PRIMARY_IP_VERSION_OPT",
153 aafee533 Michael Hanselmann
  "PRIMARY_ONLY_OPT",
154 84a5b33c Michael Hanselmann
  "PRIORITY_OPT",
155 6d4a1656 Michael Hanselmann
  "RAPI_CERT_OPT",
156 b8d0f938 Iustin Pop
  "READD_OPT",
157 12054861 Iustin Pop
  "REBOOT_TYPE_OPT",
158 8d8d650c Michael Hanselmann
  "REMOVE_INSTANCE_OPT",
159 fdad8c4d Balazs Lecz
  "REMOVE_UIDS_OPT",
160 f38ea602 Iustin Pop
  "RESERVED_LVS_OPT",
161 31d97b2a Guido Trotter
  "ROMAN_OPT",
162 8d823629 Iustin Pop
  "SECONDARY_IP_OPT",
163 aafee533 Michael Hanselmann
  "SECONDARY_ONLY_OPT",
164 67840b40 Iustin Pop
  "SELECT_OS_OPT",
165 4abc4f1e Iustin Pop
  "SEP_OPT",
166 fdcf4d84 Iustin Pop
  "SHOWCMD_OPT",
167 7e5eaaa8 Guido Trotter
  "SHUTDOWN_TIMEOUT_OPT",
168 f36d7d81 Iustin Pop
  "SINGLE_NODE_OPT",
169 32017174 Agata Murawska
  "SPECS_CPU_COUNT_OPT",
170 32017174 Agata Murawska
  "SPECS_DISK_COUNT_OPT",
171 32017174 Agata Murawska
  "SPECS_DISK_SIZE_OPT",
172 32017174 Agata Murawska
  "SPECS_MEM_SIZE_OPT",
173 32017174 Agata Murawska
  "SPECS_NIC_COUNT_OPT",
174 b6267745 Andrea Spadaccini
  "SPICE_CACERT_OPT",
175 b6267745 Andrea Spadaccini
  "SPICE_CERT_OPT",
176 df62e5db Iustin Pop
  "SRC_DIR_OPT",
177 df62e5db Iustin Pop
  "SRC_NODE_OPT",
178 4abc4f1e Iustin Pop
  "SUBMIT_OPT",
179 323f9095 Stephen Shirley
  "STARTUP_PAUSED_OPT",
180 99a8c799 Iustin Pop
  "STATIC_OPT",
181 4abc4f1e Iustin Pop
  "SYNC_OPT",
182 a57981c5 Apollon Oikonomopoulos
  "TAG_ADD_OPT",
183 4abc4f1e Iustin Pop
  "TAG_SRC_OPT",
184 b5762e2a Guido Trotter
  "TIMEOUT_OPT",
185 f6eb380d Michael Hanselmann
  "TO_GROUP_OPT",
186 1338f2b4 Balazs Lecz
  "UIDPOOL_OPT",
187 4abc4f1e Iustin Pop
  "USEUNITS_OPT",
188 bf689b7a Andrea Spadaccini
  "USE_EXTERNAL_MIP_SCRIPT",
189 74adc100 Iustin Pop
  "USE_REPL_NET_OPT",
190 9cdb9578 Iustin Pop
  "VERBOSE_OPT",
191 b58726e8 Iustin Pop
  "VG_NAME_OPT",
192 1f587d3d Iustin Pop
  "YES_DOIT_OPT",
193 38f29a36 René Nussbaumer
  "DISK_STATE_OPT",
194 38f29a36 René Nussbaumer
  "HV_STATE_OPT",
195 b6aaf437 René Nussbaumer
  "IGNORE_IPOLICY_OPT",
196 4abc4f1e Iustin Pop
  # Generic functions for CLI programs
197 25bd815c René Nussbaumer
  "ConfirmOperation",
198 4abc4f1e Iustin Pop
  "GenericMain",
199 d77490c5 Iustin Pop
  "GenericInstanceCreate",
200 ee3aedff Michael Hanselmann
  "GenericList",
201 ee3aedff Michael Hanselmann
  "GenericListFields",
202 4abc4f1e Iustin Pop
  "GetClient",
203 4abc4f1e Iustin Pop
  "GetOnlineNodes",
204 4abc4f1e Iustin Pop
  "JobExecutor",
205 4abc4f1e Iustin Pop
  "JobSubmittedException",
206 4abc4f1e Iustin Pop
  "ParseTimespec",
207 7e49b6ce Michael Hanselmann
  "RunWhileClusterStopped",
208 4abc4f1e Iustin Pop
  "SubmitOpCode",
209 4abc4f1e Iustin Pop
  "SubmitOrSend",
210 4abc4f1e Iustin Pop
  "UsesRPC",
211 4abc4f1e Iustin Pop
  # Formatting functions
212 4abc4f1e Iustin Pop
  "ToStderr", "ToStdout",
213 4abc4f1e Iustin Pop
  "FormatError",
214 ee3aedff Michael Hanselmann
  "FormatQueryResult",
215 acd19189 René Nussbaumer
  "FormatParameterDict",
216 4abc4f1e Iustin Pop
  "GenerateTable",
217 4abc4f1e Iustin Pop
  "AskUser",
218 4abc4f1e Iustin Pop
  "FormatTimestamp",
219 8a7f1c61 Michael Hanselmann
  "FormatLogMessage",
220 4abc4f1e Iustin Pop
  # Tags functions
221 4abc4f1e Iustin Pop
  "ListTags",
222 4abc4f1e Iustin Pop
  "AddTags",
223 4abc4f1e Iustin Pop
  "RemoveTags",
224 4abc4f1e Iustin Pop
  # command line options support infrastructure
225 4abc4f1e Iustin Pop
  "ARGS_MANY_INSTANCES",
226 4abc4f1e Iustin Pop
  "ARGS_MANY_NODES",
227 667dbd6b Adeodato Simo
  "ARGS_MANY_GROUPS",
228 4abc4f1e Iustin Pop
  "ARGS_NONE",
229 4abc4f1e Iustin Pop
  "ARGS_ONE_INSTANCE",
230 4abc4f1e Iustin Pop
  "ARGS_ONE_NODE",
231 667dbd6b Adeodato Simo
  "ARGS_ONE_GROUP",
232 f9faf9c3 René Nussbaumer
  "ARGS_ONE_OS",
233 4abc4f1e Iustin Pop
  "ArgChoice",
234 4abc4f1e Iustin Pop
  "ArgCommand",
235 4abc4f1e Iustin Pop
  "ArgFile",
236 667dbd6b Adeodato Simo
  "ArgGroup",
237 4abc4f1e Iustin Pop
  "ArgHost",
238 4abc4f1e Iustin Pop
  "ArgInstance",
239 4abc4f1e Iustin Pop
  "ArgJobId",
240 4abc4f1e Iustin Pop
  "ArgNode",
241 f9faf9c3 René Nussbaumer
  "ArgOs",
242 4abc4f1e Iustin Pop
  "ArgSuggest",
243 4abc4f1e Iustin Pop
  "ArgUnknown",
244 4abc4f1e Iustin Pop
  "OPT_COMPL_INST_ADD_NODES",
245 4abc4f1e Iustin Pop
  "OPT_COMPL_MANY_NODES",
246 4abc4f1e Iustin Pop
  "OPT_COMPL_ONE_IALLOCATOR",
247 4abc4f1e Iustin Pop
  "OPT_COMPL_ONE_INSTANCE",
248 4abc4f1e Iustin Pop
  "OPT_COMPL_ONE_NODE",
249 36e247e1 Guido Trotter
  "OPT_COMPL_ONE_NODEGROUP",
250 4abc4f1e Iustin Pop
  "OPT_COMPL_ONE_OS",
251 4abc4f1e Iustin Pop
  "cli_option",
252 4abc4f1e Iustin Pop
  "SplitNodeOption",
253 07150497 Guido Trotter
  "CalculateOSNames",
254 a4ebd726 Michael Hanselmann
  "ParseFields",
255 eb28ecf6 Guido Trotter
  "COMMON_CREATE_OPTS",
256 4abc4f1e Iustin Pop
  ]
257 846baef9 Iustin Pop
258 8b46606c Guido Trotter
NO_PREFIX = "no_"
259 8b46606c Guido Trotter
UN_PREFIX = "-"
260 846baef9 Iustin Pop
261 84a5b33c Michael Hanselmann
#: Priorities (sorted)
262 84a5b33c Michael Hanselmann
_PRIORITY_NAMES = [
263 84a5b33c Michael Hanselmann
  ("low", constants.OP_PRIO_LOW),
264 84a5b33c Michael Hanselmann
  ("normal", constants.OP_PRIO_NORMAL),
265 84a5b33c Michael Hanselmann
  ("high", constants.OP_PRIO_HIGH),
266 84a5b33c Michael Hanselmann
  ]
267 84a5b33c Michael Hanselmann
268 84a5b33c Michael Hanselmann
#: Priority dictionary for easier lookup
269 84a5b33c Michael Hanselmann
# TODO: Replace this and _PRIORITY_NAMES with a single sorted dictionary once
270 84a5b33c Michael Hanselmann
# we migrate to Python 2.6
271 84a5b33c Michael Hanselmann
_PRIONAME_TO_VALUE = dict(_PRIORITY_NAMES)
272 84a5b33c Michael Hanselmann
273 ee3aedff Michael Hanselmann
# Query result status for clients
274 ee3aedff Michael Hanselmann
(QR_NORMAL,
275 ee3aedff Michael Hanselmann
 QR_UNKNOWN,
276 ee3aedff Michael Hanselmann
 QR_INCOMPLETE) = range(3)
277 ee3aedff Michael Hanselmann
278 11705e3d Iustin Pop
#: Maximum batch size for ChooseJob
279 11705e3d Iustin Pop
_CHOOSE_BATCH = 25
280 11705e3d Iustin Pop
281 03298ebe Michael Hanselmann
282 863d7f46 Michael Hanselmann
class _Argument:
283 b459a848 Andrea Spadaccini
  def __init__(self, min=0, max=None): # pylint: disable=W0622
284 863d7f46 Michael Hanselmann
    self.min = min
285 863d7f46 Michael Hanselmann
    self.max = max
286 863d7f46 Michael Hanselmann
287 863d7f46 Michael Hanselmann
  def __repr__(self):
288 863d7f46 Michael Hanselmann
    return ("<%s min=%s max=%s>" %
289 863d7f46 Michael Hanselmann
            (self.__class__.__name__, self.min, self.max))
290 863d7f46 Michael Hanselmann
291 863d7f46 Michael Hanselmann
292 863d7f46 Michael Hanselmann
class ArgSuggest(_Argument):
293 863d7f46 Michael Hanselmann
  """Suggesting argument.
294 863d7f46 Michael Hanselmann

295 863d7f46 Michael Hanselmann
  Value can be any of the ones passed to the constructor.
296 863d7f46 Michael Hanselmann

297 863d7f46 Michael Hanselmann
  """
298 b459a848 Andrea Spadaccini
  # pylint: disable=W0622
299 863d7f46 Michael Hanselmann
  def __init__(self, min=0, max=None, choices=None):
300 863d7f46 Michael Hanselmann
    _Argument.__init__(self, min=min, max=max)
301 863d7f46 Michael Hanselmann
    self.choices = choices
302 863d7f46 Michael Hanselmann
303 863d7f46 Michael Hanselmann
  def __repr__(self):
304 863d7f46 Michael Hanselmann
    return ("<%s min=%s max=%s choices=%r>" %
305 863d7f46 Michael Hanselmann
            (self.__class__.__name__, self.min, self.max, self.choices))
306 863d7f46 Michael Hanselmann
307 863d7f46 Michael Hanselmann
308 863d7f46 Michael Hanselmann
class ArgChoice(ArgSuggest):
309 863d7f46 Michael Hanselmann
  """Choice argument.
310 863d7f46 Michael Hanselmann

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

314 863d7f46 Michael Hanselmann
  """
315 863d7f46 Michael Hanselmann
316 863d7f46 Michael Hanselmann
317 863d7f46 Michael Hanselmann
class ArgUnknown(_Argument):
318 863d7f46 Michael Hanselmann
  """Unknown argument to program (e.g. determined at runtime).
319 863d7f46 Michael Hanselmann

320 863d7f46 Michael Hanselmann
  """
321 863d7f46 Michael Hanselmann
322 863d7f46 Michael Hanselmann
323 863d7f46 Michael Hanselmann
class ArgInstance(_Argument):
324 863d7f46 Michael Hanselmann
  """Instances argument.
325 863d7f46 Michael Hanselmann

326 863d7f46 Michael Hanselmann
  """
327 863d7f46 Michael Hanselmann
328 863d7f46 Michael Hanselmann
329 863d7f46 Michael Hanselmann
class ArgNode(_Argument):
330 863d7f46 Michael Hanselmann
  """Node argument.
331 863d7f46 Michael Hanselmann

332 863d7f46 Michael Hanselmann
  """
333 863d7f46 Michael Hanselmann
334 667dbd6b Adeodato Simo
335 667dbd6b Adeodato Simo
class ArgGroup(_Argument):
336 667dbd6b Adeodato Simo
  """Node group argument.
337 667dbd6b Adeodato Simo

338 667dbd6b Adeodato Simo
  """
339 667dbd6b Adeodato Simo
340 667dbd6b Adeodato Simo
341 863d7f46 Michael Hanselmann
class ArgJobId(_Argument):
342 863d7f46 Michael Hanselmann
  """Job ID argument.
343 863d7f46 Michael Hanselmann

344 863d7f46 Michael Hanselmann
  """
345 863d7f46 Michael Hanselmann
346 863d7f46 Michael Hanselmann
347 863d7f46 Michael Hanselmann
class ArgFile(_Argument):
348 863d7f46 Michael Hanselmann
  """File path argument.
349 863d7f46 Michael Hanselmann

350 863d7f46 Michael Hanselmann
  """
351 863d7f46 Michael Hanselmann
352 863d7f46 Michael Hanselmann
353 863d7f46 Michael Hanselmann
class ArgCommand(_Argument):
354 863d7f46 Michael Hanselmann
  """Command argument.
355 863d7f46 Michael Hanselmann

356 863d7f46 Michael Hanselmann
  """
357 863d7f46 Michael Hanselmann
358 863d7f46 Michael Hanselmann
359 83ec7961 Michael Hanselmann
class ArgHost(_Argument):
360 83ec7961 Michael Hanselmann
  """Host argument.
361 83ec7961 Michael Hanselmann

362 83ec7961 Michael Hanselmann
  """
363 83ec7961 Michael Hanselmann
364 83ec7961 Michael Hanselmann
365 f9faf9c3 René Nussbaumer
class ArgOs(_Argument):
366 f9faf9c3 René Nussbaumer
  """OS argument.
367 f9faf9c3 René Nussbaumer

368 f9faf9c3 René Nussbaumer
  """
369 f9faf9c3 René Nussbaumer
370 f9faf9c3 René Nussbaumer
371 4a265c08 Michael Hanselmann
ARGS_NONE = []
372 4a265c08 Michael Hanselmann
ARGS_MANY_INSTANCES = [ArgInstance()]
373 4a265c08 Michael Hanselmann
ARGS_MANY_NODES = [ArgNode()]
374 667dbd6b Adeodato Simo
ARGS_MANY_GROUPS = [ArgGroup()]
375 4a265c08 Michael Hanselmann
ARGS_ONE_INSTANCE = [ArgInstance(min=1, max=1)]
376 4a265c08 Michael Hanselmann
ARGS_ONE_NODE = [ArgNode(min=1, max=1)]
377 dadf6b7d Michael Hanselmann
# TODO
378 dadf6b7d Michael Hanselmann
ARGS_ONE_GROUP = [ArgGroup(min=1, max=1)]
379 f9faf9c3 René Nussbaumer
ARGS_ONE_OS = [ArgOs(min=1, max=1)]
380 4a265c08 Michael Hanselmann
381 4a265c08 Michael Hanselmann
382 846baef9 Iustin Pop
def _ExtractTagsObject(opts, args):
383 846baef9 Iustin Pop
  """Extract the tag type object.
384 846baef9 Iustin Pop

385 846baef9 Iustin Pop
  Note that this function will modify its args parameter.
386 846baef9 Iustin Pop

387 846baef9 Iustin Pop
  """
388 846baef9 Iustin Pop
  if not hasattr(opts, "tag_type"):
389 846baef9 Iustin Pop
    raise errors.ProgrammerError("tag_type not passed to _ExtractTagsObject")
390 846baef9 Iustin Pop
  kind = opts.tag_type
391 846baef9 Iustin Pop
  if kind == constants.TAG_CLUSTER:
392 846baef9 Iustin Pop
    retval = kind, kind
393 819cbfe5 Michael Hanselmann
  elif kind in (constants.TAG_NODEGROUP,
394 819cbfe5 Michael Hanselmann
                constants.TAG_NODE,
395 819cbfe5 Michael Hanselmann
                constants.TAG_INSTANCE):
396 846baef9 Iustin Pop
    if not args:
397 0c434948 Iustin Pop
      raise errors.OpPrereqError("no arguments passed to the command")
398 846baef9 Iustin Pop
    name = args.pop(0)
399 846baef9 Iustin Pop
    retval = kind, name
400 846baef9 Iustin Pop
  else:
401 846baef9 Iustin Pop
    raise errors.ProgrammerError("Unhandled tag type '%s'" % kind)
402 846baef9 Iustin Pop
  return retval
403 846baef9 Iustin Pop
404 846baef9 Iustin Pop
405 810c50b7 Iustin Pop
def _ExtendTags(opts, args):
406 810c50b7 Iustin Pop
  """Extend the args if a source file has been given.
407 810c50b7 Iustin Pop

408 810c50b7 Iustin Pop
  This function will extend the tags with the contents of the file
409 810c50b7 Iustin Pop
  passed in the 'tags_source' attribute of the opts parameter. A file
410 810c50b7 Iustin Pop
  named '-' will be replaced by stdin.
411 810c50b7 Iustin Pop

412 810c50b7 Iustin Pop
  """
413 810c50b7 Iustin Pop
  fname = opts.tags_source
414 810c50b7 Iustin Pop
  if fname is None:
415 810c50b7 Iustin Pop
    return
416 810c50b7 Iustin Pop
  if fname == "-":
417 810c50b7 Iustin Pop
    new_fh = sys.stdin
418 810c50b7 Iustin Pop
  else:
419 810c50b7 Iustin Pop
    new_fh = open(fname, "r")
420 810c50b7 Iustin Pop
  new_data = []
421 810c50b7 Iustin Pop
  try:
422 810c50b7 Iustin Pop
    # we don't use the nice 'new_data = [line.strip() for line in fh]'
423 810c50b7 Iustin Pop
    # because of python bug 1633941
424 810c50b7 Iustin Pop
    while True:
425 810c50b7 Iustin Pop
      line = new_fh.readline()
426 810c50b7 Iustin Pop
      if not line:
427 810c50b7 Iustin Pop
        break
428 810c50b7 Iustin Pop
      new_data.append(line.strip())
429 810c50b7 Iustin Pop
  finally:
430 810c50b7 Iustin Pop
    new_fh.close()
431 810c50b7 Iustin Pop
  args.extend(new_data)
432 810c50b7 Iustin Pop
433 810c50b7 Iustin Pop
434 846baef9 Iustin Pop
def ListTags(opts, args):
435 846baef9 Iustin Pop
  """List the tags on a given object.
436 846baef9 Iustin Pop

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

442 846baef9 Iustin Pop
  """
443 846baef9 Iustin Pop
  kind, name = _ExtractTagsObject(opts, args)
444 7699c3af Iustin Pop
  cl = GetClient()
445 7699c3af Iustin Pop
  result = cl.QueryTags(kind, name)
446 846baef9 Iustin Pop
  result = list(result)
447 846baef9 Iustin Pop
  result.sort()
448 846baef9 Iustin Pop
  for tag in result:
449 03298ebe Michael Hanselmann
    ToStdout(tag)
450 846baef9 Iustin Pop
451 846baef9 Iustin Pop
452 846baef9 Iustin Pop
def AddTags(opts, args):
453 846baef9 Iustin Pop
  """Add tags on a given object.
454 846baef9 Iustin Pop

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

460 846baef9 Iustin Pop
  """
461 846baef9 Iustin Pop
  kind, name = _ExtractTagsObject(opts, args)
462 810c50b7 Iustin Pop
  _ExtendTags(opts, args)
463 846baef9 Iustin Pop
  if not args:
464 846baef9 Iustin Pop
    raise errors.OpPrereqError("No tags to be added")
465 d1602edc Iustin Pop
  op = opcodes.OpTagsSet(kind=kind, name=name, tags=args)
466 af1a81d1 Michael Hanselmann
  SubmitOpCode(op, opts=opts)
467 846baef9 Iustin Pop
468 846baef9 Iustin Pop
469 846baef9 Iustin Pop
def RemoveTags(opts, args):
470 846baef9 Iustin Pop
  """Remove tags from a given object.
471 846baef9 Iustin Pop

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

477 846baef9 Iustin Pop
  """
478 846baef9 Iustin Pop
  kind, name = _ExtractTagsObject(opts, args)
479 810c50b7 Iustin Pop
  _ExtendTags(opts, args)
480 846baef9 Iustin Pop
  if not args:
481 846baef9 Iustin Pop
    raise errors.OpPrereqError("No tags to be removed")
482 3f0ab95f Iustin Pop
  op = opcodes.OpTagsDel(kind=kind, name=name, tags=args)
483 af1a81d1 Michael Hanselmann
  SubmitOpCode(op, opts=opts)
484 846baef9 Iustin Pop
485 a8083063 Iustin Pop
486 b459a848 Andrea Spadaccini
def check_unit(option, opt, value): # pylint: disable=W0613
487 65fe4693 Iustin Pop
  """OptParsers custom converter for units.
488 65fe4693 Iustin Pop

489 65fe4693 Iustin Pop
  """
490 a8083063 Iustin Pop
  try:
491 a8083063 Iustin Pop
    return utils.ParseUnit(value)
492 a8083063 Iustin Pop
  except errors.UnitParseError, err:
493 3ecf6786 Iustin Pop
    raise OptionValueError("option %s: %s" % (opt, err))
494 a8083063 Iustin Pop
495 a8083063 Iustin Pop
496 a8469393 Iustin Pop
def _SplitKeyVal(opt, data):
497 a8469393 Iustin Pop
  """Convert a KeyVal string into a dict.
498 a8469393 Iustin Pop

499 a8469393 Iustin Pop
  This function will convert a key=val[,...] string into a dict. Empty
500 a8469393 Iustin Pop
  values will be converted specially: keys which have the prefix 'no_'
501 a8469393 Iustin Pop
  will have the value=False and the prefix stripped, the others will
502 a8469393 Iustin Pop
  have value=True.
503 a8469393 Iustin Pop

504 a8469393 Iustin Pop
  @type opt: string
505 a8469393 Iustin Pop
  @param opt: a string holding the option name for which we process the
506 a8469393 Iustin Pop
      data, used in building error messages
507 a8469393 Iustin Pop
  @type data: string
508 a8469393 Iustin Pop
  @param data: a string of the format key=val,key=val,...
509 a8469393 Iustin Pop
  @rtype: dict
510 a8469393 Iustin Pop
  @return: {key=val, key=val}
511 a8469393 Iustin Pop
  @raises errors.ParameterError: if there are duplicate keys
512 a8469393 Iustin Pop

513 a8469393 Iustin Pop
  """
514 a8469393 Iustin Pop
  kv_dict = {}
515 4f31882e Guido Trotter
  if data:
516 1b3a7656 Iustin Pop
    for elem in utils.UnescapeAndSplit(data, sep=","):
517 4f31882e Guido Trotter
      if "=" in elem:
518 4f31882e Guido Trotter
        key, val = elem.split("=", 1)
519 a8469393 Iustin Pop
      else:
520 4f31882e Guido Trotter
        if elem.startswith(NO_PREFIX):
521 4f31882e Guido Trotter
          key, val = elem[len(NO_PREFIX):], False
522 4f31882e Guido Trotter
        elif elem.startswith(UN_PREFIX):
523 4f31882e Guido Trotter
          key, val = elem[len(UN_PREFIX):], None
524 4f31882e Guido Trotter
        else:
525 4f31882e Guido Trotter
          key, val = elem, True
526 4f31882e Guido Trotter
      if key in kv_dict:
527 4f31882e Guido Trotter
        raise errors.ParameterError("Duplicate key '%s' in option %s" %
528 4f31882e Guido Trotter
                                    (key, opt))
529 4f31882e Guido Trotter
      kv_dict[key] = val
530 a8469393 Iustin Pop
  return kv_dict
531 a8469393 Iustin Pop
532 a8469393 Iustin Pop
533 b459a848 Andrea Spadaccini
def check_ident_key_val(option, opt, value):  # pylint: disable=W0613
534 552c8dff Michael Hanselmann
  """Custom parser for ident:key=val,key=val options.
535 552c8dff Michael Hanselmann

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

539 a8469393 Iustin Pop
  """
540 a8469393 Iustin Pop
  if ":" not in value:
541 d0c8c01d Iustin Pop
    ident, rest = value, ""
542 a8469393 Iustin Pop
  else:
543 a8469393 Iustin Pop
    ident, rest = value.split(":", 1)
544 8b46606c Guido Trotter
545 8b46606c Guido Trotter
  if ident.startswith(NO_PREFIX):
546 8b46606c Guido Trotter
    if rest:
547 8b46606c Guido Trotter
      msg = "Cannot pass options when removing parameter groups: %s" % value
548 8b46606c Guido Trotter
      raise errors.ParameterError(msg)
549 8b46606c Guido Trotter
    retval = (ident[len(NO_PREFIX):], False)
550 8b46606c Guido Trotter
  elif ident.startswith(UN_PREFIX):
551 8b46606c Guido Trotter
    if rest:
552 8b46606c Guido Trotter
      msg = "Cannot pass options when removing parameter groups: %s" % value
553 8b46606c Guido Trotter
      raise errors.ParameterError(msg)
554 8b46606c Guido Trotter
    retval = (ident[len(UN_PREFIX):], None)
555 8b46606c Guido Trotter
  else:
556 a8469393 Iustin Pop
    kv_dict = _SplitKeyVal(opt, rest)
557 a8469393 Iustin Pop
    retval = (ident, kv_dict)
558 a8469393 Iustin Pop
  return retval
559 a8469393 Iustin Pop
560 a8469393 Iustin Pop
561 b459a848 Andrea Spadaccini
def check_key_val(option, opt, value):  # pylint: disable=W0613
562 552c8dff Michael Hanselmann
  """Custom parser class for key=val,key=val options.
563 552c8dff Michael Hanselmann

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

566 a8469393 Iustin Pop
  """
567 a8469393 Iustin Pop
  return _SplitKeyVal(opt, value)
568 a8469393 Iustin Pop
569 a8469393 Iustin Pop
570 b459a848 Andrea Spadaccini
def check_bool(option, opt, value): # pylint: disable=W0613
571 e7b61bb0 Iustin Pop
  """Custom parser for yes/no options.
572 e7b61bb0 Iustin Pop

573 e7b61bb0 Iustin Pop
  This will store the parsed value as either True or False.
574 e7b61bb0 Iustin Pop

575 e7b61bb0 Iustin Pop
  """
576 e7b61bb0 Iustin Pop
  value = value.lower()
577 e7b61bb0 Iustin Pop
  if value == constants.VALUE_FALSE or value == "no":
578 e7b61bb0 Iustin Pop
    return False
579 e7b61bb0 Iustin Pop
  elif value == constants.VALUE_TRUE or value == "yes":
580 e7b61bb0 Iustin Pop
    return True
581 e7b61bb0 Iustin Pop
  else:
582 e7b61bb0 Iustin Pop
    raise errors.ParameterError("Invalid boolean value '%s'" % value)
583 e7b61bb0 Iustin Pop
584 e7b61bb0 Iustin Pop
585 499eb088 Iustin Pop
def check_list(option, opt, value): # pylint: disable=W0613
586 499eb088 Iustin Pop
  """Custom parser for comma-separated lists.
587 499eb088 Iustin Pop

588 499eb088 Iustin Pop
  """
589 499eb088 Iustin Pop
  # we have to make this explicit check since "".split(",") is [""],
590 499eb088 Iustin Pop
  # not an empty list :(
591 499eb088 Iustin Pop
  if not value:
592 499eb088 Iustin Pop
    return []
593 499eb088 Iustin Pop
  else:
594 499eb088 Iustin Pop
    return utils.UnescapeAndSplit(value)
595 499eb088 Iustin Pop
596 499eb088 Iustin Pop
597 63d44c55 Michael Hanselmann
# completion_suggestion is normally a list. Using numeric values not evaluating
598 63d44c55 Michael Hanselmann
# to False for dynamic completion.
599 63d44c55 Michael Hanselmann
(OPT_COMPL_MANY_NODES,
600 63d44c55 Michael Hanselmann
 OPT_COMPL_ONE_NODE,
601 63d44c55 Michael Hanselmann
 OPT_COMPL_ONE_INSTANCE,
602 63d44c55 Michael Hanselmann
 OPT_COMPL_ONE_OS,
603 2d3ed64b Michael Hanselmann
 OPT_COMPL_ONE_IALLOCATOR,
604 36e247e1 Guido Trotter
 OPT_COMPL_INST_ADD_NODES,
605 36e247e1 Guido Trotter
 OPT_COMPL_ONE_NODEGROUP) = range(100, 107)
606 63d44c55 Michael Hanselmann
607 63d44c55 Michael Hanselmann
OPT_COMPL_ALL = frozenset([
608 63d44c55 Michael Hanselmann
  OPT_COMPL_MANY_NODES,
609 63d44c55 Michael Hanselmann
  OPT_COMPL_ONE_NODE,
610 63d44c55 Michael Hanselmann
  OPT_COMPL_ONE_INSTANCE,
611 63d44c55 Michael Hanselmann
  OPT_COMPL_ONE_OS,
612 63d44c55 Michael Hanselmann
  OPT_COMPL_ONE_IALLOCATOR,
613 2d3ed64b Michael Hanselmann
  OPT_COMPL_INST_ADD_NODES,
614 36e247e1 Guido Trotter
  OPT_COMPL_ONE_NODEGROUP,
615 63d44c55 Michael Hanselmann
  ])
616 63d44c55 Michael Hanselmann
617 63d44c55 Michael Hanselmann
618 552c8dff Michael Hanselmann
class CliOption(Option):
619 552c8dff Michael Hanselmann
  """Custom option class for optparse.
620 a8469393 Iustin Pop

621 a8469393 Iustin Pop
  """
622 863d7f46 Michael Hanselmann
  ATTRS = Option.ATTRS + [
623 863d7f46 Michael Hanselmann
    "completion_suggest",
624 863d7f46 Michael Hanselmann
    ]
625 552c8dff Michael Hanselmann
  TYPES = Option.TYPES + (
626 552c8dff Michael Hanselmann
    "identkeyval",
627 552c8dff Michael Hanselmann
    "keyval",
628 552c8dff Michael Hanselmann
    "unit",
629 e7b61bb0 Iustin Pop
    "bool",
630 499eb088 Iustin Pop
    "list",
631 552c8dff Michael Hanselmann
    )
632 552c8dff Michael Hanselmann
  TYPE_CHECKER = Option.TYPE_CHECKER.copy()
633 552c8dff Michael Hanselmann
  TYPE_CHECKER["identkeyval"] = check_ident_key_val
634 a8469393 Iustin Pop
  TYPE_CHECKER["keyval"] = check_key_val
635 552c8dff Michael Hanselmann
  TYPE_CHECKER["unit"] = check_unit
636 e7b61bb0 Iustin Pop
  TYPE_CHECKER["bool"] = check_bool
637 499eb088 Iustin Pop
  TYPE_CHECKER["list"] = check_list
638 a8469393 Iustin Pop
639 a8469393 Iustin Pop
640 a8083063 Iustin Pop
# optparse.py sets make_option, so we do it for our own option class, too
641 a8083063 Iustin Pop
cli_option = CliOption
642 a8083063 Iustin Pop
643 a8083063 Iustin Pop
644 771734c9 Iustin Pop
_YORNO = "yes|no"
645 771734c9 Iustin Pop
646 ea34193f Iustin Pop
DEBUG_OPT = cli_option("-d", "--debug", default=0, action="count",
647 ea34193f Iustin Pop
                       help="Increase debugging level")
648 c38c44ad Michael Hanselmann
649 c38c44ad Michael Hanselmann
NOHDR_OPT = cli_option("--no-headers", default=False,
650 c38c44ad Michael Hanselmann
                       action="store_true", dest="no_headers",
651 c38c44ad Michael Hanselmann
                       help="Don't display column headers")
652 c38c44ad Michael Hanselmann
653 c38c44ad Michael Hanselmann
SEP_OPT = cli_option("--separator", default=None,
654 c38c44ad Michael Hanselmann
                     action="store", dest="separator",
655 c38c44ad Michael Hanselmann
                     help=("Separator between output fields"
656 c38c44ad Michael Hanselmann
                           " (defaults to one space)"))
657 c38c44ad Michael Hanselmann
658 c38c44ad Michael Hanselmann
USEUNITS_OPT = cli_option("--units", default=None,
659 d0c8c01d Iustin Pop
                          dest="units", choices=("h", "m", "g", "t"),
660 b714765a Adeodato Simo
                          help="Specify units for output (one of h/m/g/t)")
661 c38c44ad Michael Hanselmann
662 c38c44ad Michael Hanselmann
FIELDS_OPT = cli_option("-o", "--output", dest="output", action="store",
663 c38c44ad Michael Hanselmann
                        type="string", metavar="FIELDS",
664 c38c44ad Michael Hanselmann
                        help="Comma separated list of output fields")
665 c38c44ad Michael Hanselmann
666 c38c44ad Michael Hanselmann
FORCE_OPT = cli_option("-f", "--force", dest="force", action="store_true",
667 c38c44ad Michael Hanselmann
                       default=False, help="Force the operation")
668 c38c44ad Michael Hanselmann
669 c38c44ad Michael Hanselmann
CONFIRM_OPT = cli_option("--yes", dest="confirm", action="store_true",
670 c38c44ad Michael Hanselmann
                         default=False, help="Do not require confirmation")
671 c38c44ad Michael Hanselmann
672 b44bd844 Michael Hanselmann
IGNORE_OFFLINE_OPT = cli_option("--ignore-offline", dest="ignore_offline",
673 b44bd844 Michael Hanselmann
                                  action="store_true", default=False,
674 b44bd844 Michael Hanselmann
                                  help=("Ignore offline nodes and do as much"
675 b44bd844 Michael Hanselmann
                                        " as possible"))
676 b44bd844 Michael Hanselmann
677 a57981c5 Apollon Oikonomopoulos
TAG_ADD_OPT = cli_option("--tags", dest="tags",
678 a57981c5 Apollon Oikonomopoulos
                         default=None, help="Comma-separated list of instance"
679 a57981c5 Apollon Oikonomopoulos
                                            " tags")
680 a57981c5 Apollon Oikonomopoulos
681 c38c44ad Michael Hanselmann
TAG_SRC_OPT = cli_option("--from", dest="tags_source",
682 c38c44ad Michael Hanselmann
                         default=None, help="File with tag names")
683 c38c44ad Michael Hanselmann
684 c38c44ad Michael Hanselmann
SUBMIT_OPT = cli_option("--submit", dest="submit_only",
685 c38c44ad Michael Hanselmann
                        default=False, action="store_true",
686 c38c44ad Michael Hanselmann
                        help=("Submit the job and return the job ID, but"
687 c38c44ad Michael Hanselmann
                              " don't wait for the job to finish"))
688 c38c44ad Michael Hanselmann
689 c38c44ad Michael Hanselmann
SYNC_OPT = cli_option("--sync", dest="do_locking",
690 c38c44ad Michael Hanselmann
                      default=False, action="store_true",
691 c38c44ad Michael Hanselmann
                      help=("Grab locks while doing the queries"
692 c38c44ad Michael Hanselmann
                            " in order to ensure more consistent results"))
693 c38c44ad Michael Hanselmann
694 a0a6ff34 Iustin Pop
DRY_RUN_OPT = cli_option("--dry-run", default=False,
695 a0a6ff34 Iustin Pop
                         action="store_true",
696 a0a6ff34 Iustin Pop
                         help=("Do not execute the operation, just run the"
697 a0a6ff34 Iustin Pop
                               " check steps and verify it it could be"
698 a0a6ff34 Iustin Pop
                               " executed"))
699 c38c44ad Michael Hanselmann
700 9cdb9578 Iustin Pop
VERBOSE_OPT = cli_option("-v", "--verbose", default=False,
701 9cdb9578 Iustin Pop
                         action="store_true",
702 9cdb9578 Iustin Pop
                         help="Increase the verbosity of the operation")
703 9cdb9578 Iustin Pop
704 a0c9776a Iustin Pop
DEBUG_SIMERR_OPT = cli_option("--debug-simulate-errors", default=False,
705 a0c9776a Iustin Pop
                              action="store_true", dest="simulate_errors",
706 a0c9776a Iustin Pop
                              help="Debugging option that makes the operation"
707 a0c9776a Iustin Pop
                              " treat most runtime checks as failed")
708 a0c9776a Iustin Pop
709 3f75b4f3 Iustin Pop
NWSYNC_OPT = cli_option("--no-wait-for-sync", dest="wait_for_sync",
710 3f75b4f3 Iustin Pop
                        default=True, action="store_false",
711 3f75b4f3 Iustin Pop
                        help="Don't wait for sync (DANGEROUS!)")
712 3f75b4f3 Iustin Pop
713 57de31c0 Agata Murawska
ONLINE_INST_OPT = cli_option("--online", dest="online_inst",
714 57de31c0 Agata Murawska
                             action="store_true", default=False,
715 57de31c0 Agata Murawska
                             help="Enable offline instance")
716 57de31c0 Agata Murawska
717 57de31c0 Agata Murawska
OFFLINE_INST_OPT = cli_option("--offline", dest="offline_inst",
718 57de31c0 Agata Murawska
                              action="store_true", default=False,
719 57de31c0 Agata Murawska
                              help="Disable down instance")
720 57de31c0 Agata Murawska
721 4f365444 Iustin Pop
DISK_TEMPLATE_OPT = cli_option("-t", "--disk-template", dest="disk_template",
722 235407ba Michael Hanselmann
                               help=("Custom disk setup (%s)" %
723 235407ba Michael Hanselmann
                                     utils.CommaJoin(constants.DISK_TEMPLATES)),
724 4f365444 Iustin Pop
                               default=None, metavar="TEMPL",
725 4f365444 Iustin Pop
                               choices=list(constants.DISK_TEMPLATES))
726 4f365444 Iustin Pop
727 26023ecd Iustin Pop
NONICS_OPT = cli_option("--no-nics", default=False, action="store_true",
728 26023ecd Iustin Pop
                        help="Do not create any network cards for"
729 26023ecd Iustin Pop
                        " the instance")
730 26023ecd Iustin Pop
731 4a25828c Iustin Pop
FILESTORE_DIR_OPT = cli_option("--file-storage-dir", dest="file_storage_dir",
732 4a25828c Iustin Pop
                               help="Relative path under default cluster-wide"
733 4a25828c Iustin Pop
                               " file storage dir to store file-based disks",
734 4a25828c Iustin Pop
                               default=None, metavar="<DIR>")
735 4a25828c Iustin Pop
736 0f87c43e Iustin Pop
FILESTORE_DRIVER_OPT = cli_option("--file-driver", dest="file_driver",
737 0f87c43e Iustin Pop
                                  help="Driver to use for image files",
738 0f87c43e Iustin Pop
                                  default="loop", metavar="<DRIVER>",
739 0f87c43e Iustin Pop
                                  choices=list(constants.FILE_DRIVER))
740 0f87c43e Iustin Pop
741 4eb62659 Iustin Pop
IALLOCATOR_OPT = cli_option("-I", "--iallocator", metavar="<NAME>",
742 4eb62659 Iustin Pop
                            help="Select nodes for the instance automatically"
743 4eb62659 Iustin Pop
                            " using the <NAME> iallocator plugin",
744 4eb62659 Iustin Pop
                            default=None, type="string",
745 4eb62659 Iustin Pop
                            completion_suggest=OPT_COMPL_ONE_IALLOCATOR)
746 4eb62659 Iustin Pop
747 bf4af505 Apollon Oikonomopoulos
DEFAULT_IALLOCATOR_OPT = cli_option("-I", "--default-iallocator",
748 bf4af505 Apollon Oikonomopoulos
                            metavar="<NAME>",
749 bf4af505 Apollon Oikonomopoulos
                            help="Set the default instance allocator plugin",
750 bf4af505 Apollon Oikonomopoulos
                            default=None, type="string",
751 bf4af505 Apollon Oikonomopoulos
                            completion_suggest=OPT_COMPL_ONE_IALLOCATOR)
752 bf4af505 Apollon Oikonomopoulos
753 d3ed23ff Iustin Pop
OS_OPT = cli_option("-o", "--os-type", dest="os", help="What OS to run",
754 d3ed23ff Iustin Pop
                    metavar="<os>",
755 d3ed23ff Iustin Pop
                    completion_suggest=OPT_COMPL_ONE_OS)
756 d3ed23ff Iustin Pop
757 062a7100 Iustin Pop
OSPARAMS_OPT = cli_option("-O", "--os-parameters", dest="osparams",
758 062a7100 Iustin Pop
                         type="keyval", default={},
759 062a7100 Iustin Pop
                         help="OS parameters")
760 062a7100 Iustin Pop
761 06073e85 Guido Trotter
FORCE_VARIANT_OPT = cli_option("--force-variant", dest="force_variant",
762 06073e85 Guido Trotter
                               action="store_true", default=False,
763 06073e85 Guido Trotter
                               help="Force an unknown variant")
764 06073e85 Guido Trotter
765 25a8792c Iustin Pop
NO_INSTALL_OPT = cli_option("--no-install", dest="no_install",
766 25a8792c Iustin Pop
                            action="store_true", default=False,
767 25a8792c Iustin Pop
                            help="Do not install the OS (will"
768 25a8792c Iustin Pop
                            " enable no-start)")
769 25a8792c Iustin Pop
770 087ed2ed Iustin Pop
BACKEND_OPT = cli_option("-B", "--backend-parameters", dest="beparams",
771 087ed2ed Iustin Pop
                         type="keyval", default={},
772 087ed2ed Iustin Pop
                         help="Backend parameters")
773 48f212d7 Iustin Pop
774 e687ec01 Michael Hanselmann
HVOPTS_OPT = cli_option("-H", "--hypervisor-parameters", type="keyval",
775 e687ec01 Michael Hanselmann
                        default={}, dest="hvparams",
776 e687ec01 Michael Hanselmann
                        help="Hypervisor parameters")
777 087ed2ed Iustin Pop
778 bc5d0215 Andrea Spadaccini
DISK_PARAMS_OPT = cli_option("-D", "--disk-parameters", dest="diskparams",
779 bc5d0215 Andrea Spadaccini
                             help="Disk template parameters, in the format"
780 bc5d0215 Andrea Spadaccini
                             " template:option=value,option=value,...",
781 bc5d0215 Andrea Spadaccini
                             type="identkeyval", action="append", default=[])
782 bc5d0215 Andrea Spadaccini
783 32017174 Agata Murawska
SPECS_MEM_SIZE_OPT = cli_option("--specs-mem-size", dest="ispecs_mem_size",
784 32017174 Agata Murawska
                                 type="keyval", default={},
785 32017174 Agata Murawska
                                 help="Memory count specs: min, max, std"
786 32017174 Agata Murawska
                                 " (in MB)")
787 32017174 Agata Murawska
788 32017174 Agata Murawska
SPECS_CPU_COUNT_OPT = cli_option("--specs-cpu-count", dest="ispecs_cpu_count",
789 32017174 Agata Murawska
                                 type="keyval", default={},
790 32017174 Agata Murawska
                                 help="CPU count specs: min, max, std")
791 32017174 Agata Murawska
792 32017174 Agata Murawska
SPECS_DISK_COUNT_OPT = cli_option("--specs-disk-count",
793 32017174 Agata Murawska
                                  dest="ispecs_disk_count",
794 32017174 Agata Murawska
                                  type="keyval", default={},
795 32017174 Agata Murawska
                                  help="Disk count specs: min, max, std")
796 32017174 Agata Murawska
797 32017174 Agata Murawska
SPECS_DISK_SIZE_OPT = cli_option("--specs-disk-size", dest="ispecs_disk_size",
798 32017174 Agata Murawska
                                 type="keyval", default={},
799 32017174 Agata Murawska
                                 help="Disk size specs: min, max, std (in MB)")
800 32017174 Agata Murawska
801 32017174 Agata Murawska
SPECS_NIC_COUNT_OPT = cli_option("--specs-nic-count", dest="ispecs_nic_count",
802 32017174 Agata Murawska
                                 type="keyval", default={},
803 32017174 Agata Murawska
                                 help="NIC count specs: min, max, std")
804 32017174 Agata Murawska
805 236fd9c4 Iustin Pop
HYPERVISOR_OPT = cli_option("-H", "--hypervisor-parameters", dest="hypervisor",
806 236fd9c4 Iustin Pop
                            help="Hypervisor and hypervisor options, in the"
807 236fd9c4 Iustin Pop
                            " format hypervisor:option=value,option=value,...",
808 236fd9c4 Iustin Pop
                            default=None, type="identkeyval")
809 073271f6 Iustin Pop
810 073271f6 Iustin Pop
HVLIST_OPT = cli_option("-H", "--hypervisor-parameters", dest="hvparams",
811 073271f6 Iustin Pop
                        help="Hypervisor and hypervisor options, in the"
812 073271f6 Iustin Pop
                        " format hypervisor:option=value,option=value,...",
813 073271f6 Iustin Pop
                        default=[], action="append", type="identkeyval")
814 236fd9c4 Iustin Pop
815 91e0748c Iustin Pop
NOIPCHECK_OPT = cli_option("--no-ip-check", dest="ip_check", default=True,
816 91e0748c Iustin Pop
                           action="store_false",
817 91e0748c Iustin Pop
                           help="Don't check that the instance's IP"
818 91e0748c Iustin Pop
                           " is alive")
819 91e0748c Iustin Pop
820 460d22be Iustin Pop
NONAMECHECK_OPT = cli_option("--no-name-check", dest="name_check",
821 460d22be Iustin Pop
                             default=True, action="store_false",
822 460d22be Iustin Pop
                             help="Don't check that the instance's name"
823 460d22be Iustin Pop
                             " is resolvable")
824 460d22be Iustin Pop
825 7d3a9fab Iustin Pop
NET_OPT = cli_option("--net",
826 7d3a9fab Iustin Pop
                     help="NIC parameters", default=[],
827 7d3a9fab Iustin Pop
                     dest="nics", action="append", type="identkeyval")
828 e3876ccb Iustin Pop
829 e3876ccb Iustin Pop
DISK_OPT = cli_option("--disk", help="Disk parameters", default=[],
830 e3876ccb Iustin Pop
                      dest="disks", action="append", type="identkeyval")
831 91e0748c Iustin Pop
832 4b038a1e Iustin Pop
DISKIDX_OPT = cli_option("--disks", dest="disks", default=None,
833 4b038a1e Iustin Pop
                         help="Comma-separated list of disks"
834 4b038a1e Iustin Pop
                         " indices to act on (e.g. 0,2) (optional,"
835 4b038a1e Iustin Pop
                         " defaults to all disks)")
836 4b038a1e Iustin Pop
837 ff00c1a7 Iustin Pop
OS_SIZE_OPT = cli_option("-s", "--os-size", dest="sd_size",
838 ff00c1a7 Iustin Pop
                         help="Enforces a single-disk configuration using the"
839 ff00c1a7 Iustin Pop
                         " given disk size, in MiB unless a suffix is used",
840 ff00c1a7 Iustin Pop
                         default=None, type="unit", metavar="<size>")
841 ff00c1a7 Iustin Pop
842 82a786d5 Iustin Pop
IGNORE_CONSIST_OPT = cli_option("--ignore-consistency",
843 82a786d5 Iustin Pop
                                dest="ignore_consistency",
844 82a786d5 Iustin Pop
                                action="store_true", default=False,
845 82a786d5 Iustin Pop
                                help="Ignore the consistency of the disks on"
846 82a786d5 Iustin Pop
                                " the secondary")
847 82a786d5 Iustin Pop
848 e9c487be René Nussbaumer
ALLOW_FAILOVER_OPT = cli_option("--allow-failover",
849 e9c487be René Nussbaumer
                                dest="allow_failover",
850 e9c487be René Nussbaumer
                                action="store_true", default=False,
851 e9c487be René Nussbaumer
                                help="If migration is not possible fallback to"
852 e9c487be René Nussbaumer
                                     " failover")
853 e9c487be René Nussbaumer
854 f2a0828c Iustin Pop
NONLIVE_OPT = cli_option("--non-live", dest="live",
855 f2a0828c Iustin Pop
                         default=True, action="store_false",
856 f2a0828c Iustin Pop
                         help="Do a non-live migration (this usually means"
857 f2a0828c Iustin Pop
                         " freeze the instance, save the state, transfer and"
858 f2a0828c Iustin Pop
                         " only then resume running on the secondary node)")
859 f2a0828c Iustin Pop
860 783a6c0b Iustin Pop
MIGRATION_MODE_OPT = cli_option("--migration-mode", dest="migration_mode",
861 e71b9ef4 Iustin Pop
                                default=None,
862 783a6c0b Iustin Pop
                                choices=list(constants.HT_MIGRATION_MODES),
863 783a6c0b Iustin Pop
                                help="Override default migration mode (choose"
864 e71b9ef4 Iustin Pop
                                " either live or non-live")
865 e71b9ef4 Iustin Pop
866 990b7886 Iustin Pop
NODE_PLACEMENT_OPT = cli_option("-n", "--node", dest="node",
867 990b7886 Iustin Pop
                                help="Target node and optional secondary node",
868 990b7886 Iustin Pop
                                metavar="<pnode>[:<snode>]",
869 990b7886 Iustin Pop
                                completion_suggest=OPT_COMPL_INST_ADD_NODES)
870 990b7886 Iustin Pop
871 7edc4637 Iustin Pop
NODE_LIST_OPT = cli_option("-n", "--node", dest="nodes", default=[],
872 7edc4637 Iustin Pop
                           action="append", metavar="<node>",
873 7edc4637 Iustin Pop
                           help="Use only this node (can be used multiple"
874 7edc4637 Iustin Pop
                           " times, if not given defaults to all nodes)",
875 7edc4637 Iustin Pop
                           completion_suggest=OPT_COMPL_ONE_NODE)
876 f36d7d81 Iustin Pop
877 21ee2318 Michael Hanselmann
NODEGROUP_OPT_NAME = "--node-group"
878 21ee2318 Michael Hanselmann
NODEGROUP_OPT = cli_option("-g", NODEGROUP_OPT_NAME,
879 5fbbd028 Guido Trotter
                           dest="nodegroup",
880 5fbbd028 Guido Trotter
                           help="Node group (name or uuid)",
881 5fbbd028 Guido Trotter
                           metavar="<nodegroup>",
882 5fbbd028 Guido Trotter
                           default=None, type="string",
883 5fbbd028 Guido Trotter
                           completion_suggest=OPT_COMPL_ONE_NODEGROUP)
884 5fbbd028 Guido Trotter
885 f36d7d81 Iustin Pop
SINGLE_NODE_OPT = cli_option("-n", "--node", dest="node", help="Target node",
886 f36d7d81 Iustin Pop
                             metavar="<node>",
887 f36d7d81 Iustin Pop
                             completion_suggest=OPT_COMPL_ONE_NODE)
888 7edc4637 Iustin Pop
889 edeb878a Iustin Pop
NOSTART_OPT = cli_option("--no-start", dest="start", default=True,
890 edeb878a Iustin Pop
                         action="store_false",
891 edeb878a Iustin Pop
                         help="Don't start the instance after creation")
892 edeb878a Iustin Pop
893 fdcf4d84 Iustin Pop
SHOWCMD_OPT = cli_option("--show-cmd", dest="show_command",
894 fdcf4d84 Iustin Pop
                         action="store_true", default=False,
895 fdcf4d84 Iustin Pop
                         help="Show command instead of executing it")
896 fdcf4d84 Iustin Pop
897 baef337d Iustin Pop
CLEANUP_OPT = cli_option("--cleanup", dest="cleanup",
898 baef337d Iustin Pop
                         default=False, action="store_true",
899 baef337d Iustin Pop
                         help="Instead of performing the migration, try to"
900 baef337d Iustin Pop
                         " recover from a failed cleanup. This is safe"
901 baef337d Iustin Pop
                         " to run even if the instance is healthy, but it"
902 baef337d Iustin Pop
                         " will create extra replication traffic and "
903 baef337d Iustin Pop
                         " disrupt briefly the replication (like during the"
904 baef337d Iustin Pop
                         " migration")
905 baef337d Iustin Pop
906 99a8c799 Iustin Pop
STATIC_OPT = cli_option("-s", "--static", dest="static",
907 99a8c799 Iustin Pop
                        action="store_true", default=False,
908 99a8c799 Iustin Pop
                        help="Only show configuration data, not runtime data")
909 99a8c799 Iustin Pop
910 2d5e7ae1 Iustin Pop
ALL_OPT = cli_option("--all", dest="show_all",
911 2d5e7ae1 Iustin Pop
                     default=False, action="store_true",
912 2d5e7ae1 Iustin Pop
                     help="Show info on all instances on the cluster."
913 2d5e7ae1 Iustin Pop
                     " This can take a long time to run, use wisely")
914 2d5e7ae1 Iustin Pop
915 67840b40 Iustin Pop
SELECT_OS_OPT = cli_option("--select-os", dest="select_os",
916 67840b40 Iustin Pop
                           action="store_true", default=False,
917 67840b40 Iustin Pop
                           help="Interactive OS reinstall, lists available"
918 67840b40 Iustin Pop
                           " OS templates for selection")
919 2d5e7ae1 Iustin Pop
920 b6e841a8 Iustin Pop
IGNORE_FAILURES_OPT = cli_option("--ignore-failures", dest="ignore_failures",
921 b6e841a8 Iustin Pop
                                 action="store_true", default=False,
922 b6e841a8 Iustin Pop
                                 help="Remove the instance from the cluster"
923 b6e841a8 Iustin Pop
                                 " configuration even if there are failures"
924 b6e841a8 Iustin Pop
                                 " during the removal process")
925 b6e841a8 Iustin Pop
926 8d8d650c Michael Hanselmann
IGNORE_REMOVE_FAILURES_OPT = cli_option("--ignore-remove-failures",
927 8d8d650c Michael Hanselmann
                                        dest="ignore_remove_failures",
928 8d8d650c Michael Hanselmann
                                        action="store_true", default=False,
929 8d8d650c Michael Hanselmann
                                        help="Remove the instance from the"
930 8d8d650c Michael Hanselmann
                                        " cluster configuration even if there"
931 8d8d650c Michael Hanselmann
                                        " are failures during the removal"
932 8d8d650c Michael Hanselmann
                                        " process")
933 8d8d650c Michael Hanselmann
934 8d8d650c Michael Hanselmann
REMOVE_INSTANCE_OPT = cli_option("--remove-instance", dest="remove_instance",
935 8d8d650c Michael Hanselmann
                                 action="store_true", default=False,
936 8d8d650c Michael Hanselmann
                                 help="Remove the instance from the cluster")
937 8d8d650c Michael Hanselmann
938 1b7761fd Apollon Oikonomopoulos
DST_NODE_OPT = cli_option("-n", "--target-node", dest="dst_node",
939 1b7761fd Apollon Oikonomopoulos
                               help="Specifies the new node for the instance",
940 1b7761fd Apollon Oikonomopoulos
                               metavar="NODE", default=None,
941 1b7761fd Apollon Oikonomopoulos
                               completion_suggest=OPT_COMPL_ONE_NODE)
942 1b7761fd Apollon Oikonomopoulos
943 a14db5ff Iustin Pop
NEW_SECONDARY_OPT = cli_option("-n", "--new-secondary", dest="dst_node",
944 a14db5ff Iustin Pop
                               help="Specifies the new secondary node",
945 a14db5ff Iustin Pop
                               metavar="NODE", default=None,
946 a14db5ff Iustin Pop
                               completion_suggest=OPT_COMPL_ONE_NODE)
947 a14db5ff Iustin Pop
948 a72d0a79 Iustin Pop
ON_PRIMARY_OPT = cli_option("-p", "--on-primary", dest="on_primary",
949 a72d0a79 Iustin Pop
                            default=False, action="store_true",
950 a72d0a79 Iustin Pop
                            help="Replace the disk(s) on the primary"
951 235407ba Michael Hanselmann
                                 " node (applies only to internally mirrored"
952 235407ba Michael Hanselmann
                                 " disk templates, e.g. %s)" %
953 235407ba Michael Hanselmann
                                 utils.CommaJoin(constants.DTS_INT_MIRROR))
954 feb09e6a Iustin Pop
955 feb09e6a Iustin Pop
ON_SECONDARY_OPT = cli_option("-s", "--on-secondary", dest="on_secondary",
956 feb09e6a Iustin Pop
                              default=False, action="store_true",
957 feb09e6a Iustin Pop
                              help="Replace the disk(s) on the secondary"
958 235407ba Michael Hanselmann
                                   " node (applies only to internally mirrored"
959 235407ba Michael Hanselmann
                                   " disk templates, e.g. %s)" %
960 235407ba Michael Hanselmann
                                   utils.CommaJoin(constants.DTS_INT_MIRROR))
961 e00f7a05 Iustin Pop
962 4c61d894 Iustin Pop
AUTO_PROMOTE_OPT = cli_option("--auto-promote", dest="auto_promote",
963 4c61d894 Iustin Pop
                              default=False, action="store_true",
964 4c61d894 Iustin Pop
                              help="Lock all nodes and auto-promote as needed"
965 4c61d894 Iustin Pop
                              " to MC status")
966 4c61d894 Iustin Pop
967 e00f7a05 Iustin Pop
AUTO_REPLACE_OPT = cli_option("-a", "--auto", dest="auto",
968 e00f7a05 Iustin Pop
                              default=False, action="store_true",
969 e00f7a05 Iustin Pop
                              help="Automatically replace faulty disks"
970 235407ba Michael Hanselmann
                                   " (applies only to internally mirrored"
971 235407ba Michael Hanselmann
                                   " disk templates, e.g. %s)" %
972 235407ba Michael Hanselmann
                                   utils.CommaJoin(constants.DTS_INT_MIRROR))
973 a72d0a79 Iustin Pop
974 05586c90 Iustin Pop
IGNORE_SIZE_OPT = cli_option("--ignore-size", dest="ignore_size",
975 05586c90 Iustin Pop
                             default=False, action="store_true",
976 05586c90 Iustin Pop
                             help="Ignore current recorded size"
977 05586c90 Iustin Pop
                             " (useful for forcing activation when"
978 05586c90 Iustin Pop
                             " the recorded size is wrong)")
979 05586c90 Iustin Pop
980 df62e5db Iustin Pop
SRC_NODE_OPT = cli_option("--src-node", dest="src_node", help="Source node",
981 df62e5db Iustin Pop
                          metavar="<node>",
982 df62e5db Iustin Pop
                          completion_suggest=OPT_COMPL_ONE_NODE)
983 df62e5db Iustin Pop
984 df62e5db Iustin Pop
SRC_DIR_OPT = cli_option("--src-dir", dest="src_dir", help="Source directory",
985 df62e5db Iustin Pop
                         metavar="<dir>")
986 df62e5db Iustin Pop
987 8d823629 Iustin Pop
SECONDARY_IP_OPT = cli_option("-s", "--secondary-ip", dest="secondary_ip",
988 8d823629 Iustin Pop
                              help="Specify the secondary ip for the node",
989 8d823629 Iustin Pop
                              metavar="ADDRESS", default=None)
990 8d823629 Iustin Pop
991 b8d0f938 Iustin Pop
READD_OPT = cli_option("--readd", dest="readd",
992 b8d0f938 Iustin Pop
                       default=False, action="store_true",
993 b8d0f938 Iustin Pop
                       help="Readd old node after replacing it")
994 b8d0f938 Iustin Pop
995 fcdde7f2 Iustin Pop
NOSSH_KEYCHECK_OPT = cli_option("--no-ssh-key-check", dest="ssh_key_check",
996 fcdde7f2 Iustin Pop
                                default=True, action="store_false",
997 fcdde7f2 Iustin Pop
                                help="Disable SSH key fingerprint checking")
998 fcdde7f2 Iustin Pop
999 61413377 Stephen Shirley
NODE_FORCE_JOIN_OPT = cli_option("--force-join", dest="force_join",
1000 61413377 Stephen Shirley
                                 default=False, action="store_true",
1001 50769215 Stephen Shirley
                                 help="Force the joining of a node")
1002 61413377 Stephen Shirley
1003 771734c9 Iustin Pop
MC_OPT = cli_option("-C", "--master-candidate", dest="master_candidate",
1004 e7b61bb0 Iustin Pop
                    type="bool", default=None, metavar=_YORNO,
1005 771734c9 Iustin Pop
                    help="Set the master_candidate flag on the node")
1006 771734c9 Iustin Pop
1007 771734c9 Iustin Pop
OFFLINE_OPT = cli_option("-O", "--offline", dest="offline", metavar=_YORNO,
1008 e7b61bb0 Iustin Pop
                         type="bool", default=None,
1009 34616379 Michael Hanselmann
                         help=("Set the offline flag on the node"
1010 34616379 Michael Hanselmann
                               " (cluster does not communicate with offline"
1011 34616379 Michael Hanselmann
                               " nodes)"))
1012 771734c9 Iustin Pop
1013 771734c9 Iustin Pop
DRAINED_OPT = cli_option("-D", "--drained", dest="drained", metavar=_YORNO,
1014 e7b61bb0 Iustin Pop
                         type="bool", default=None,
1015 34616379 Michael Hanselmann
                         help=("Set the drained flag on the node"
1016 34616379 Michael Hanselmann
                               " (excluded from allocation operations)"))
1017 771734c9 Iustin Pop
1018 f91e255a Iustin Pop
CAPAB_MASTER_OPT = cli_option("--master-capable", dest="master_capable",
1019 f91e255a Iustin Pop
                    type="bool", default=None, metavar=_YORNO,
1020 f91e255a Iustin Pop
                    help="Set the master_capable flag on the node")
1021 f91e255a Iustin Pop
1022 53919782 Iustin Pop
CAPAB_VM_OPT = cli_option("--vm-capable", dest="vm_capable",
1023 53919782 Iustin Pop
                    type="bool", default=None, metavar=_YORNO,
1024 53919782 Iustin Pop
                    help="Set the vm_capable flag on the node")
1025 53919782 Iustin Pop
1026 e7e09483 Iustin Pop
ALLOCATABLE_OPT = cli_option("--allocatable", dest="allocatable",
1027 e7b61bb0 Iustin Pop
                             type="bool", default=None, metavar=_YORNO,
1028 e7e09483 Iustin Pop
                             help="Set the allocatable flag on a volume")
1029 e7e09483 Iustin Pop
1030 831040bf Iustin Pop
NOLVM_STORAGE_OPT = cli_option("--no-lvm-storage", dest="lvm_storage",
1031 831040bf Iustin Pop
                               help="Disable support for lvm based instances"
1032 831040bf Iustin Pop
                               " (cluster-wide)",
1033 831040bf Iustin Pop
                               action="store_false", default=True)
1034 831040bf Iustin Pop
1035 383a3591 Iustin Pop
ENABLED_HV_OPT = cli_option("--enabled-hypervisors",
1036 383a3591 Iustin Pop
                            dest="enabled_hypervisors",
1037 383a3591 Iustin Pop
                            help="Comma-separated list of hypervisors",
1038 383a3591 Iustin Pop
                            type="string", default=None)
1039 383a3591 Iustin Pop
1040 4fbc93dd Iustin Pop
NIC_PARAMS_OPT = cli_option("-N", "--nic-parameters", dest="nicparams",
1041 4fbc93dd Iustin Pop
                            type="keyval", default={},
1042 4fbc93dd Iustin Pop
                            help="NIC parameters")
1043 4fbc93dd Iustin Pop
1044 e32df528 Iustin Pop
CP_SIZE_OPT = cli_option("-C", "--candidate-pool-size", default=None,
1045 e32df528 Iustin Pop
                         dest="candidate_pool_size", type="int",
1046 e32df528 Iustin Pop
                         help="Set the candidate pool size")
1047 e32df528 Iustin Pop
1048 04367e70 Guido Trotter
VG_NAME_OPT = cli_option("--vg-name", dest="vg_name",
1049 34616379 Michael Hanselmann
                         help=("Enables LVM and specifies the volume group"
1050 34616379 Michael Hanselmann
                               " name (cluster-wide) for disk allocation"
1051 34616379 Michael Hanselmann
                               " [%s]" % constants.DEFAULT_VG),
1052 b58726e8 Iustin Pop
                         metavar="VG", default=None)
1053 b58726e8 Iustin Pop
1054 a3ac3243 Iustin Pop
YES_DOIT_OPT = cli_option("--yes-do-it", "--ya-rly", dest="yes_do_it",
1055 1f587d3d Iustin Pop
                          help="Destroy cluster", action="store_true")
1056 b58726e8 Iustin Pop
1057 58371861 Iustin Pop
NOVOTING_OPT = cli_option("--no-voting", dest="no_voting",
1058 58371861 Iustin Pop
                          help="Skip node agreement check (dangerous)",
1059 58371861 Iustin Pop
                          action="store_true", default=False)
1060 58371861 Iustin Pop
1061 e3646f22 Iustin Pop
MAC_PREFIX_OPT = cli_option("-m", "--mac-prefix", dest="mac_prefix",
1062 e3646f22 Iustin Pop
                            help="Specify the mac prefix for the instance IP"
1063 e3646f22 Iustin Pop
                            " addresses, in the format XX:XX:XX",
1064 e3646f22 Iustin Pop
                            metavar="PREFIX",
1065 e3646f22 Iustin Pop
                            default=None)
1066 e3646f22 Iustin Pop
1067 29392516 Iustin Pop
MASTER_NETDEV_OPT = cli_option("--master-netdev", dest="master_netdev",
1068 29392516 Iustin Pop
                               help="Specify the node interface (cluster-wide)"
1069 25be0c75 Guido Trotter
                               " on which the master IP address will be added"
1070 25be0c75 Guido Trotter
                               " (cluster init default: %s)" %
1071 25be0c75 Guido Trotter
                               constants.DEFAULT_BRIDGE,
1072 29392516 Iustin Pop
                               metavar="NETDEV",
1073 25be0c75 Guido Trotter
                               default=None)
1074 29392516 Iustin Pop
1075 5a8648eb Andrea Spadaccini
MASTER_NETMASK_OPT = cli_option("--master-netmask", dest="master_netmask",
1076 5a8648eb Andrea Spadaccini
                                help="Specify the netmask of the master IP",
1077 5a8648eb Andrea Spadaccini
                                metavar="NETMASK",
1078 5a8648eb Andrea Spadaccini
                                default=None)
1079 5a8648eb Andrea Spadaccini
1080 bf689b7a Andrea Spadaccini
USE_EXTERNAL_MIP_SCRIPT = cli_option("--use-external-mip-script",
1081 bf689b7a Andrea Spadaccini
                                dest="use_external_mip_script",
1082 bf689b7a Andrea Spadaccini
                                help="Specify whether to run a user-provided"
1083 bf689b7a Andrea Spadaccini
                                " script for the master IP address turnup and"
1084 bf689b7a Andrea Spadaccini
                                " turndown operations",
1085 bf689b7a Andrea Spadaccini
                                type="bool", metavar=_YORNO, default=None)
1086 bf689b7a Andrea Spadaccini
1087 29392516 Iustin Pop
GLOBAL_FILEDIR_OPT = cli_option("--file-storage-dir", dest="file_storage_dir",
1088 29392516 Iustin Pop
                                help="Specify the default directory (cluster-"
1089 29392516 Iustin Pop
                                "wide) for storing the file-based disks [%s]" %
1090 29392516 Iustin Pop
                                constants.DEFAULT_FILE_STORAGE_DIR,
1091 29392516 Iustin Pop
                                metavar="DIR",
1092 29392516 Iustin Pop
                                default=constants.DEFAULT_FILE_STORAGE_DIR)
1093 4b97f902 Apollon Oikonomopoulos
1094 4b97f902 Apollon Oikonomopoulos
GLOBAL_SHARED_FILEDIR_OPT = cli_option("--shared-file-storage-dir",
1095 4b97f902 Apollon Oikonomopoulos
                            dest="shared_file_storage_dir",
1096 4b97f902 Apollon Oikonomopoulos
                            help="Specify the default directory (cluster-"
1097 4b97f902 Apollon Oikonomopoulos
                            "wide) for storing the shared file-based"
1098 4b97f902 Apollon Oikonomopoulos
                            " disks [%s]" %
1099 4b97f902 Apollon Oikonomopoulos
                            constants.DEFAULT_SHARED_FILE_STORAGE_DIR,
1100 4b97f902 Apollon Oikonomopoulos
                            metavar="SHAREDDIR",
1101 4b97f902 Apollon Oikonomopoulos
                            default=constants.DEFAULT_SHARED_FILE_STORAGE_DIR)
1102 29392516 Iustin Pop
1103 29392516 Iustin Pop
NOMODIFY_ETCHOSTS_OPT = cli_option("--no-etc-hosts", dest="modify_etc_hosts",
1104 29392516 Iustin Pop
                                   help="Don't modify /etc/hosts",
1105 29392516 Iustin Pop
                                   action="store_false", default=True)
1106 29392516 Iustin Pop
1107 b989b9d9 Ken Wehr
NOMODIFY_SSH_SETUP_OPT = cli_option("--no-ssh-init", dest="modify_ssh_setup",
1108 b989b9d9 Ken Wehr
                                    help="Don't initialize SSH keys",
1109 b989b9d9 Ken Wehr
                                    action="store_false", default=True)
1110 b989b9d9 Ken Wehr
1111 14e9e7f3 Iustin Pop
ERROR_CODES_OPT = cli_option("--error-codes", dest="error_codes",
1112 14e9e7f3 Iustin Pop
                             help="Enable parseable error messages",
1113 14e9e7f3 Iustin Pop
                             action="store_true", default=False)
1114 14e9e7f3 Iustin Pop
1115 14e9e7f3 Iustin Pop
NONPLUS1_OPT = cli_option("--no-nplus1-mem", dest="skip_nplusone_mem",
1116 14e9e7f3 Iustin Pop
                          help="Skip N+1 memory redundancy tests",
1117 14e9e7f3 Iustin Pop
                          action="store_true", default=False)
1118 14e9e7f3 Iustin Pop
1119 12054861 Iustin Pop
REBOOT_TYPE_OPT = cli_option("-t", "--type", dest="reboot_type",
1120 12054861 Iustin Pop
                             help="Type of reboot: soft/hard/full",
1121 12054861 Iustin Pop
                             default=constants.INSTANCE_REBOOT_HARD,
1122 12054861 Iustin Pop
                             metavar="<REBOOT>",
1123 12054861 Iustin Pop
                             choices=list(constants.REBOOT_TYPES))
1124 12054861 Iustin Pop
1125 ee3f9578 Iustin Pop
IGNORE_SECONDARIES_OPT = cli_option("--ignore-secondaries",
1126 ee3f9578 Iustin Pop
                                    dest="ignore_secondaries",
1127 ee3f9578 Iustin Pop
                                    default=False, action="store_true",
1128 ee3f9578 Iustin Pop
                                    help="Ignore errors from secondaries")
1129 ee3f9578 Iustin Pop
1130 69b99987 Michael Hanselmann
NOSHUTDOWN_OPT = cli_option("--noshutdown", dest="shutdown",
1131 44c44832 Iustin Pop
                            action="store_false", default=True,
1132 44c44832 Iustin Pop
                            help="Don't shutdown the instance (unsafe)")
1133 44c44832 Iustin Pop
1134 b5762e2a Guido Trotter
TIMEOUT_OPT = cli_option("--timeout", dest="timeout", type="int",
1135 b5762e2a Guido Trotter
                         default=constants.DEFAULT_SHUTDOWN_TIMEOUT,
1136 b5762e2a Guido Trotter
                         help="Maximum time to wait")
1137 44c44832 Iustin Pop
1138 4d98c565 Guido Trotter
SHUTDOWN_TIMEOUT_OPT = cli_option("--shutdown-timeout",
1139 4d98c565 Guido Trotter
                         dest="shutdown_timeout", type="int",
1140 7e5eaaa8 Guido Trotter
                         default=constants.DEFAULT_SHUTDOWN_TIMEOUT,
1141 7e5eaaa8 Guido Trotter
                         help="Maximum time to wait for instance shutdown")
1142 7e5eaaa8 Guido Trotter
1143 19b9ba9a Michael Hanselmann
INTERVAL_OPT = cli_option("--interval", dest="interval", type="int",
1144 19b9ba9a Michael Hanselmann
                          default=None,
1145 19b9ba9a Michael Hanselmann
                          help=("Number of seconds between repetions of the"
1146 19b9ba9a Michael Hanselmann
                                " command"))
1147 19b9ba9a Michael Hanselmann
1148 7ea7bcf6 Iustin Pop
EARLY_RELEASE_OPT = cli_option("--early-release",
1149 7ea7bcf6 Iustin Pop
                               dest="early_release", default=False,
1150 7ea7bcf6 Iustin Pop
                               action="store_true",
1151 7ea7bcf6 Iustin Pop
                               help="Release the locks on the secondary"
1152 7ea7bcf6 Iustin Pop
                               " node(s) early")
1153 7ea7bcf6 Iustin Pop
1154 6d4a1656 Michael Hanselmann
NEW_CLUSTER_CERT_OPT = cli_option("--new-cluster-certificate",
1155 6d4a1656 Michael Hanselmann
                                  dest="new_cluster_cert",
1156 6d4a1656 Michael Hanselmann
                                  default=False, action="store_true",
1157 6d4a1656 Michael Hanselmann
                                  help="Generate a new cluster certificate")
1158 6d4a1656 Michael Hanselmann
1159 6d4a1656 Michael Hanselmann
RAPI_CERT_OPT = cli_option("--rapi-certificate", dest="rapi_cert",
1160 6d4a1656 Michael Hanselmann
                           default=None,
1161 6d4a1656 Michael Hanselmann
                           help="File containing new RAPI certificate")
1162 6d4a1656 Michael Hanselmann
1163 6d4a1656 Michael Hanselmann
NEW_RAPI_CERT_OPT = cli_option("--new-rapi-certificate", dest="new_rapi_cert",
1164 6d4a1656 Michael Hanselmann
                               default=None, action="store_true",
1165 6d4a1656 Michael Hanselmann
                               help=("Generate a new self-signed RAPI"
1166 6d4a1656 Michael Hanselmann
                                     " certificate"))
1167 6d4a1656 Michael Hanselmann
1168 b6267745 Andrea Spadaccini
SPICE_CERT_OPT = cli_option("--spice-certificate", dest="spice_cert",
1169 b6267745 Andrea Spadaccini
                           default=None,
1170 b6267745 Andrea Spadaccini
                           help="File containing new SPICE certificate")
1171 b6267745 Andrea Spadaccini
1172 b6267745 Andrea Spadaccini
SPICE_CACERT_OPT = cli_option("--spice-ca-certificate", dest="spice_cacert",
1173 b6267745 Andrea Spadaccini
                           default=None,
1174 b6267745 Andrea Spadaccini
                           help="File containing the certificate of the CA"
1175 b6267745 Andrea Spadaccini
                                " which signed the SPICE certificate")
1176 b6267745 Andrea Spadaccini
1177 b6267745 Andrea Spadaccini
NEW_SPICE_CERT_OPT = cli_option("--new-spice-certificate",
1178 b6267745 Andrea Spadaccini
                               dest="new_spice_cert", default=None,
1179 b6267745 Andrea Spadaccini
                               action="store_true",
1180 b6267745 Andrea Spadaccini
                               help=("Generate a new self-signed SPICE"
1181 b6267745 Andrea Spadaccini
                                     " certificate"))
1182 b6267745 Andrea Spadaccini
1183 6b7d5878 Michael Hanselmann
NEW_CONFD_HMAC_KEY_OPT = cli_option("--new-confd-hmac-key",
1184 6b7d5878 Michael Hanselmann
                                    dest="new_confd_hmac_key",
1185 6b7d5878 Michael Hanselmann
                                    default=False, action="store_true",
1186 6b7d5878 Michael Hanselmann
                                    help=("Create a new HMAC key for %s" %
1187 6b7d5878 Michael Hanselmann
                                          constants.CONFD))
1188 6d4a1656 Michael Hanselmann
1189 3db3eb2a Michael Hanselmann
CLUSTER_DOMAIN_SECRET_OPT = cli_option("--cluster-domain-secret",
1190 3db3eb2a Michael Hanselmann
                                       dest="cluster_domain_secret",
1191 3db3eb2a Michael Hanselmann
                                       default=None,
1192 3db3eb2a Michael Hanselmann
                                       help=("Load new new cluster domain"
1193 3db3eb2a Michael Hanselmann
                                             " secret from file"))
1194 3db3eb2a Michael Hanselmann
1195 3db3eb2a Michael Hanselmann
NEW_CLUSTER_DOMAIN_SECRET_OPT = cli_option("--new-cluster-domain-secret",
1196 3db3eb2a Michael Hanselmann
                                           dest="new_cluster_domain_secret",
1197 3db3eb2a Michael Hanselmann
                                           default=False, action="store_true",
1198 3db3eb2a Michael Hanselmann
                                           help=("Create a new cluster domain"
1199 3db3eb2a Michael Hanselmann
                                                 " secret"))
1200 3db3eb2a Michael Hanselmann
1201 74adc100 Iustin Pop
USE_REPL_NET_OPT = cli_option("--use-replication-network",
1202 74adc100 Iustin Pop
                              dest="use_replication_network",
1203 74adc100 Iustin Pop
                              help="Whether to use the replication network"
1204 74adc100 Iustin Pop
                              " for talking to the nodes",
1205 74adc100 Iustin Pop
                              action="store_true", default=False)
1206 74adc100 Iustin Pop
1207 3953242f Iustin Pop
MAINTAIN_NODE_HEALTH_OPT = \
1208 3953242f Iustin Pop
    cli_option("--maintain-node-health", dest="maintain_node_health",
1209 3953242f Iustin Pop
               metavar=_YORNO, default=None, type="bool",
1210 3953242f Iustin Pop
               help="Configure the cluster to automatically maintain node"
1211 3953242f Iustin Pop
               " health, by shutting down unknown instances, shutting down"
1212 3953242f Iustin Pop
               " unknown DRBD devices, etc.")
1213 3953242f Iustin Pop
1214 e588764d Iustin Pop
IDENTIFY_DEFAULTS_OPT = \
1215 e588764d Iustin Pop
    cli_option("--identify-defaults", dest="identify_defaults",
1216 e588764d Iustin Pop
               default=False, action="store_true",
1217 e588764d Iustin Pop
               help="Identify which saved instance parameters are equal to"
1218 e588764d Iustin Pop
               " the current cluster defaults and set them as such, instead"
1219 e588764d Iustin Pop
               " of marking them as overridden")
1220 e588764d Iustin Pop
1221 1338f2b4 Balazs Lecz
UIDPOOL_OPT = cli_option("--uid-pool", default=None,
1222 1338f2b4 Balazs Lecz
                         action="store", dest="uid_pool",
1223 1338f2b4 Balazs Lecz
                         help=("A list of user-ids or user-id"
1224 1338f2b4 Balazs Lecz
                               " ranges separated by commas"))
1225 1338f2b4 Balazs Lecz
1226 fdad8c4d Balazs Lecz
ADD_UIDS_OPT = cli_option("--add-uids", default=None,
1227 fdad8c4d Balazs Lecz
                          action="store", dest="add_uids",
1228 fdad8c4d Balazs Lecz
                          help=("A list of user-ids or user-id"
1229 fdad8c4d Balazs Lecz
                                " ranges separated by commas, to be"
1230 fdad8c4d Balazs Lecz
                                " added to the user-id pool"))
1231 fdad8c4d Balazs Lecz
1232 fdad8c4d Balazs Lecz
REMOVE_UIDS_OPT = cli_option("--remove-uids", default=None,
1233 fdad8c4d Balazs Lecz
                             action="store", dest="remove_uids",
1234 fdad8c4d Balazs Lecz
                             help=("A list of user-ids or user-id"
1235 fdad8c4d Balazs Lecz
                                   " ranges separated by commas, to be"
1236 fdad8c4d Balazs Lecz
                                   " removed from the user-id pool"))
1237 fdad8c4d Balazs Lecz
1238 f38ea602 Iustin Pop
RESERVED_LVS_OPT = cli_option("--reserved-lvs", default=None,
1239 f38ea602 Iustin Pop
                             action="store", dest="reserved_lvs",
1240 f38ea602 Iustin Pop
                             help=("A comma-separated list of reserved"
1241 f38ea602 Iustin Pop
                                   " logical volumes names, that will be"
1242 f38ea602 Iustin Pop
                                   " ignored by cluster verify"))
1243 f38ea602 Iustin Pop
1244 31d97b2a Guido Trotter
ROMAN_OPT = cli_option("--roman",
1245 31d97b2a Guido Trotter
                       dest="roman_integers", default=False,
1246 31d97b2a Guido Trotter
                       action="store_true",
1247 31d97b2a Guido Trotter
                       help="Use roman numbers for positive integers")
1248 31d97b2a Guido Trotter
1249 26591bfd Luca Bigliardi
DRBD_HELPER_OPT = cli_option("--drbd-usermode-helper", dest="drbd_helper",
1250 26591bfd Luca Bigliardi
                             action="store", default=None,
1251 26591bfd Luca Bigliardi
                             help="Specifies usermode helper for DRBD")
1252 26591bfd Luca Bigliardi
1253 26591bfd Luca Bigliardi
NODRBD_STORAGE_OPT = cli_option("--no-drbd-storage", dest="drbd_storage",
1254 26591bfd Luca Bigliardi
                                action="store_false", default=True,
1255 26591bfd Luca Bigliardi
                                help="Disable support for DRBD")
1256 31d97b2a Guido Trotter
1257 e7323b5e Manuel Franceschini
PRIMARY_IP_VERSION_OPT = \
1258 e7323b5e Manuel Franceschini
    cli_option("--primary-ip-version", default=constants.IP4_VERSION,
1259 e7323b5e Manuel Franceschini
               action="store", dest="primary_ip_version",
1260 e7323b5e Manuel Franceschini
               metavar="%d|%d" % (constants.IP4_VERSION,
1261 e7323b5e Manuel Franceschini
                                  constants.IP6_VERSION),
1262 e7323b5e Manuel Franceschini
               help="Cluster-wide IP version for primary IP")
1263 e7323b5e Manuel Franceschini
1264 84a5b33c Michael Hanselmann
PRIORITY_OPT = cli_option("--priority", default=None, dest="priority",
1265 84a5b33c Michael Hanselmann
                          metavar="|".join(name for name, _ in _PRIORITY_NAMES),
1266 84a5b33c Michael Hanselmann
                          choices=_PRIONAME_TO_VALUE.keys(),
1267 aa06f8c6 Michael Hanselmann
                          help="Priority for opcode processing")
1268 84a5b33c Michael Hanselmann
1269 61a14bb3 Iustin Pop
HID_OS_OPT = cli_option("--hidden", dest="hidden",
1270 61a14bb3 Iustin Pop
                        type="bool", default=None, metavar=_YORNO,
1271 61a14bb3 Iustin Pop
                        help="Sets the hidden flag on the OS")
1272 61a14bb3 Iustin Pop
1273 61a14bb3 Iustin Pop
BLK_OS_OPT = cli_option("--blacklisted", dest="blacklisted",
1274 61a14bb3 Iustin Pop
                        type="bool", default=None, metavar=_YORNO,
1275 61a14bb3 Iustin Pop
                        help="Sets the blacklisted flag on the OS")
1276 61a14bb3 Iustin Pop
1277 b883637f René Nussbaumer
PREALLOC_WIPE_DISKS_OPT = cli_option("--prealloc-wipe-disks", default=None,
1278 b883637f René Nussbaumer
                                     type="bool", metavar=_YORNO,
1279 b883637f René Nussbaumer
                                     dest="prealloc_wipe_disks",
1280 b883637f René Nussbaumer
                                     help=("Wipe disks prior to instance"
1281 b883637f René Nussbaumer
                                           " creation"))
1282 b883637f René Nussbaumer
1283 a535cef7 René Nussbaumer
NODE_PARAMS_OPT = cli_option("--node-parameters", dest="ndparams",
1284 3c2b6a98 René Nussbaumer
                             type="keyval", default=None,
1285 a535cef7 René Nussbaumer
                             help="Node parameters")
1286 a535cef7 René Nussbaumer
1287 90e99856 Adeodato Simo
ALLOC_POLICY_OPT = cli_option("--alloc-policy", dest="alloc_policy",
1288 90e99856 Adeodato Simo
                              action="store", metavar="POLICY", default=None,
1289 90e99856 Adeodato Simo
                              help="Allocation policy for the node group")
1290 90e99856 Adeodato Simo
1291 d2881c71 René Nussbaumer
NODE_POWERED_OPT = cli_option("--node-powered", default=None,
1292 d2881c71 René Nussbaumer
                              type="bool", metavar=_YORNO,
1293 d2881c71 René Nussbaumer
                              dest="node_powered",
1294 d2881c71 René Nussbaumer
                              help="Specify if the SoR for node is powered")
1295 d2881c71 René Nussbaumer
1296 41543d8b René Nussbaumer
OOB_TIMEOUT_OPT = cli_option("--oob-timeout", dest="oob_timeout", type="int",
1297 41543d8b René Nussbaumer
                         default=constants.OOB_TIMEOUT,
1298 41543d8b René Nussbaumer
                         help="Maximum time to wait for out-of-band helper")
1299 41543d8b René Nussbaumer
1300 0c086a13 René Nussbaumer
POWER_DELAY_OPT = cli_option("--power-delay", dest="power_delay", type="float",
1301 0c086a13 René Nussbaumer
                             default=constants.OOB_POWER_DELAY,
1302 0c086a13 René Nussbaumer
                             help="Time in seconds to wait between power-ons")
1303 0c086a13 René Nussbaumer
1304 442587bf Michael Hanselmann
FORCE_FILTER_OPT = cli_option("-F", "--filter", dest="force_filter",
1305 442587bf Michael Hanselmann
                              action="store_true", default=False,
1306 442587bf Michael Hanselmann
                              help=("Whether command argument should be treated"
1307 442587bf Michael Hanselmann
                                    " as filter"))
1308 442587bf Michael Hanselmann
1309 885a0fc4 Iustin Pop
NO_REMEMBER_OPT = cli_option("--no-remember",
1310 885a0fc4 Iustin Pop
                             dest="no_remember",
1311 885a0fc4 Iustin Pop
                             action="store_true", default=False,
1312 885a0fc4 Iustin Pop
                             help="Perform but do not record the change"
1313 885a0fc4 Iustin Pop
                             " in the configuration")
1314 885a0fc4 Iustin Pop
1315 aafee533 Michael Hanselmann
PRIMARY_ONLY_OPT = cli_option("-p", "--primary-only",
1316 aafee533 Michael Hanselmann
                              default=False, action="store_true",
1317 aafee533 Michael Hanselmann
                              help="Evacuate primary instances only")
1318 aafee533 Michael Hanselmann
1319 aafee533 Michael Hanselmann
SECONDARY_ONLY_OPT = cli_option("-s", "--secondary-only",
1320 aafee533 Michael Hanselmann
                                default=False, action="store_true",
1321 aafee533 Michael Hanselmann
                                help="Evacuate secondary instances only"
1322 aafee533 Michael Hanselmann
                                     " (applies only to internally mirrored"
1323 aafee533 Michael Hanselmann
                                     " disk templates, e.g. %s)" %
1324 aafee533 Michael Hanselmann
                                     utils.CommaJoin(constants.DTS_INT_MIRROR))
1325 aafee533 Michael Hanselmann
1326 323f9095 Stephen Shirley
STARTUP_PAUSED_OPT = cli_option("--paused", dest="startup_paused",
1327 323f9095 Stephen Shirley
                                action="store_true", default=False,
1328 323f9095 Stephen Shirley
                                help="Pause instance at startup")
1329 323f9095 Stephen Shirley
1330 f6eb380d Michael Hanselmann
TO_GROUP_OPT = cli_option("--to", dest="to", metavar="<group>",
1331 f6eb380d Michael Hanselmann
                          help="Destination node group (name or uuid)",
1332 f6eb380d Michael Hanselmann
                          default=None, action="append",
1333 f6eb380d Michael Hanselmann
                          completion_suggest=OPT_COMPL_ONE_NODEGROUP)
1334 f6eb380d Michael Hanselmann
1335 93f2399e Andrea Spadaccini
IGNORE_ERRORS_OPT = cli_option("-I", "--ignore-errors", default=[],
1336 93f2399e Andrea Spadaccini
                               action="append", dest="ignore_errors",
1337 93f2399e Andrea Spadaccini
                               choices=list(constants.CV_ALL_ECODES_STRINGS),
1338 93f2399e Andrea Spadaccini
                               help="Error code to be ignored")
1339 93f2399e Andrea Spadaccini
1340 38f29a36 René Nussbaumer
DISK_STATE_OPT = cli_option("--disk-state", default=[], dest="disk_state",
1341 38f29a36 René Nussbaumer
                            action="append",
1342 38f29a36 René Nussbaumer
                            help=("Specify disk state information in the format"
1343 38f29a36 René Nussbaumer
                                  " storage_type/identifier:option=value,..."),
1344 38f29a36 René Nussbaumer
                            type="identkeyval")
1345 38f29a36 René Nussbaumer
1346 38f29a36 René Nussbaumer
HV_STATE_OPT = cli_option("--hypervisor-state", default=[], dest="hv_state",
1347 38f29a36 René Nussbaumer
                          action="append",
1348 38f29a36 René Nussbaumer
                          help=("Specify hypervisor state information in the"
1349 38f29a36 René Nussbaumer
                                " format hypervisor:option=value,..."),
1350 38f29a36 René Nussbaumer
                          type="identkeyval")
1351 38f29a36 René Nussbaumer
1352 b6aaf437 René Nussbaumer
IGNORE_IPOLICY_OPT = cli_option("--ignore-ipolicy", dest="ignore_ipolicy",
1353 b6aaf437 René Nussbaumer
                                action="store_true", default=False,
1354 b6aaf437 René Nussbaumer
                                help="Ignore instance policy violations")
1355 b6aaf437 René Nussbaumer
1356 61a14bb3 Iustin Pop
1357 5786c087 Michael Hanselmann
#: Options provided by all commands
1358 5786c087 Michael Hanselmann
COMMON_OPTS = [DEBUG_OPT]
1359 5786c087 Michael Hanselmann
1360 eb28ecf6 Guido Trotter
# common options for creating instances. add and import then add their own
1361 eb28ecf6 Guido Trotter
# specific ones.
1362 eb28ecf6 Guido Trotter
COMMON_CREATE_OPTS = [
1363 eb28ecf6 Guido Trotter
  BACKEND_OPT,
1364 eb28ecf6 Guido Trotter
  DISK_OPT,
1365 eb28ecf6 Guido Trotter
  DISK_TEMPLATE_OPT,
1366 eb28ecf6 Guido Trotter
  FILESTORE_DIR_OPT,
1367 eb28ecf6 Guido Trotter
  FILESTORE_DRIVER_OPT,
1368 eb28ecf6 Guido Trotter
  HYPERVISOR_OPT,
1369 eb28ecf6 Guido Trotter
  IALLOCATOR_OPT,
1370 eb28ecf6 Guido Trotter
  NET_OPT,
1371 eb28ecf6 Guido Trotter
  NODE_PLACEMENT_OPT,
1372 eb28ecf6 Guido Trotter
  NOIPCHECK_OPT,
1373 eb28ecf6 Guido Trotter
  NONAMECHECK_OPT,
1374 eb28ecf6 Guido Trotter
  NONICS_OPT,
1375 eb28ecf6 Guido Trotter
  NWSYNC_OPT,
1376 eb28ecf6 Guido Trotter
  OSPARAMS_OPT,
1377 eb28ecf6 Guido Trotter
  OS_SIZE_OPT,
1378 eb28ecf6 Guido Trotter
  SUBMIT_OPT,
1379 0f8810df Michael Hanselmann
  TAG_ADD_OPT,
1380 eb28ecf6 Guido Trotter
  DRY_RUN_OPT,
1381 eb28ecf6 Guido Trotter
  PRIORITY_OPT,
1382 eb28ecf6 Guido Trotter
  ]
1383 eb28ecf6 Guido Trotter
1384 771734c9 Iustin Pop
1385 ef9fa5b9 René Nussbaumer
def _ParseArgs(argv, commands, aliases, env_override):
1386 c41eea6e Iustin Pop
  """Parser for the command line arguments.
1387 a8083063 Iustin Pop

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

1391 c41eea6e Iustin Pop
  @param argv: the command line
1392 c41eea6e Iustin Pop
  @param commands: dictionary with special contents, see the design
1393 c41eea6e Iustin Pop
      doc for cmdline handling
1394 c41eea6e Iustin Pop
  @param aliases: dictionary with command aliases {'alias': 'target, ...}
1395 ef9fa5b9 René Nussbaumer
  @param env_override: list of env variables allowed for default args
1396 098c0958 Michael Hanselmann

1397 a8083063 Iustin Pop
  """
1398 ef9fa5b9 René Nussbaumer
  assert not (env_override - set(commands))
1399 ef9fa5b9 René Nussbaumer
1400 a8083063 Iustin Pop
  if len(argv) == 0:
1401 a8083063 Iustin Pop
    binary = "<command>"
1402 a8083063 Iustin Pop
  else:
1403 a8083063 Iustin Pop
    binary = argv[0].split("/")[-1]
1404 a8083063 Iustin Pop
1405 a8083063 Iustin Pop
  if len(argv) > 1 and argv[1] == "--version":
1406 84a12e40 Iustin Pop
    ToStdout("%s (ganeti %s) %s", binary, constants.VCS_VERSION,
1407 84a12e40 Iustin Pop
             constants.RELEASE_VERSION)
1408 a8083063 Iustin Pop
    # Quit right away. That way we don't have to care about this special
1409 a8083063 Iustin Pop
    # argument. optparse.py does it the same.
1410 a8083063 Iustin Pop
    sys.exit(0)
1411 a8083063 Iustin Pop
1412 de47cf8f Guido Trotter
  if len(argv) < 2 or not (argv[1] in commands or
1413 70a35b6f Guido Trotter
                           argv[1] in aliases):
1414 a8083063 Iustin Pop
    # let's do a nice thing
1415 a8083063 Iustin Pop
    sortedcmds = commands.keys()
1416 a8083063 Iustin Pop
    sortedcmds.sort()
1417 03298ebe Michael Hanselmann
1418 03298ebe Michael Hanselmann
    ToStdout("Usage: %s {command} [options...] [argument...]", binary)
1419 03298ebe Michael Hanselmann
    ToStdout("%s <command> --help to see details, or man %s", binary, binary)
1420 03298ebe Michael Hanselmann
    ToStdout("")
1421 03298ebe Michael Hanselmann
1422 a8083063 Iustin Pop
    # compute the max line length for cmd + usage
1423 4e713df6 Iustin Pop
    mlen = max([len(" %s" % cmd) for cmd in commands])
1424 a8083063 Iustin Pop
    mlen = min(60, mlen) # should not get here...
1425 03298ebe Michael Hanselmann
1426 a8083063 Iustin Pop
    # and format a nice command list
1427 03298ebe Michael Hanselmann
    ToStdout("Commands:")
1428 a8083063 Iustin Pop
    for cmd in sortedcmds:
1429 4e713df6 Iustin Pop
      cmdstr = " %s" % (cmd,)
1430 9a033156 Iustin Pop
      help_text = commands[cmd][4]
1431 03298ebe Michael Hanselmann
      help_lines = textwrap.wrap(help_text, 79 - 3 - mlen)
1432 03298ebe Michael Hanselmann
      ToStdout("%-*s - %s", mlen, cmdstr, help_lines.pop(0))
1433 a8083063 Iustin Pop
      for line in help_lines:
1434 03298ebe Michael Hanselmann
        ToStdout("%-*s   %s", mlen, "", line)
1435 03298ebe Michael Hanselmann
1436 03298ebe Michael Hanselmann
    ToStdout("")
1437 03298ebe Michael Hanselmann
1438 a8083063 Iustin Pop
    return None, None, None
1439 de47cf8f Guido Trotter
1440 de47cf8f Guido Trotter
  # get command, unalias it, and look it up in commands
1441 a8083063 Iustin Pop
  cmd = argv.pop(1)
1442 de47cf8f Guido Trotter
  if cmd in aliases:
1443 de47cf8f Guido Trotter
    if cmd in commands:
1444 de47cf8f Guido Trotter
      raise errors.ProgrammerError("Alias '%s' overrides an existing"
1445 de47cf8f Guido Trotter
                                   " command" % cmd)
1446 de47cf8f Guido Trotter
1447 de47cf8f Guido Trotter
    if aliases[cmd] not in commands:
1448 de47cf8f Guido Trotter
      raise errors.ProgrammerError("Alias '%s' maps to non-existing"
1449 de47cf8f Guido Trotter
                                   " command '%s'" % (cmd, aliases[cmd]))
1450 de47cf8f Guido Trotter
1451 de47cf8f Guido Trotter
    cmd = aliases[cmd]
1452 de47cf8f Guido Trotter
1453 ef9fa5b9 René Nussbaumer
  if cmd in env_override:
1454 ef9fa5b9 René Nussbaumer
    args_env_name = ("%s_%s" % (binary.replace("-", "_"), cmd)).upper()
1455 ef9fa5b9 René Nussbaumer
    env_args = os.environ.get(args_env_name)
1456 ef9fa5b9 René Nussbaumer
    if env_args:
1457 ef9fa5b9 René Nussbaumer
      argv = utils.InsertAtPos(argv, 1, shlex.split(env_args))
1458 ef9fa5b9 René Nussbaumer
1459 a8005e17 Michael Hanselmann
  func, args_def, parser_opts, usage, description = commands[cmd]
1460 5786c087 Michael Hanselmann
  parser = OptionParser(option_list=parser_opts + COMMON_OPTS,
1461 a8083063 Iustin Pop
                        description=description,
1462 a8083063 Iustin Pop
                        formatter=TitledHelpFormatter(),
1463 a8083063 Iustin Pop
                        usage="%%prog %s %s" % (cmd, usage))
1464 a8083063 Iustin Pop
  parser.disable_interspersed_args()
1465 ef9fa5b9 René Nussbaumer
  options, args = parser.parse_args(args=argv[1:])
1466 a8005e17 Michael Hanselmann
1467 a8005e17 Michael Hanselmann
  if not _CheckArguments(cmd, args_def, args):
1468 a8083063 Iustin Pop
    return None, None, None
1469 a8083063 Iustin Pop
1470 a8083063 Iustin Pop
  return func, options, args
1471 a8083063 Iustin Pop
1472 a8083063 Iustin Pop
1473 a8005e17 Michael Hanselmann
def _CheckArguments(cmd, args_def, args):
1474 a8005e17 Michael Hanselmann
  """Verifies the arguments using the argument definition.
1475 a8005e17 Michael Hanselmann

1476 a8005e17 Michael Hanselmann
  Algorithm:
1477 a8005e17 Michael Hanselmann

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

1480 a8005e17 Michael Hanselmann
    1. For each argument in definition
1481 a8005e17 Michael Hanselmann

1482 a8005e17 Michael Hanselmann
      1. Keep running count of minimum number of values (min_count)
1483 a8005e17 Michael Hanselmann
      1. Keep running count of maximum number of values (max_count)
1484 a8005e17 Michael Hanselmann
      1. If it has an unlimited number of values
1485 a8005e17 Michael Hanselmann

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

1488 a8005e17 Michael Hanselmann
    1. If last argument has limited number of values
1489 a8005e17 Michael Hanselmann

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

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

1494 a8005e17 Michael Hanselmann
  """
1495 a8005e17 Michael Hanselmann
  if args and not args_def:
1496 a8005e17 Michael Hanselmann
    ToStderr("Error: Command %s expects no arguments", cmd)
1497 a8005e17 Michael Hanselmann
    return False
1498 a8005e17 Michael Hanselmann
1499 a8005e17 Michael Hanselmann
  min_count = None
1500 a8005e17 Michael Hanselmann
  max_count = None
1501 a8005e17 Michael Hanselmann
  check_max = None
1502 a8005e17 Michael Hanselmann
1503 a8005e17 Michael Hanselmann
  last_idx = len(args_def) - 1
1504 a8005e17 Michael Hanselmann
1505 a8005e17 Michael Hanselmann
  for idx, arg in enumerate(args_def):
1506 a8005e17 Michael Hanselmann
    if min_count is None:
1507 a8005e17 Michael Hanselmann
      min_count = arg.min
1508 a8005e17 Michael Hanselmann
    elif arg.min is not None:
1509 a8005e17 Michael Hanselmann
      min_count += arg.min
1510 a8005e17 Michael Hanselmann
1511 a8005e17 Michael Hanselmann
    if max_count is None:
1512 a8005e17 Michael Hanselmann
      max_count = arg.max
1513 a8005e17 Michael Hanselmann
    elif arg.max is not None:
1514 a8005e17 Michael Hanselmann
      max_count += arg.max
1515 a8005e17 Michael Hanselmann
1516 a8005e17 Michael Hanselmann
    if idx == last_idx:
1517 a8005e17 Michael Hanselmann
      check_max = (arg.max is not None)
1518 a8005e17 Michael Hanselmann
1519 a8005e17 Michael Hanselmann
    elif arg.max is None:
1520 a8005e17 Michael Hanselmann
      raise errors.ProgrammerError("Only the last argument can have max=None")
1521 a8005e17 Michael Hanselmann
1522 a8005e17 Michael Hanselmann
  if check_max:
1523 a8005e17 Michael Hanselmann
    # Command with exact number of arguments
1524 a8005e17 Michael Hanselmann
    if (min_count is not None and max_count is not None and
1525 a8005e17 Michael Hanselmann
        min_count == max_count and len(args) != min_count):
1526 a8005e17 Michael Hanselmann
      ToStderr("Error: Command %s expects %d argument(s)", cmd, min_count)
1527 a8005e17 Michael Hanselmann
      return False
1528 a8005e17 Michael Hanselmann
1529 a8005e17 Michael Hanselmann
    # Command with limited number of arguments
1530 a8005e17 Michael Hanselmann
    if max_count is not None and len(args) > max_count:
1531 a8005e17 Michael Hanselmann
      ToStderr("Error: Command %s expects only %d argument(s)",
1532 a8005e17 Michael Hanselmann
               cmd, max_count)
1533 a8005e17 Michael Hanselmann
      return False
1534 a8005e17 Michael Hanselmann
1535 a8005e17 Michael Hanselmann
  # Command with some required arguments
1536 a8005e17 Michael Hanselmann
  if min_count is not None and len(args) < min_count:
1537 a8005e17 Michael Hanselmann
    ToStderr("Error: Command %s expects at least %d argument(s)",
1538 a8005e17 Michael Hanselmann
             cmd, min_count)
1539 a8005e17 Michael Hanselmann
    return False
1540 a8005e17 Michael Hanselmann
1541 a8005e17 Michael Hanselmann
  return True
1542 a8005e17 Michael Hanselmann
1543 a8005e17 Michael Hanselmann
1544 60d49723 Michael Hanselmann
def SplitNodeOption(value):
1545 60d49723 Michael Hanselmann
  """Splits the value of a --node option.
1546 60d49723 Michael Hanselmann

1547 60d49723 Michael Hanselmann
  """
1548 d0c8c01d Iustin Pop
  if value and ":" in value:
1549 d0c8c01d Iustin Pop
    return value.split(":", 1)
1550 60d49723 Michael Hanselmann
  else:
1551 60d49723 Michael Hanselmann
    return (value, None)
1552 60d49723 Michael Hanselmann
1553 60d49723 Michael Hanselmann
1554 07150497 Guido Trotter
def CalculateOSNames(os_name, os_variants):
1555 07150497 Guido Trotter
  """Calculates all the names an OS can be called, according to its variants.
1556 07150497 Guido Trotter

1557 07150497 Guido Trotter
  @type os_name: string
1558 07150497 Guido Trotter
  @param os_name: base name of the os
1559 07150497 Guido Trotter
  @type os_variants: list or None
1560 07150497 Guido Trotter
  @param os_variants: list of supported variants
1561 07150497 Guido Trotter
  @rtype: list
1562 07150497 Guido Trotter
  @return: list of valid names
1563 07150497 Guido Trotter

1564 07150497 Guido Trotter
  """
1565 07150497 Guido Trotter
  if os_variants:
1566 d0c8c01d Iustin Pop
    return ["%s+%s" % (os_name, v) for v in os_variants]
1567 07150497 Guido Trotter
  else:
1568 07150497 Guido Trotter
    return [os_name]
1569 07150497 Guido Trotter
1570 07150497 Guido Trotter
1571 a4ebd726 Michael Hanselmann
def ParseFields(selected, default):
1572 a4ebd726 Michael Hanselmann
  """Parses the values of "--field"-like options.
1573 a4ebd726 Michael Hanselmann

1574 a4ebd726 Michael Hanselmann
  @type selected: string or None
1575 a4ebd726 Michael Hanselmann
  @param selected: User-selected options
1576 a4ebd726 Michael Hanselmann
  @type default: list
1577 a4ebd726 Michael Hanselmann
  @param default: Default fields
1578 a4ebd726 Michael Hanselmann

1579 a4ebd726 Michael Hanselmann
  """
1580 a4ebd726 Michael Hanselmann
  if selected is None:
1581 a4ebd726 Michael Hanselmann
    return default
1582 a4ebd726 Michael Hanselmann
1583 a4ebd726 Michael Hanselmann
  if selected.startswith("+"):
1584 a4ebd726 Michael Hanselmann
    return default + selected[1:].split(",")
1585 a4ebd726 Michael Hanselmann
1586 a4ebd726 Michael Hanselmann
  return selected.split(",")
1587 a4ebd726 Michael Hanselmann
1588 a4ebd726 Michael Hanselmann
1589 e0e916fe Iustin Pop
UsesRPC = rpc.RunWithRPC
1590 4331f6cd Michael Hanselmann
1591 4331f6cd Michael Hanselmann
1592 47988778 Iustin Pop
def AskUser(text, choices=None):
1593 47988778 Iustin Pop
  """Ask the user a question.
1594 a8083063 Iustin Pop

1595 c41eea6e Iustin Pop
  @param text: the question to ask
1596 a8083063 Iustin Pop

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

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

1606 a8083063 Iustin Pop
  """
1607 47988778 Iustin Pop
  if choices is None:
1608 d0c8c01d Iustin Pop
    choices = [("y", True, "Perform the operation"),
1609 d0c8c01d Iustin Pop
               ("n", False, "Do not perform the operation")]
1610 47988778 Iustin Pop
  if not choices or not isinstance(choices, list):
1611 5bbd3f7f Michael Hanselmann
    raise errors.ProgrammerError("Invalid choices argument to AskUser")
1612 47988778 Iustin Pop
  for entry in choices:
1613 d0c8c01d Iustin Pop
    if not isinstance(entry, tuple) or len(entry) < 3 or entry[0] == "?":
1614 5bbd3f7f Michael Hanselmann
      raise errors.ProgrammerError("Invalid choices element to AskUser")
1615 47988778 Iustin Pop
1616 47988778 Iustin Pop
  answer = choices[-1][1]
1617 47988778 Iustin Pop
  new_text = []
1618 47988778 Iustin Pop
  for line in text.splitlines():
1619 47988778 Iustin Pop
    new_text.append(textwrap.fill(line, 70, replace_whitespace=False))
1620 47988778 Iustin Pop
  text = "\n".join(new_text)
1621 a8083063 Iustin Pop
  try:
1622 3023170f Iustin Pop
    f = file("/dev/tty", "a+")
1623 a8083063 Iustin Pop
  except IOError:
1624 47988778 Iustin Pop
    return answer
1625 a8083063 Iustin Pop
  try:
1626 47988778 Iustin Pop
    chars = [entry[0] for entry in choices]
1627 47988778 Iustin Pop
    chars[-1] = "[%s]" % chars[-1]
1628 d0c8c01d Iustin Pop
    chars.append("?")
1629 47988778 Iustin Pop
    maps = dict([(entry[0], entry[1]) for entry in choices])
1630 47988778 Iustin Pop
    while True:
1631 47988778 Iustin Pop
      f.write(text)
1632 d0c8c01d Iustin Pop
      f.write("\n")
1633 47988778 Iustin Pop
      f.write("/".join(chars))
1634 47988778 Iustin Pop
      f.write(": ")
1635 47988778 Iustin Pop
      line = f.readline(2).strip().lower()
1636 47988778 Iustin Pop
      if line in maps:
1637 47988778 Iustin Pop
        answer = maps[line]
1638 47988778 Iustin Pop
        break
1639 d0c8c01d Iustin Pop
      elif line == "?":
1640 47988778 Iustin Pop
        for entry in choices:
1641 47988778 Iustin Pop
          f.write(" %s - %s\n" % (entry[0], entry[2]))
1642 47988778 Iustin Pop
        f.write("\n")
1643 47988778 Iustin Pop
        continue
1644 a8083063 Iustin Pop
  finally:
1645 a8083063 Iustin Pop
    f.close()
1646 a8083063 Iustin Pop
  return answer
1647 a8083063 Iustin Pop
1648 a8083063 Iustin Pop
1649 e9d741b6 Iustin Pop
class JobSubmittedException(Exception):
1650 e9d741b6 Iustin Pop
  """Job was submitted, client should exit.
1651 e9d741b6 Iustin Pop

1652 e9d741b6 Iustin Pop
  This exception has one argument, the ID of the job that was
1653 e9d741b6 Iustin Pop
  submitted. The handler should print this ID.
1654 e9d741b6 Iustin Pop

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

1657 e9d741b6 Iustin Pop
  """
1658 e9d741b6 Iustin Pop
1659 e9d741b6 Iustin Pop
1660 0a1e74d9 Iustin Pop
def SendJob(ops, cl=None):
1661 0a1e74d9 Iustin Pop
  """Function to submit an opcode without waiting for the results.
1662 a8083063 Iustin Pop

1663 0a1e74d9 Iustin Pop
  @type ops: list
1664 0a1e74d9 Iustin Pop
  @param ops: list of opcodes
1665 0a1e74d9 Iustin Pop
  @type cl: luxi.Client
1666 0a1e74d9 Iustin Pop
  @param cl: the luxi client to use for communicating with the master;
1667 0a1e74d9 Iustin Pop
             if None, a new client will be created
1668 a8083063 Iustin Pop

1669 a8083063 Iustin Pop
  """
1670 e2212007 Iustin Pop
  if cl is None:
1671 b33e986b Iustin Pop
    cl = GetClient()
1672 685ee993 Iustin Pop
1673 0a1e74d9 Iustin Pop
  job_id = cl.SubmitJob(ops)
1674 0a1e74d9 Iustin Pop
1675 0a1e74d9 Iustin Pop
  return job_id
1676 0a1e74d9 Iustin Pop
1677 0a1e74d9 Iustin Pop
1678 4e338533 Michael Hanselmann
def GenericPollJob(job_id, cbs, report_cbs):
1679 4e338533 Michael Hanselmann
  """Generic job-polling function.
1680 0a1e74d9 Iustin Pop

1681 4e338533 Michael Hanselmann
  @type job_id: number
1682 4e338533 Michael Hanselmann
  @param job_id: Job ID
1683 4e338533 Michael Hanselmann
  @type cbs: Instance of L{JobPollCbBase}
1684 4e338533 Michael Hanselmann
  @param cbs: Data callbacks
1685 4e338533 Michael Hanselmann
  @type report_cbs: Instance of L{JobPollReportCbBase}
1686 4e338533 Michael Hanselmann
  @param report_cbs: Reporting callbacks
1687 0a1e74d9 Iustin Pop

1688 0a1e74d9 Iustin Pop
  """
1689 6c5a7090 Michael Hanselmann
  prev_job_info = None
1690 6c5a7090 Michael Hanselmann
  prev_logmsg_serial = None
1691 6c5a7090 Michael Hanselmann
1692 f4484122 Michael Hanselmann
  status = None
1693 f4484122 Michael Hanselmann
1694 685ee993 Iustin Pop
  while True:
1695 4e338533 Michael Hanselmann
    result = cbs.WaitForJobChangeOnce(job_id, ["status"], prev_job_info,
1696 4e338533 Michael Hanselmann
                                      prev_logmsg_serial)
1697 6c5a7090 Michael Hanselmann
    if not result:
1698 685ee993 Iustin Pop
      # job not found, go away!
1699 0bbe448c Michael Hanselmann
      raise errors.JobLost("Job with id %s lost" % job_id)
1700 4e338533 Michael Hanselmann
1701 4e338533 Michael Hanselmann
    if result == constants.JOB_NOTCHANGED:
1702 4e338533 Michael Hanselmann
      report_cbs.ReportNotChanged(job_id, status)
1703 f4484122 Michael Hanselmann
1704 f4484122 Michael Hanselmann
      # Wait again
1705 f4484122 Michael Hanselmann
      continue
1706 685ee993 Iustin Pop
1707 6c5a7090 Michael Hanselmann
    # Split result, a tuple of (field values, log entries)
1708 6c5a7090 Michael Hanselmann
    (job_info, log_entries) = result
1709 6c5a7090 Michael Hanselmann
    (status, ) = job_info
1710 6c5a7090 Michael Hanselmann
1711 6c5a7090 Michael Hanselmann
    if log_entries:
1712 6c5a7090 Michael Hanselmann
      for log_entry in log_entries:
1713 4e338533 Michael Hanselmann
        (serial, timestamp, log_type, message) = log_entry
1714 4e338533 Michael Hanselmann
        report_cbs.ReportLogMessage(job_id, serial, timestamp,
1715 4e338533 Michael Hanselmann
                                    log_type, message)
1716 6c5a7090 Michael Hanselmann
        prev_logmsg_serial = max(prev_logmsg_serial, serial)
1717 6c5a7090 Michael Hanselmann
1718 0bbe448c Michael Hanselmann
    # TODO: Handle canceled and archived jobs
1719 fbf0262f Michael Hanselmann
    elif status in (constants.JOB_STATUS_SUCCESS,
1720 fbf0262f Michael Hanselmann
                    constants.JOB_STATUS_ERROR,
1721 fbf0262f Michael Hanselmann
                    constants.JOB_STATUS_CANCELING,
1722 fbf0262f Michael Hanselmann
                    constants.JOB_STATUS_CANCELED):
1723 685ee993 Iustin Pop
      break
1724 6c5a7090 Michael Hanselmann
1725 6c5a7090 Michael Hanselmann
    prev_job_info = job_info
1726 685ee993 Iustin Pop
1727 4e338533 Michael Hanselmann
  jobs = cbs.QueryJobs([job_id], ["status", "opstatus", "opresult"])
1728 0bbe448c Michael Hanselmann
  if not jobs:
1729 0bbe448c Michael Hanselmann
    raise errors.JobLost("Job with id %s lost" % job_id)
1730 685ee993 Iustin Pop
1731 0e050889 Iustin Pop
  status, opstatus, result = jobs[0]
1732 4e338533 Michael Hanselmann
1733 0bbe448c Michael Hanselmann
  if status == constants.JOB_STATUS_SUCCESS:
1734 53c04d04 Iustin Pop
    return result
1735 4e338533 Michael Hanselmann
1736 4e338533 Michael Hanselmann
  if status in (constants.JOB_STATUS_CANCELING, constants.JOB_STATUS_CANCELED):
1737 fbf0262f Michael Hanselmann
    raise errors.OpExecError("Job was canceled")
1738 4e338533 Michael Hanselmann
1739 4e338533 Michael Hanselmann
  has_ok = False
1740 4e338533 Michael Hanselmann
  for idx, (status, msg) in enumerate(zip(opstatus, result)):
1741 4e338533 Michael Hanselmann
    if status == constants.OP_STATUS_SUCCESS:
1742 4e338533 Michael Hanselmann
      has_ok = True
1743 4e338533 Michael Hanselmann
    elif status == constants.OP_STATUS_ERROR:
1744 4e338533 Michael Hanselmann
      errors.MaybeRaise(msg)
1745 4e338533 Michael Hanselmann
1746 4e338533 Michael Hanselmann
      if has_ok:
1747 4e338533 Michael Hanselmann
        raise errors.OpExecError("partial failure (opcode %d): %s" %
1748 4e338533 Michael Hanselmann
                                 (idx, msg))
1749 4e338533 Michael Hanselmann
1750 4e338533 Michael Hanselmann
      raise errors.OpExecError(str(msg))
1751 4e338533 Michael Hanselmann
1752 4e338533 Michael Hanselmann
  # default failure mode
1753 4e338533 Michael Hanselmann
  raise errors.OpExecError(result)
1754 4e338533 Michael Hanselmann
1755 4e338533 Michael Hanselmann
1756 4e338533 Michael Hanselmann
class JobPollCbBase:
1757 4e338533 Michael Hanselmann
  """Base class for L{GenericPollJob} callbacks.
1758 4e338533 Michael Hanselmann

1759 4e338533 Michael Hanselmann
  """
1760 4e338533 Michael Hanselmann
  def __init__(self):
1761 4e338533 Michael Hanselmann
    """Initializes this class.
1762 4e338533 Michael Hanselmann

1763 4e338533 Michael Hanselmann
    """
1764 4e338533 Michael Hanselmann
1765 4e338533 Michael Hanselmann
  def WaitForJobChangeOnce(self, job_id, fields,
1766 4e338533 Michael Hanselmann
                           prev_job_info, prev_log_serial):
1767 4e338533 Michael Hanselmann
    """Waits for changes on a job.
1768 4e338533 Michael Hanselmann

1769 4e338533 Michael Hanselmann
    """
1770 4e338533 Michael Hanselmann
    raise NotImplementedError()
1771 4e338533 Michael Hanselmann
1772 4e338533 Michael Hanselmann
  def QueryJobs(self, job_ids, fields):
1773 4e338533 Michael Hanselmann
    """Returns the selected fields for the selected job IDs.
1774 4e338533 Michael Hanselmann

1775 4e338533 Michael Hanselmann
    @type job_ids: list of numbers
1776 4e338533 Michael Hanselmann
    @param job_ids: Job IDs
1777 4e338533 Michael Hanselmann
    @type fields: list of strings
1778 4e338533 Michael Hanselmann
    @param fields: Fields
1779 4e338533 Michael Hanselmann

1780 4e338533 Michael Hanselmann
    """
1781 4e338533 Michael Hanselmann
    raise NotImplementedError()
1782 4e338533 Michael Hanselmann
1783 4e338533 Michael Hanselmann
1784 4e338533 Michael Hanselmann
class JobPollReportCbBase:
1785 4e338533 Michael Hanselmann
  """Base class for L{GenericPollJob} reporting callbacks.
1786 4e338533 Michael Hanselmann

1787 4e338533 Michael Hanselmann
  """
1788 4e338533 Michael Hanselmann
  def __init__(self):
1789 4e338533 Michael Hanselmann
    """Initializes this class.
1790 4e338533 Michael Hanselmann

1791 4e338533 Michael Hanselmann
    """
1792 4e338533 Michael Hanselmann
1793 4e338533 Michael Hanselmann
  def ReportLogMessage(self, job_id, serial, timestamp, log_type, log_msg):
1794 4e338533 Michael Hanselmann
    """Handles a log message.
1795 4e338533 Michael Hanselmann

1796 4e338533 Michael Hanselmann
    """
1797 4e338533 Michael Hanselmann
    raise NotImplementedError()
1798 4e338533 Michael Hanselmann
1799 4e338533 Michael Hanselmann
  def ReportNotChanged(self, job_id, status):
1800 4e338533 Michael Hanselmann
    """Called for if a job hasn't changed in a while.
1801 4e338533 Michael Hanselmann

1802 4e338533 Michael Hanselmann
    @type job_id: number
1803 4e338533 Michael Hanselmann
    @param job_id: Job ID
1804 4e338533 Michael Hanselmann
    @type status: string or None
1805 4e338533 Michael Hanselmann
    @param status: Job status if available
1806 4e338533 Michael Hanselmann

1807 4e338533 Michael Hanselmann
    """
1808 4e338533 Michael Hanselmann
    raise NotImplementedError()
1809 4e338533 Michael Hanselmann
1810 4e338533 Michael Hanselmann
1811 4e338533 Michael Hanselmann
class _LuxiJobPollCb(JobPollCbBase):
1812 4e338533 Michael Hanselmann
  def __init__(self, cl):
1813 4e338533 Michael Hanselmann
    """Initializes this class.
1814 4e338533 Michael Hanselmann

1815 4e338533 Michael Hanselmann
    """
1816 4e338533 Michael Hanselmann
    JobPollCbBase.__init__(self)
1817 4e338533 Michael Hanselmann
    self.cl = cl
1818 4e338533 Michael Hanselmann
1819 4e338533 Michael Hanselmann
  def WaitForJobChangeOnce(self, job_id, fields,
1820 4e338533 Michael Hanselmann
                           prev_job_info, prev_log_serial):
1821 4e338533 Michael Hanselmann
    """Waits for changes on a job.
1822 4e338533 Michael Hanselmann

1823 4e338533 Michael Hanselmann
    """
1824 4e338533 Michael Hanselmann
    return self.cl.WaitForJobChangeOnce(job_id, fields,
1825 4e338533 Michael Hanselmann
                                        prev_job_info, prev_log_serial)
1826 4e338533 Michael Hanselmann
1827 4e338533 Michael Hanselmann
  def QueryJobs(self, job_ids, fields):
1828 4e338533 Michael Hanselmann
    """Returns the selected fields for the selected job IDs.
1829 4e338533 Michael Hanselmann

1830 4e338533 Michael Hanselmann
    """
1831 4e338533 Michael Hanselmann
    return self.cl.QueryJobs(job_ids, fields)
1832 4e338533 Michael Hanselmann
1833 4e338533 Michael Hanselmann
1834 4e338533 Michael Hanselmann
class FeedbackFnJobPollReportCb(JobPollReportCbBase):
1835 4e338533 Michael Hanselmann
  def __init__(self, feedback_fn):
1836 4e338533 Michael Hanselmann
    """Initializes this class.
1837 4e338533 Michael Hanselmann

1838 4e338533 Michael Hanselmann
    """
1839 4e338533 Michael Hanselmann
    JobPollReportCbBase.__init__(self)
1840 4e338533 Michael Hanselmann
1841 4e338533 Michael Hanselmann
    self.feedback_fn = feedback_fn
1842 4e338533 Michael Hanselmann
1843 4e338533 Michael Hanselmann
    assert callable(feedback_fn)
1844 4e338533 Michael Hanselmann
1845 4e338533 Michael Hanselmann
  def ReportLogMessage(self, job_id, serial, timestamp, log_type, log_msg):
1846 4e338533 Michael Hanselmann
    """Handles a log message.
1847 4e338533 Michael Hanselmann

1848 4e338533 Michael Hanselmann
    """
1849 4e338533 Michael Hanselmann
    self.feedback_fn((timestamp, log_type, log_msg))
1850 4e338533 Michael Hanselmann
1851 4e338533 Michael Hanselmann
  def ReportNotChanged(self, job_id, status):
1852 4e338533 Michael Hanselmann
    """Called if a job hasn't changed in a while.
1853 4e338533 Michael Hanselmann

1854 4e338533 Michael Hanselmann
    """
1855 4e338533 Michael Hanselmann
    # Ignore
1856 4e338533 Michael Hanselmann
1857 4e338533 Michael Hanselmann
1858 4e338533 Michael Hanselmann
class StdioJobPollReportCb(JobPollReportCbBase):
1859 4e338533 Michael Hanselmann
  def __init__(self):
1860 4e338533 Michael Hanselmann
    """Initializes this class.
1861 4e338533 Michael Hanselmann

1862 4e338533 Michael Hanselmann
    """
1863 4e338533 Michael Hanselmann
    JobPollReportCbBase.__init__(self)
1864 4e338533 Michael Hanselmann
1865 4e338533 Michael Hanselmann
    self.notified_queued = False
1866 4e338533 Michael Hanselmann
    self.notified_waitlock = False
1867 4e338533 Michael Hanselmann
1868 4e338533 Michael Hanselmann
  def ReportLogMessage(self, job_id, serial, timestamp, log_type, log_msg):
1869 4e338533 Michael Hanselmann
    """Handles a log message.
1870 4e338533 Michael Hanselmann

1871 4e338533 Michael Hanselmann
    """
1872 4e338533 Michael Hanselmann
    ToStdout("%s %s", time.ctime(utils.MergeTime(timestamp)),
1873 8a7f1c61 Michael Hanselmann
             FormatLogMessage(log_type, log_msg))
1874 4e338533 Michael Hanselmann
1875 4e338533 Michael Hanselmann
  def ReportNotChanged(self, job_id, status):
1876 4e338533 Michael Hanselmann
    """Called if a job hasn't changed in a while.
1877 4e338533 Michael Hanselmann

1878 4e338533 Michael Hanselmann
    """
1879 4e338533 Michael Hanselmann
    if status is None:
1880 4e338533 Michael Hanselmann
      return
1881 4e338533 Michael Hanselmann
1882 4e338533 Michael Hanselmann
    if status == constants.JOB_STATUS_QUEUED and not self.notified_queued:
1883 4e338533 Michael Hanselmann
      ToStderr("Job %s is waiting in queue", job_id)
1884 4e338533 Michael Hanselmann
      self.notified_queued = True
1885 4e338533 Michael Hanselmann
1886 47099cd1 Michael Hanselmann
    elif status == constants.JOB_STATUS_WAITING and not self.notified_waitlock:
1887 4e338533 Michael Hanselmann
      ToStderr("Job %s is trying to acquire all necessary locks", job_id)
1888 4e338533 Michael Hanselmann
      self.notified_waitlock = True
1889 4e338533 Michael Hanselmann
1890 4e338533 Michael Hanselmann
1891 8a7f1c61 Michael Hanselmann
def FormatLogMessage(log_type, log_msg):
1892 8a7f1c61 Michael Hanselmann
  """Formats a job message according to its type.
1893 8a7f1c61 Michael Hanselmann

1894 8a7f1c61 Michael Hanselmann
  """
1895 8a7f1c61 Michael Hanselmann
  if log_type != constants.ELOG_MESSAGE:
1896 8a7f1c61 Michael Hanselmann
    log_msg = str(log_msg)
1897 8a7f1c61 Michael Hanselmann
1898 8a7f1c61 Michael Hanselmann
  return utils.SafeEncode(log_msg)
1899 8a7f1c61 Michael Hanselmann
1900 8a7f1c61 Michael Hanselmann
1901 583163a6 Michael Hanselmann
def PollJob(job_id, cl=None, feedback_fn=None, reporter=None):
1902 4e338533 Michael Hanselmann
  """Function to poll for the result of a job.
1903 4e338533 Michael Hanselmann

1904 4e338533 Michael Hanselmann
  @type job_id: job identified
1905 4e338533 Michael Hanselmann
  @param job_id: the job to poll for results
1906 4e338533 Michael Hanselmann
  @type cl: luxi.Client
1907 4e338533 Michael Hanselmann
  @param cl: the luxi client to use for communicating with the master;
1908 4e338533 Michael Hanselmann
             if None, a new client will be created
1909 4e338533 Michael Hanselmann

1910 4e338533 Michael Hanselmann
  """
1911 4e338533 Michael Hanselmann
  if cl is None:
1912 4e338533 Michael Hanselmann
    cl = GetClient()
1913 4e338533 Michael Hanselmann
1914 583163a6 Michael Hanselmann
  if reporter is None:
1915 583163a6 Michael Hanselmann
    if feedback_fn:
1916 583163a6 Michael Hanselmann
      reporter = FeedbackFnJobPollReportCb(feedback_fn)
1917 583163a6 Michael Hanselmann
    else:
1918 583163a6 Michael Hanselmann
      reporter = StdioJobPollReportCb()
1919 583163a6 Michael Hanselmann
  elif feedback_fn:
1920 583163a6 Michael Hanselmann
    raise errors.ProgrammerError("Can't specify reporter and feedback function")
1921 4e338533 Michael Hanselmann
1922 4e338533 Michael Hanselmann
  return GenericPollJob(job_id, _LuxiJobPollCb(cl), reporter)
1923 ceab32dd Iustin Pop
1924 ceab32dd Iustin Pop
1925 583163a6 Michael Hanselmann
def SubmitOpCode(op, cl=None, feedback_fn=None, opts=None, reporter=None):
1926 0a1e74d9 Iustin Pop
  """Legacy function to submit an opcode.
1927 0a1e74d9 Iustin Pop

1928 0a1e74d9 Iustin Pop
  This is just a simple wrapper over the construction of the processor
1929 0a1e74d9 Iustin Pop
  instance. It should be extended to better handle feedback and
1930 0a1e74d9 Iustin Pop
  interaction functions.
1931 0a1e74d9 Iustin Pop

1932 0a1e74d9 Iustin Pop
  """
1933 0a1e74d9 Iustin Pop
  if cl is None:
1934 0a1e74d9 Iustin Pop
    cl = GetClient()
1935 0a1e74d9 Iustin Pop
1936 293ba2d8 Iustin Pop
  SetGenericOpcodeOpts([op], opts)
1937 293ba2d8 Iustin Pop
1938 5d297d8a Michael Hanselmann
  job_id = SendJob([op], cl=cl)
1939 0a1e74d9 Iustin Pop
1940 583163a6 Michael Hanselmann
  op_results = PollJob(job_id, cl=cl, feedback_fn=feedback_fn,
1941 583163a6 Michael Hanselmann
                       reporter=reporter)
1942 53c04d04 Iustin Pop
1943 53c04d04 Iustin Pop
  return op_results[0]
1944 0a1e74d9 Iustin Pop
1945 0a1e74d9 Iustin Pop
1946 94428652 Iustin Pop
def SubmitOrSend(op, opts, cl=None, feedback_fn=None):
1947 94428652 Iustin Pop
  """Wrapper around SubmitOpCode or SendJob.
1948 94428652 Iustin Pop

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

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

1957 94428652 Iustin Pop
  """
1958 94428652 Iustin Pop
  if opts and opts.submit_only:
1959 293ba2d8 Iustin Pop
    job = [op]
1960 293ba2d8 Iustin Pop
    SetGenericOpcodeOpts(job, opts)
1961 293ba2d8 Iustin Pop
    job_id = SendJob(job, cl=cl)
1962 e9d741b6 Iustin Pop
    raise JobSubmittedException(job_id)
1963 94428652 Iustin Pop
  else:
1964 293ba2d8 Iustin Pop
    return SubmitOpCode(op, cl=cl, feedback_fn=feedback_fn, opts=opts)
1965 293ba2d8 Iustin Pop
1966 293ba2d8 Iustin Pop
1967 293ba2d8 Iustin Pop
def SetGenericOpcodeOpts(opcode_list, options):
1968 293ba2d8 Iustin Pop
  """Processor for generic options.
1969 293ba2d8 Iustin Pop

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

1973 293ba2d8 Iustin Pop
  @param opcode_list: list of opcodes
1974 293ba2d8 Iustin Pop
  @param options: command line options or None
1975 293ba2d8 Iustin Pop
  @return: None (in-place modification)
1976 293ba2d8 Iustin Pop

1977 293ba2d8 Iustin Pop
  """
1978 293ba2d8 Iustin Pop
  if not options:
1979 293ba2d8 Iustin Pop
    return
1980 293ba2d8 Iustin Pop
  for op in opcode_list:
1981 aa06f8c6 Michael Hanselmann
    op.debug_level = options.debug
1982 a0a6ff34 Iustin Pop
    if hasattr(options, "dry_run"):
1983 a0a6ff34 Iustin Pop
      op.dry_run = options.dry_run
1984 aa06f8c6 Michael Hanselmann
    if getattr(options, "priority", None) is not None:
1985 aa06f8c6 Michael Hanselmann
      op.priority = _PRIONAME_TO_VALUE[options.priority]
1986 94428652 Iustin Pop
1987 94428652 Iustin Pop
1988 af30b2fd Michael Hanselmann
def GetClient():
1989 af30b2fd Michael Hanselmann
  # TODO: Cache object?
1990 b33e986b Iustin Pop
  try:
1991 b33e986b Iustin Pop
    client = luxi.Client()
1992 b33e986b Iustin Pop
  except luxi.NoMasterError:
1993 d9a51679 Michael Hanselmann
    ss = ssconf.SimpleStore()
1994 d9a51679 Michael Hanselmann
1995 d9a51679 Michael Hanselmann
    # Try to read ssconf file
1996 d9a51679 Michael Hanselmann
    try:
1997 d9a51679 Michael Hanselmann
      ss.GetMasterNode()
1998 d9a51679 Michael Hanselmann
    except errors.ConfigurationError:
1999 d9a51679 Michael Hanselmann
      raise errors.OpPrereqError("Cluster not initialized or this machine is"
2000 d9a51679 Michael Hanselmann
                                 " not part of a cluster")
2001 d9a51679 Michael Hanselmann
2002 d9a51679 Michael Hanselmann
    master, myself = ssconf.GetMasterAndMyself(ss=ss)
2003 b33e986b Iustin Pop
    if master != myself:
2004 b33e986b Iustin Pop
      raise errors.OpPrereqError("This is not the master node, please connect"
2005 b33e986b Iustin Pop
                                 " to node '%s' and rerun the command" %
2006 b33e986b Iustin Pop
                                 master)
2007 d9a51679 Michael Hanselmann
    raise
2008 b33e986b Iustin Pop
  return client
2009 af30b2fd Michael Hanselmann
2010 af30b2fd Michael Hanselmann
2011 73702ee7 Iustin Pop
def FormatError(err):
2012 73702ee7 Iustin Pop
  """Return a formatted error message for a given error.
2013 73702ee7 Iustin Pop

2014 73702ee7 Iustin Pop
  This function takes an exception instance and returns a tuple
2015 73702ee7 Iustin Pop
  consisting of two values: first, the recommended exit code, and
2016 73702ee7 Iustin Pop
  second, a string describing the error message (not
2017 73702ee7 Iustin Pop
  newline-terminated).
2018 73702ee7 Iustin Pop

2019 73702ee7 Iustin Pop
  """
2020 73702ee7 Iustin Pop
  retcode = 1
2021 73702ee7 Iustin Pop
  obuf = StringIO()
2022 e2e521d0 Iustin Pop
  msg = str(err)
2023 73702ee7 Iustin Pop
  if isinstance(err, errors.ConfigurationError):
2024 e2e521d0 Iustin Pop
    txt = "Corrupt configuration file: %s" % msg
2025 46fbdd04 Iustin Pop
    logging.error(txt)
2026 e2e521d0 Iustin Pop
    obuf.write(txt + "\n")
2027 73702ee7 Iustin Pop
    obuf.write("Aborting.")
2028 73702ee7 Iustin Pop
    retcode = 2
2029 73702ee7 Iustin Pop
  elif isinstance(err, errors.HooksAbort):
2030 73702ee7 Iustin Pop
    obuf.write("Failure: hooks execution failed:\n")
2031 73702ee7 Iustin Pop
    for node, script, out in err.args[0]:
2032 73702ee7 Iustin Pop
      if out:
2033 73702ee7 Iustin Pop
        obuf.write("  node: %s, script: %s, output: %s\n" %
2034 73702ee7 Iustin Pop
                   (node, script, out))
2035 73702ee7 Iustin Pop
      else:
2036 73702ee7 Iustin Pop
        obuf.write("  node: %s, script: %s (no output)\n" %
2037 73702ee7 Iustin Pop
                   (node, script))
2038 73702ee7 Iustin Pop
  elif isinstance(err, errors.HooksFailure):
2039 e2e521d0 Iustin Pop
    obuf.write("Failure: hooks general failure: %s" % msg)
2040 73702ee7 Iustin Pop
  elif isinstance(err, errors.ResolverError):
2041 b705c7a6 Manuel Franceschini
    this_host = netutils.Hostname.GetSysName()
2042 73702ee7 Iustin Pop
    if err.args[0] == this_host:
2043 73702ee7 Iustin Pop
      msg = "Failure: can't resolve my own hostname ('%s')"
2044 73702ee7 Iustin Pop
    else:
2045 73702ee7 Iustin Pop
      msg = "Failure: can't resolve hostname '%s'"
2046 73702ee7 Iustin Pop
    obuf.write(msg % err.args[0])
2047 73702ee7 Iustin Pop
  elif isinstance(err, errors.OpPrereqError):
2048 5c983ee5 Iustin Pop
    if len(err.args) == 2:
2049 5c983ee5 Iustin Pop
      obuf.write("Failure: prerequisites not met for this"
2050 5c983ee5 Iustin Pop
               " operation:\nerror type: %s, error details:\n%s" %
2051 5c983ee5 Iustin Pop
                 (err.args[1], err.args[0]))
2052 5c983ee5 Iustin Pop
    else:
2053 5c983ee5 Iustin Pop
      obuf.write("Failure: prerequisites not met for this"
2054 5c983ee5 Iustin Pop
                 " operation:\n%s" % msg)
2055 73702ee7 Iustin Pop
  elif isinstance(err, errors.OpExecError):
2056 e2e521d0 Iustin Pop
    obuf.write("Failure: command execution error:\n%s" % msg)
2057 73702ee7 Iustin Pop
  elif isinstance(err, errors.TagError):
2058 e2e521d0 Iustin Pop
    obuf.write("Failure: invalid tag(s) given:\n%s" % msg)
2059 686d7433 Iustin Pop
  elif isinstance(err, errors.JobQueueDrainError):
2060 686d7433 Iustin Pop
    obuf.write("Failure: the job queue is marked for drain and doesn't"
2061 686d7433 Iustin Pop
               " accept new requests\n")
2062 f87b405e Michael Hanselmann
  elif isinstance(err, errors.JobQueueFull):
2063 f87b405e Michael Hanselmann
    obuf.write("Failure: the job queue is full and doesn't accept new"
2064 f87b405e Michael Hanselmann
               " job submissions until old jobs are archived\n")
2065 a5728081 Guido Trotter
  elif isinstance(err, errors.TypeEnforcementError):
2066 a5728081 Guido Trotter
    obuf.write("Parameter Error: %s" % msg)
2067 c1ce76bb Iustin Pop
  elif isinstance(err, errors.ParameterError):
2068 c1ce76bb Iustin Pop
    obuf.write("Failure: unknown/wrong parameter name '%s'" % msg)
2069 03a8dbdc Iustin Pop
  elif isinstance(err, luxi.NoMasterError):
2070 03a8dbdc Iustin Pop
    obuf.write("Cannot communicate with the master daemon.\nIs it running"
2071 082c5adb Michael Hanselmann
               " and listening for connections?")
2072 03a8dbdc Iustin Pop
  elif isinstance(err, luxi.TimeoutError):
2073 cd4c86a8 Michael Hanselmann
    obuf.write("Timeout while talking to the master daemon. Jobs might have"
2074 cd4c86a8 Michael Hanselmann
               " been submitted and will continue to run even if the call"
2075 cd4c86a8 Michael Hanselmann
               " timed out. Useful commands in this situation are \"gnt-job"
2076 cd4c86a8 Michael Hanselmann
               " list\", \"gnt-job cancel\" and \"gnt-job watch\". Error:\n")
2077 cd4c86a8 Michael Hanselmann
    obuf.write(msg)
2078 5a1c22fe Iustin Pop
  elif isinstance(err, luxi.PermissionError):
2079 5a1c22fe Iustin Pop
    obuf.write("It seems you don't have permissions to connect to the"
2080 5a1c22fe Iustin Pop
               " master daemon.\nPlease retry as a different user.")
2081 03a8dbdc Iustin Pop
  elif isinstance(err, luxi.ProtocolError):
2082 03a8dbdc Iustin Pop
    obuf.write("Unhandled protocol error while talking to the master daemon:\n"
2083 03a8dbdc Iustin Pop
               "%s" % msg)
2084 91c622a8 Iustin Pop
  elif isinstance(err, errors.JobLost):
2085 91c622a8 Iustin Pop
    obuf.write("Error checking job status: %s" % msg)
2086 cb1e6c3c Michael Hanselmann
  elif isinstance(err, errors.QueryFilterParseError):
2087 cb1e6c3c Michael Hanselmann
    obuf.write("Error while parsing query filter: %s\n" % err.args[0])
2088 cb1e6c3c Michael Hanselmann
    obuf.write("\n".join(err.GetDetails()))
2089 797506fc Michael Hanselmann
  elif isinstance(err, errors.GenericError):
2090 797506fc Michael Hanselmann
    obuf.write("Unhandled Ganeti error: %s" % msg)
2091 e9d741b6 Iustin Pop
  elif isinstance(err, JobSubmittedException):
2092 e9d741b6 Iustin Pop
    obuf.write("JobID: %s\n" % err.args[0])
2093 e9d741b6 Iustin Pop
    retcode = 0
2094 73702ee7 Iustin Pop
  else:
2095 e2e521d0 Iustin Pop
    obuf.write("Unhandled exception: %s" % msg)
2096 d0c8c01d Iustin Pop
  return retcode, obuf.getvalue().rstrip("\n")
2097 73702ee7 Iustin Pop
2098 73702ee7 Iustin Pop
2099 ef9fa5b9 René Nussbaumer
def GenericMain(commands, override=None, aliases=None,
2100 ef9fa5b9 René Nussbaumer
                env_override=frozenset()):
2101 a8083063 Iustin Pop
  """Generic main function for all the gnt-* commands.
2102 a8083063 Iustin Pop

2103 ef9fa5b9 René Nussbaumer
  @param commands: a dictionary with a special structure, see the design doc
2104 ef9fa5b9 René Nussbaumer
                   for command line handling.
2105 ef9fa5b9 René Nussbaumer
  @param override: if not None, we expect a dictionary with keys that will
2106 ef9fa5b9 René Nussbaumer
                   override command line options; this can be used to pass
2107 ef9fa5b9 René Nussbaumer
                   options from the scripts to generic functions
2108 ef9fa5b9 René Nussbaumer
  @param aliases: dictionary with command aliases {'alias': 'target, ...}
2109 ef9fa5b9 René Nussbaumer
  @param env_override: list of environment names which are allowed to submit
2110 ef9fa5b9 René Nussbaumer
                       default args for commands
2111 a8083063 Iustin Pop

2112 a8083063 Iustin Pop
  """
2113 a8083063 Iustin Pop
  # save the program name and the entire command line for later logging
2114 a8083063 Iustin Pop
  if sys.argv:
2115 a8083063 Iustin Pop
    binary = os.path.basename(sys.argv[0]) or sys.argv[0]
2116 a8083063 Iustin Pop
    if len(sys.argv) >= 2:
2117 a8083063 Iustin Pop
      binary += " " + sys.argv[1]
2118 a8083063 Iustin Pop
      old_cmdline = " ".join(sys.argv[2:])
2119 a8083063 Iustin Pop
    else:
2120 a8083063 Iustin Pop
      old_cmdline = ""
2121 a8083063 Iustin Pop
  else:
2122 a8083063 Iustin Pop
    binary = "<unknown program>"
2123 a8083063 Iustin Pop
    old_cmdline = ""
2124 a8083063 Iustin Pop
2125 de47cf8f Guido Trotter
  if aliases is None:
2126 de47cf8f Guido Trotter
    aliases = {}
2127 de47cf8f Guido Trotter
2128 3126878d Guido Trotter
  try:
2129 ef9fa5b9 René Nussbaumer
    func, options, args = _ParseArgs(sys.argv, commands, aliases, env_override)
2130 3126878d Guido Trotter
  except errors.ParameterError, err:
2131 3126878d Guido Trotter
    result, err_msg = FormatError(err)
2132 3126878d Guido Trotter
    ToStderr(err_msg)
2133 3126878d Guido Trotter
    return 1
2134 3126878d Guido Trotter
2135 a8083063 Iustin Pop
  if func is None: # parse error
2136 a8083063 Iustin Pop
    return 1
2137 a8083063 Iustin Pop
2138 334d1483 Iustin Pop
  if override is not None:
2139 334d1483 Iustin Pop
    for key, val in override.iteritems():
2140 334d1483 Iustin Pop
      setattr(options, key, val)
2141 334d1483 Iustin Pop
2142 cfcc79c6 Michael Hanselmann
  utils.SetupLogging(constants.LOG_COMMANDS, binary, debug=options.debug,
2143 cfcc79c6 Michael Hanselmann
                     stderr_logging=True)
2144 a8083063 Iustin Pop
2145 a8083063 Iustin Pop
  if old_cmdline:
2146 46fbdd04 Iustin Pop
    logging.info("run with arguments '%s'", old_cmdline)
2147 a8083063 Iustin Pop
  else:
2148 46fbdd04 Iustin Pop
    logging.info("run with no arguments")
2149 a8083063 Iustin Pop
2150 a8083063 Iustin Pop
  try:
2151 a4af651e Iustin Pop
    result = func(options, args)
2152 d8353c3a Iustin Pop
  except (errors.GenericError, luxi.ProtocolError,
2153 d8353c3a Iustin Pop
          JobSubmittedException), err:
2154 a4af651e Iustin Pop
    result, err_msg = FormatError(err)
2155 5bbd3f7f Michael Hanselmann
    logging.exception("Error during command processing")
2156 46fbdd04 Iustin Pop
    ToStderr(err_msg)
2157 8a53b55f Iustin Pop
  except KeyboardInterrupt:
2158 8a53b55f Iustin Pop
    result = constants.EXIT_FAILURE
2159 8a53b55f Iustin Pop
    ToStderr("Aborted. Note that if the operation created any jobs, they"
2160 8a53b55f Iustin Pop
             " might have been submitted and"
2161 8a53b55f Iustin Pop
             " will continue to run in the background.")
2162 225e2544 Iustin Pop
  except IOError, err:
2163 225e2544 Iustin Pop
    if err.errno == errno.EPIPE:
2164 225e2544 Iustin Pop
      # our terminal went away, we'll exit
2165 225e2544 Iustin Pop
      sys.exit(constants.EXIT_FAILURE)
2166 225e2544 Iustin Pop
    else:
2167 225e2544 Iustin Pop
      raise
2168 a8083063 Iustin Pop
2169 a8083063 Iustin Pop
  return result
2170 137161c9 Michael Hanselmann
2171 137161c9 Michael Hanselmann
2172 845c79d8 Michael Hanselmann
def ParseNicOption(optvalue):
2173 845c79d8 Michael Hanselmann
  """Parses the value of the --net option(s).
2174 845c79d8 Michael Hanselmann

2175 845c79d8 Michael Hanselmann
  """
2176 845c79d8 Michael Hanselmann
  try:
2177 845c79d8 Michael Hanselmann
    nic_max = max(int(nidx[0]) + 1 for nidx in optvalue)
2178 845c79d8 Michael Hanselmann
  except (TypeError, ValueError), err:
2179 845c79d8 Michael Hanselmann
    raise errors.OpPrereqError("Invalid NIC index passed: %s" % str(err))
2180 845c79d8 Michael Hanselmann
2181 845c79d8 Michael Hanselmann
  nics = [{}] * nic_max
2182 845c79d8 Michael Hanselmann
  for nidx, ndict in optvalue:
2183 845c79d8 Michael Hanselmann
    nidx = int(nidx)
2184 845c79d8 Michael Hanselmann
2185 845c79d8 Michael Hanselmann
    if not isinstance(ndict, dict):
2186 845c79d8 Michael Hanselmann
      raise errors.OpPrereqError("Invalid nic/%d value: expected dict,"
2187 845c79d8 Michael Hanselmann
                                 " got %s" % (nidx, ndict))
2188 845c79d8 Michael Hanselmann
2189 845c79d8 Michael Hanselmann
    utils.ForceDictType(ndict, constants.INIC_PARAMS_TYPES)
2190 845c79d8 Michael Hanselmann
2191 845c79d8 Michael Hanselmann
    nics[nidx] = ndict
2192 845c79d8 Michael Hanselmann
2193 845c79d8 Michael Hanselmann
  return nics
2194 845c79d8 Michael Hanselmann
2195 845c79d8 Michael Hanselmann
2196 d77490c5 Iustin Pop
def GenericInstanceCreate(mode, opts, args):
2197 d77490c5 Iustin Pop
  """Add an instance to the cluster via either creation or import.
2198 d77490c5 Iustin Pop

2199 d77490c5 Iustin Pop
  @param mode: constants.INSTANCE_CREATE or constants.INSTANCE_IMPORT
2200 d77490c5 Iustin Pop
  @param opts: the command line options selected by the user
2201 d77490c5 Iustin Pop
  @type args: list
2202 d77490c5 Iustin Pop
  @param args: should contain only one element, the new instance name
2203 d77490c5 Iustin Pop
  @rtype: int
2204 d77490c5 Iustin Pop
  @return: the desired exit code
2205 d77490c5 Iustin Pop

2206 d77490c5 Iustin Pop
  """
2207 d77490c5 Iustin Pop
  instance = args[0]
2208 d77490c5 Iustin Pop
2209 d77490c5 Iustin Pop
  (pnode, snode) = SplitNodeOption(opts.node)
2210 d77490c5 Iustin Pop
2211 d77490c5 Iustin Pop
  hypervisor = None
2212 d77490c5 Iustin Pop
  hvparams = {}
2213 d77490c5 Iustin Pop
  if opts.hypervisor:
2214 d77490c5 Iustin Pop
    hypervisor, hvparams = opts.hypervisor
2215 d77490c5 Iustin Pop
2216 d77490c5 Iustin Pop
  if opts.nics:
2217 845c79d8 Michael Hanselmann
    nics = ParseNicOption(opts.nics)
2218 d77490c5 Iustin Pop
  elif opts.no_nics:
2219 d77490c5 Iustin Pop
    # no nics
2220 d77490c5 Iustin Pop
    nics = []
2221 0af0f641 Iustin Pop
  elif mode == constants.INSTANCE_CREATE:
2222 d77490c5 Iustin Pop
    # default of one nic, all auto
2223 d77490c5 Iustin Pop
    nics = [{}]
2224 0af0f641 Iustin Pop
  else:
2225 0af0f641 Iustin Pop
    # mode == import
2226 0af0f641 Iustin Pop
    nics = []
2227 d77490c5 Iustin Pop
2228 d77490c5 Iustin Pop
  if opts.disk_template == constants.DT_DISKLESS:
2229 d77490c5 Iustin Pop
    if opts.disks or opts.sd_size is not None:
2230 d77490c5 Iustin Pop
      raise errors.OpPrereqError("Diskless instance but disk"
2231 d77490c5 Iustin Pop
                                 " information passed")
2232 d77490c5 Iustin Pop
    disks = []
2233 d77490c5 Iustin Pop
  else:
2234 9b12ed0f Iustin Pop
    if (not opts.disks and not opts.sd_size
2235 9b12ed0f Iustin Pop
        and mode == constants.INSTANCE_CREATE):
2236 d77490c5 Iustin Pop
      raise errors.OpPrereqError("No disk information specified")
2237 d77490c5 Iustin Pop
    if opts.disks and opts.sd_size is not None:
2238 d77490c5 Iustin Pop
      raise errors.OpPrereqError("Please use either the '--disk' or"
2239 d77490c5 Iustin Pop
                                 " '-s' option")
2240 d77490c5 Iustin Pop
    if opts.sd_size is not None:
2241 ccfa86ba Michael Hanselmann
      opts.disks = [(0, {constants.IDISK_SIZE: opts.sd_size})]
2242 9b12ed0f Iustin Pop
2243 9b12ed0f Iustin Pop
    if opts.disks:
2244 9b12ed0f Iustin Pop
      try:
2245 9b12ed0f Iustin Pop
        disk_max = max(int(didx[0]) + 1 for didx in opts.disks)
2246 9b12ed0f Iustin Pop
      except ValueError, err:
2247 9b12ed0f Iustin Pop
        raise errors.OpPrereqError("Invalid disk index passed: %s" % str(err))
2248 9b12ed0f Iustin Pop
      disks = [{}] * disk_max
2249 9b12ed0f Iustin Pop
    else:
2250 9b12ed0f Iustin Pop
      disks = []
2251 d77490c5 Iustin Pop
    for didx, ddict in opts.disks:
2252 d77490c5 Iustin Pop
      didx = int(didx)
2253 d77490c5 Iustin Pop
      if not isinstance(ddict, dict):
2254 d77490c5 Iustin Pop
        msg = "Invalid disk/%d value: expected dict, got %s" % (didx, ddict)
2255 d77490c5 Iustin Pop
        raise errors.OpPrereqError(msg)
2256 ccfa86ba Michael Hanselmann
      elif constants.IDISK_SIZE in ddict:
2257 ccfa86ba Michael Hanselmann
        if constants.IDISK_ADOPT in ddict:
2258 5029db65 Iustin Pop
          raise errors.OpPrereqError("Only one of 'size' and 'adopt' allowed"
2259 5029db65 Iustin Pop
                                     " (disk %d)" % didx)
2260 5029db65 Iustin Pop
        try:
2261 ccfa86ba Michael Hanselmann
          ddict[constants.IDISK_SIZE] = \
2262 ccfa86ba Michael Hanselmann
            utils.ParseUnit(ddict[constants.IDISK_SIZE])
2263 5029db65 Iustin Pop
        except ValueError, err:
2264 5029db65 Iustin Pop
          raise errors.OpPrereqError("Invalid disk size for disk %d: %s" %
2265 5029db65 Iustin Pop
                                     (didx, err))
2266 ccfa86ba Michael Hanselmann
      elif constants.IDISK_ADOPT in ddict:
2267 5029db65 Iustin Pop
        if mode == constants.INSTANCE_IMPORT:
2268 5029db65 Iustin Pop
          raise errors.OpPrereqError("Disk adoption not allowed for instance"
2269 5029db65 Iustin Pop
                                     " import")
2270 ccfa86ba Michael Hanselmann
        ddict[constants.IDISK_SIZE] = 0
2271 5029db65 Iustin Pop
      else:
2272 5029db65 Iustin Pop
        raise errors.OpPrereqError("Missing size or adoption source for"
2273 5029db65 Iustin Pop
                                   " disk %d" % didx)
2274 d77490c5 Iustin Pop
      disks[didx] = ddict
2275 d77490c5 Iustin Pop
2276 a57981c5 Apollon Oikonomopoulos
  if opts.tags is not None:
2277 0f8810df Michael Hanselmann
    tags = opts.tags.split(",")
2278 a57981c5 Apollon Oikonomopoulos
  else:
2279 a57981c5 Apollon Oikonomopoulos
    tags = []
2280 a57981c5 Apollon Oikonomopoulos
2281 b2e233a5 Guido Trotter
  utils.ForceDictType(opts.beparams, constants.BES_PARAMETER_COMPAT)
2282 d77490c5 Iustin Pop
  utils.ForceDictType(hvparams, constants.HVS_PARAMETER_TYPES)
2283 d77490c5 Iustin Pop
2284 d77490c5 Iustin Pop
  if mode == constants.INSTANCE_CREATE:
2285 d77490c5 Iustin Pop
    start = opts.start
2286 d77490c5 Iustin Pop
    os_type = opts.os
2287 1ee8e01a Guido Trotter
    force_variant = opts.force_variant
2288 d77490c5 Iustin Pop
    src_node = None
2289 d77490c5 Iustin Pop
    src_path = None
2290 25a8792c Iustin Pop
    no_install = opts.no_install
2291 e588764d Iustin Pop
    identify_defaults = False
2292 d77490c5 Iustin Pop
  elif mode == constants.INSTANCE_IMPORT:
2293 d77490c5 Iustin Pop
    start = False
2294 d77490c5 Iustin Pop
    os_type = None
2295 1ee8e01a Guido Trotter
    force_variant = False
2296 d77490c5 Iustin Pop
    src_node = opts.src_node
2297 d77490c5 Iustin Pop
    src_path = opts.src_dir
2298 25a8792c Iustin Pop
    no_install = None
2299 e588764d Iustin Pop
    identify_defaults = opts.identify_defaults
2300 d77490c5 Iustin Pop
  else:
2301 d77490c5 Iustin Pop
    raise errors.ProgrammerError("Invalid creation mode %s" % mode)
2302 d77490c5 Iustin Pop
2303 e1530b10 Iustin Pop
  op = opcodes.OpInstanceCreate(instance_name=instance,
2304 d77490c5 Iustin Pop
                                disks=disks,
2305 d77490c5 Iustin Pop
                                disk_template=opts.disk_template,
2306 d77490c5 Iustin Pop
                                nics=nics,
2307 d77490c5 Iustin Pop
                                pnode=pnode, snode=snode,
2308 d77490c5 Iustin Pop
                                ip_check=opts.ip_check,
2309 460d22be Iustin Pop
                                name_check=opts.name_check,
2310 d77490c5 Iustin Pop
                                wait_for_sync=opts.wait_for_sync,
2311 d77490c5 Iustin Pop
                                file_storage_dir=opts.file_storage_dir,
2312 d77490c5 Iustin Pop
                                file_driver=opts.file_driver,
2313 d77490c5 Iustin Pop
                                iallocator=opts.iallocator,
2314 d77490c5 Iustin Pop
                                hypervisor=hypervisor,
2315 d77490c5 Iustin Pop
                                hvparams=hvparams,
2316 d77490c5 Iustin Pop
                                beparams=opts.beparams,
2317 062a7100 Iustin Pop
                                osparams=opts.osparams,
2318 d77490c5 Iustin Pop
                                mode=mode,
2319 d77490c5 Iustin Pop
                                start=start,
2320 d77490c5 Iustin Pop
                                os_type=os_type,
2321 1ee8e01a Guido Trotter
                                force_variant=force_variant,
2322 d77490c5 Iustin Pop
                                src_node=src_node,
2323 25a8792c Iustin Pop
                                src_path=src_path,
2324 a57981c5 Apollon Oikonomopoulos
                                tags=tags,
2325 e588764d Iustin Pop
                                no_install=no_install,
2326 10889e0c René Nussbaumer
                                identify_defaults=identify_defaults,
2327 10889e0c René Nussbaumer
                                ignore_ipolicy=opts.ignore_ipolicy)
2328 d77490c5 Iustin Pop
2329 d77490c5 Iustin Pop
  SubmitOrSend(op, opts)
2330 d77490c5 Iustin Pop
  return 0
2331 d77490c5 Iustin Pop
2332 d77490c5 Iustin Pop
2333 7e49b6ce Michael Hanselmann
class _RunWhileClusterStoppedHelper:
2334 7e49b6ce Michael Hanselmann
  """Helper class for L{RunWhileClusterStopped} to simplify state management
2335 7e49b6ce Michael Hanselmann

2336 7e49b6ce Michael Hanselmann
  """
2337 7e49b6ce Michael Hanselmann
  def __init__(self, feedback_fn, cluster_name, master_node, online_nodes):
2338 7e49b6ce Michael Hanselmann
    """Initializes this class.
2339 7e49b6ce Michael Hanselmann

2340 7e49b6ce Michael Hanselmann
    @type feedback_fn: callable
2341 7e49b6ce Michael Hanselmann
    @param feedback_fn: Feedback function
2342 7e49b6ce Michael Hanselmann
    @type cluster_name: string
2343 7e49b6ce Michael Hanselmann
    @param cluster_name: Cluster name
2344 7e49b6ce Michael Hanselmann
    @type master_node: string
2345 7e49b6ce Michael Hanselmann
    @param master_node Master node name
2346 7e49b6ce Michael Hanselmann
    @type online_nodes: list
2347 7e49b6ce Michael Hanselmann
    @param online_nodes: List of names of online nodes
2348 7e49b6ce Michael Hanselmann

2349 7e49b6ce Michael Hanselmann
    """
2350 7e49b6ce Michael Hanselmann
    self.feedback_fn = feedback_fn
2351 7e49b6ce Michael Hanselmann
    self.cluster_name = cluster_name
2352 7e49b6ce Michael Hanselmann
    self.master_node = master_node
2353 7e49b6ce Michael Hanselmann
    self.online_nodes = online_nodes
2354 7e49b6ce Michael Hanselmann
2355 7e49b6ce Michael Hanselmann
    self.ssh = ssh.SshRunner(self.cluster_name)
2356 7e49b6ce Michael Hanselmann
2357 7e49b6ce Michael Hanselmann
    self.nonmaster_nodes = [name for name in online_nodes
2358 7e49b6ce Michael Hanselmann
                            if name != master_node]
2359 7e49b6ce Michael Hanselmann
2360 7e49b6ce Michael Hanselmann
    assert self.master_node not in self.nonmaster_nodes
2361 7e49b6ce Michael Hanselmann
2362 7e49b6ce Michael Hanselmann
  def _RunCmd(self, node_name, cmd):
2363 7e49b6ce Michael Hanselmann
    """Runs a command on the local or a remote machine.
2364 7e49b6ce Michael Hanselmann

2365 7e49b6ce Michael Hanselmann
    @type node_name: string
2366 7e49b6ce Michael Hanselmann
    @param node_name: Machine name
2367 7e49b6ce Michael Hanselmann
    @type cmd: list
2368 7e49b6ce Michael Hanselmann
    @param cmd: Command
2369 7e49b6ce Michael Hanselmann

2370 7e49b6ce Michael Hanselmann
    """
2371 7e49b6ce Michael Hanselmann
    if node_name is None or node_name == self.master_node:
2372 7e49b6ce Michael Hanselmann
      # No need to use SSH
2373 7e49b6ce Michael Hanselmann
      result = utils.RunCmd(cmd)
2374 7e49b6ce Michael Hanselmann
    else:
2375 7e49b6ce Michael Hanselmann
      result = self.ssh.Run(node_name, "root", utils.ShellQuoteArgs(cmd))
2376 7e49b6ce Michael Hanselmann
2377 7e49b6ce Michael Hanselmann
    if result.failed:
2378 7e49b6ce Michael Hanselmann
      errmsg = ["Failed to run command %s" % result.cmd]
2379 7e49b6ce Michael Hanselmann
      if node_name:
2380 7e49b6ce Michael Hanselmann
        errmsg.append("on node %s" % node_name)
2381 7e49b6ce Michael Hanselmann
      errmsg.append(": exitcode %s and error %s" %
2382 7e49b6ce Michael Hanselmann
                    (result.exit_code, result.output))
2383 7e49b6ce Michael Hanselmann
      raise errors.OpExecError(" ".join(errmsg))
2384 7e49b6ce Michael Hanselmann
2385 7e49b6ce Michael Hanselmann
  def Call(self, fn, *args):
2386 7e49b6ce Michael Hanselmann
    """Call function while all daemons are stopped.
2387 7e49b6ce Michael Hanselmann

2388 7e49b6ce Michael Hanselmann
    @type fn: callable
2389 7e49b6ce Michael Hanselmann
    @param fn: Function to be called
2390 7e49b6ce Michael Hanselmann

2391 7e49b6ce Michael Hanselmann
    """
2392 7e49b6ce Michael Hanselmann
    # Pause watcher by acquiring an exclusive lock on watcher state file
2393 7e49b6ce Michael Hanselmann
    self.feedback_fn("Blocking watcher")
2394 16e0b9c9 Michael Hanselmann
    watcher_block = utils.FileLock.Open(constants.WATCHER_LOCK_FILE)
2395 7e49b6ce Michael Hanselmann
    try:
2396 7e49b6ce Michael Hanselmann
      # TODO: Currently, this just blocks. There's no timeout.
2397 7e49b6ce Michael Hanselmann
      # TODO: Should it be a shared lock?
2398 7e49b6ce Michael Hanselmann
      watcher_block.Exclusive(blocking=True)
2399 7e49b6ce Michael Hanselmann
2400 7e49b6ce Michael Hanselmann
      # Stop master daemons, so that no new jobs can come in and all running
2401 7e49b6ce Michael Hanselmann
      # ones are finished
2402 7e49b6ce Michael Hanselmann
      self.feedback_fn("Stopping master daemons")
2403 7e49b6ce Michael Hanselmann
      self._RunCmd(None, [constants.DAEMON_UTIL, "stop-master"])
2404 7e49b6ce Michael Hanselmann
      try:
2405 7e49b6ce Michael Hanselmann
        # Stop daemons on all nodes
2406 7e49b6ce Michael Hanselmann
        for node_name in self.online_nodes:
2407 7e49b6ce Michael Hanselmann
          self.feedback_fn("Stopping daemons on %s" % node_name)
2408 7e49b6ce Michael Hanselmann
          self._RunCmd(node_name, [constants.DAEMON_UTIL, "stop-all"])
2409 7e49b6ce Michael Hanselmann
2410 7e49b6ce Michael Hanselmann
        # All daemons are shut down now
2411 7e49b6ce Michael Hanselmann
        try:
2412 7e49b6ce Michael Hanselmann
          return fn(self, *args)
2413 d512e84b Michael Hanselmann
        except Exception, err:
2414 d512e84b Michael Hanselmann
          _, errmsg = FormatError(err)
2415 7e49b6ce Michael Hanselmann
          logging.exception("Caught exception")
2416 d512e84b Michael Hanselmann
          self.feedback_fn(errmsg)
2417 7e49b6ce Michael Hanselmann
          raise
2418 7e49b6ce Michael Hanselmann
      finally:
2419 7e49b6ce Michael Hanselmann
        # Start cluster again, master node last
2420 7e49b6ce Michael Hanselmann
        for node_name in self.nonmaster_nodes + [self.master_node]:
2421 7e49b6ce Michael Hanselmann
          self.feedback_fn("Starting daemons on %s" % node_name)
2422 7e49b6ce Michael Hanselmann
          self._RunCmd(node_name, [constants.DAEMON_UTIL, "start-all"])
2423 7e49b6ce Michael Hanselmann
    finally:
2424 7e49b6ce Michael Hanselmann
      # Resume watcher
2425 7e49b6ce Michael Hanselmann
      watcher_block.Close()
2426 7e49b6ce Michael Hanselmann
2427 7e49b6ce Michael Hanselmann
2428 7e49b6ce Michael Hanselmann
def RunWhileClusterStopped(feedback_fn, fn, *args):
2429 7e49b6ce Michael Hanselmann
  """Calls a function while all cluster daemons are stopped.
2430 7e49b6ce Michael Hanselmann

2431 7e49b6ce Michael Hanselmann
  @type feedback_fn: callable
2432 7e49b6ce Michael Hanselmann
  @param feedback_fn: Feedback function
2433 7e49b6ce Michael Hanselmann
  @type fn: callable
2434 7e49b6ce Michael Hanselmann
  @param fn: Function to be called when daemons are stopped
2435 7e49b6ce Michael Hanselmann

2436 7e49b6ce Michael Hanselmann
  """
2437 7e49b6ce Michael Hanselmann
  feedback_fn("Gathering cluster information")
2438 7e49b6ce Michael Hanselmann
2439 7e49b6ce Michael Hanselmann
  # This ensures we're running on the master daemon
2440 7e49b6ce Michael Hanselmann
  cl = GetClient()
2441 7e49b6ce Michael Hanselmann
2442 7e49b6ce Michael Hanselmann
  (cluster_name, master_node) = \
2443 7e49b6ce Michael Hanselmann
    cl.QueryConfigValues(["cluster_name", "master_node"])
2444 7e49b6ce Michael Hanselmann
2445 7e49b6ce Michael Hanselmann
  online_nodes = GetOnlineNodes([], cl=cl)
2446 7e49b6ce Michael Hanselmann
2447 7e49b6ce Michael Hanselmann
  # Don't keep a reference to the client. The master daemon will go away.
2448 7e49b6ce Michael Hanselmann
  del cl
2449 7e49b6ce Michael Hanselmann
2450 7e49b6ce Michael Hanselmann
  assert master_node in online_nodes
2451 7e49b6ce Michael Hanselmann
2452 7e49b6ce Michael Hanselmann
  return _RunWhileClusterStoppedHelper(feedback_fn, cluster_name, master_node,
2453 7e49b6ce Michael Hanselmann
                                       online_nodes).Call(fn, *args)
2454 7e49b6ce Michael Hanselmann
2455 7e49b6ce Michael Hanselmann
2456 16be8703 Iustin Pop
def GenerateTable(headers, fields, separator, data,
2457 9fbfbb7b Iustin Pop
                  numfields=None, unitfields=None,
2458 9fbfbb7b Iustin Pop
                  units=None):
2459 137161c9 Michael Hanselmann
  """Prints a table with headers and different fields.
2460 137161c9 Michael Hanselmann

2461 9fbfbb7b Iustin Pop
  @type headers: dict
2462 9fbfbb7b Iustin Pop
  @param headers: dictionary mapping field names to headers for
2463 9fbfbb7b Iustin Pop
      the table
2464 9fbfbb7b Iustin Pop
  @type fields: list
2465 9fbfbb7b Iustin Pop
  @param fields: the field names corresponding to each row in
2466 9fbfbb7b Iustin Pop
      the data field
2467 9fbfbb7b Iustin Pop
  @param separator: the separator to be used; if this is None,
2468 9fbfbb7b Iustin Pop
      the default 'smart' algorithm is used which computes optimal
2469 9fbfbb7b Iustin Pop
      field width, otherwise just the separator is used between
2470 9fbfbb7b Iustin Pop
      each field
2471 9fbfbb7b Iustin Pop
  @type data: list
2472 9fbfbb7b Iustin Pop
  @param data: a list of lists, each sublist being one row to be output
2473 9fbfbb7b Iustin Pop
  @type numfields: list
2474 9fbfbb7b Iustin Pop
  @param numfields: a list with the fields that hold numeric
2475 9fbfbb7b Iustin Pop
      values and thus should be right-aligned
2476 9fbfbb7b Iustin Pop
  @type unitfields: list
2477 9fbfbb7b Iustin Pop
  @param unitfields: a list with the fields that hold numeric
2478 9fbfbb7b Iustin Pop
      values that should be formatted with the units field
2479 9fbfbb7b Iustin Pop
  @type units: string or None
2480 9fbfbb7b Iustin Pop
  @param units: the units we should use for formatting, or None for
2481 9fbfbb7b Iustin Pop
      automatic choice (human-readable for non-separator usage, otherwise
2482 9fbfbb7b Iustin Pop
      megabytes); this is a one-letter string
2483 137161c9 Michael Hanselmann

2484 137161c9 Michael Hanselmann
  """
2485 9fbfbb7b Iustin Pop
  if units is None:
2486 9fbfbb7b Iustin Pop
    if separator:
2487 9fbfbb7b Iustin Pop
      units = "m"
2488 9fbfbb7b Iustin Pop
    else:
2489 9fbfbb7b Iustin Pop
      units = "h"
2490 9fbfbb7b Iustin Pop
2491 137161c9 Michael Hanselmann
  if numfields is None:
2492 137161c9 Michael Hanselmann
    numfields = []
2493 137161c9 Michael Hanselmann
  if unitfields is None:
2494 137161c9 Michael Hanselmann
    unitfields = []
2495 137161c9 Michael Hanselmann
2496 b459a848 Andrea Spadaccini
  numfields = utils.FieldSet(*numfields)   # pylint: disable=W0142
2497 b459a848 Andrea Spadaccini
  unitfields = utils.FieldSet(*unitfields) # pylint: disable=W0142
2498 00430f8e Iustin Pop
2499 137161c9 Michael Hanselmann
  format_fields = []
2500 137161c9 Michael Hanselmann
  for field in fields:
2501 01ca31ae Iustin Pop
    if headers and field not in headers:
2502 ea5a5b74 Guido Trotter
      # TODO: handle better unknown fields (either revert to old
2503 71c1af58 Iustin Pop
      # style of raising exception, or deal more intelligently with
2504 71c1af58 Iustin Pop
      # variable fields)
2505 71c1af58 Iustin Pop
      headers[field] = field
2506 137161c9 Michael Hanselmann
    if separator is not None:
2507 137161c9 Michael Hanselmann
      format_fields.append("%s")
2508 00430f8e Iustin Pop
    elif numfields.Matches(field):
2509 137161c9 Michael Hanselmann
      format_fields.append("%*s")
2510 137161c9 Michael Hanselmann
    else:
2511 137161c9 Michael Hanselmann
      format_fields.append("%-*s")
2512 137161c9 Michael Hanselmann
2513 137161c9 Michael Hanselmann
  if separator is None:
2514 137161c9 Michael Hanselmann
    mlens = [0 for name in fields]
2515 d0c8c01d Iustin Pop
    format_str = " ".join(format_fields)
2516 137161c9 Michael Hanselmann
  else:
2517 c04bc777 Iustin Pop
    format_str = separator.replace("%", "%%").join(format_fields)
2518 137161c9 Michael Hanselmann
2519 137161c9 Michael Hanselmann
  for row in data:
2520 dcbd6288 Guido Trotter
    if row is None:
2521 dcbd6288 Guido Trotter
      continue
2522 137161c9 Michael Hanselmann
    for idx, val in enumerate(row):
2523 00430f8e Iustin Pop
      if unitfields.Matches(fields[idx]):
2524 137161c9 Michael Hanselmann
        try:
2525 137161c9 Michael Hanselmann
          val = int(val)
2526 691744c4 Iustin Pop
        except (TypeError, ValueError):
2527 137161c9 Michael Hanselmann
          pass
2528 137161c9 Michael Hanselmann
        else:
2529 9fbfbb7b Iustin Pop
          val = row[idx] = utils.FormatUnit(val, units)
2530 01ca31ae Iustin Pop
      val = row[idx] = str(val)
2531 137161c9 Michael Hanselmann
      if separator is None:
2532 137161c9 Michael Hanselmann
        mlens[idx] = max(mlens[idx], len(val))
2533 137161c9 Michael Hanselmann
2534 16be8703 Iustin Pop
  result = []
2535 137161c9 Michael Hanselmann
  if headers:
2536 137161c9 Michael Hanselmann
    args = []
2537 137161c9 Michael Hanselmann
    for idx, name in enumerate(fields):
2538 137161c9 Michael Hanselmann
      hdr = headers[name]
2539 137161c9 Michael Hanselmann
      if separator is None:
2540 137161c9 Michael Hanselmann
        mlens[idx] = max(mlens[idx], len(hdr))
2541 137161c9 Michael Hanselmann
        args.append(mlens[idx])
2542 137161c9 Michael Hanselmann
      args.append(hdr)
2543 c04bc777 Iustin Pop
    result.append(format_str % tuple(args))
2544 137161c9 Michael Hanselmann
2545 ec39d63c Michael Hanselmann
  if separator is None:
2546 ec39d63c Michael Hanselmann
    assert len(mlens) == len(fields)
2547 ec39d63c Michael Hanselmann
2548 ec39d63c Michael Hanselmann
    if fields and not numfields.Matches(fields[-1]):
2549 ec39d63c Michael Hanselmann
      mlens[-1] = 0
2550 ec39d63c Michael Hanselmann
2551 137161c9 Michael Hanselmann
  for line in data:
2552 137161c9 Michael Hanselmann
    args = []
2553 dcbd6288 Guido Trotter
    if line is None:
2554 d0c8c01d Iustin Pop
      line = ["-" for _ in fields]
2555 f1501b3f Michael Hanselmann
    for idx in range(len(fields)):
2556 137161c9 Michael Hanselmann
      if separator is None:
2557 137161c9 Michael Hanselmann
        args.append(mlens[idx])
2558 137161c9 Michael Hanselmann
      args.append(line[idx])
2559 c04bc777 Iustin Pop
    result.append(format_str % tuple(args))
2560 16be8703 Iustin Pop
2561 16be8703 Iustin Pop
  return result
2562 3386e7a9 Iustin Pop
2563 3386e7a9 Iustin Pop
2564 ee3aedff Michael Hanselmann
def _FormatBool(value):
2565 ee3aedff Michael Hanselmann
  """Formats a boolean value as a string.
2566 ee3aedff Michael Hanselmann

2567 ee3aedff Michael Hanselmann
  """
2568 ee3aedff Michael Hanselmann
  if value:
2569 ee3aedff Michael Hanselmann
    return "Y"
2570 ee3aedff Michael Hanselmann
  return "N"
2571 ee3aedff Michael Hanselmann
2572 ee3aedff Michael Hanselmann
2573 ee3aedff Michael Hanselmann
#: Default formatting for query results; (callback, align right)
2574 ee3aedff Michael Hanselmann
_DEFAULT_FORMAT_QUERY = {
2575 ee3aedff Michael Hanselmann
  constants.QFT_TEXT: (str, False),
2576 ee3aedff Michael Hanselmann
  constants.QFT_BOOL: (_FormatBool, False),
2577 ee3aedff Michael Hanselmann
  constants.QFT_NUMBER: (str, True),
2578 ee3aedff Michael Hanselmann
  constants.QFT_TIMESTAMP: (utils.FormatTime, False),
2579 ee3aedff Michael Hanselmann
  constants.QFT_OTHER: (str, False),
2580 ee3aedff Michael Hanselmann
  constants.QFT_UNKNOWN: (str, False),
2581 ee3aedff Michael Hanselmann
  }
2582 ee3aedff Michael Hanselmann
2583 ee3aedff Michael Hanselmann
2584 ee3aedff Michael Hanselmann
def _GetColumnFormatter(fdef, override, unit):
2585 ee3aedff Michael Hanselmann
  """Returns formatting function for a field.
2586 ee3aedff Michael Hanselmann

2587 ee3aedff Michael Hanselmann
  @type fdef: L{objects.QueryFieldDefinition}
2588 ee3aedff Michael Hanselmann
  @type override: dict
2589 ee3aedff Michael Hanselmann
  @param override: Dictionary for overriding field formatting functions,
2590 ee3aedff Michael Hanselmann
    indexed by field name, contents like L{_DEFAULT_FORMAT_QUERY}
2591 ee3aedff Michael Hanselmann
  @type unit: string
2592 ee3aedff Michael Hanselmann
  @param unit: Unit used for formatting fields of type L{constants.QFT_UNIT}
2593 ee3aedff Michael Hanselmann
  @rtype: tuple; (callable, bool)
2594 ee3aedff Michael Hanselmann
  @return: Returns the function to format a value (takes one parameter) and a
2595 ee3aedff Michael Hanselmann
    boolean for aligning the value on the right-hand side
2596 ee3aedff Michael Hanselmann

2597 ee3aedff Michael Hanselmann
  """
2598 ee3aedff Michael Hanselmann
  fmt = override.get(fdef.name, None)
2599 ee3aedff Michael Hanselmann
  if fmt is not None:
2600 ee3aedff Michael Hanselmann
    return fmt
2601 ee3aedff Michael Hanselmann
2602 ee3aedff Michael Hanselmann
  assert constants.QFT_UNIT not in _DEFAULT_FORMAT_QUERY
2603 ee3aedff Michael Hanselmann
2604 ee3aedff Michael Hanselmann
  if fdef.kind == constants.QFT_UNIT:
2605 ee3aedff Michael Hanselmann
    # Can't keep this information in the static dictionary
2606 ee3aedff Michael Hanselmann
    return (lambda value: utils.FormatUnit(value, unit), True)
2607 ee3aedff Michael Hanselmann
2608 ee3aedff Michael Hanselmann
  fmt = _DEFAULT_FORMAT_QUERY.get(fdef.kind, None)
2609 ee3aedff Michael Hanselmann
  if fmt is not None:
2610 ee3aedff Michael Hanselmann
    return fmt
2611 ee3aedff Michael Hanselmann
2612 ee3aedff Michael Hanselmann
  raise NotImplementedError("Can't format column type '%s'" % fdef.kind)
2613 ee3aedff Michael Hanselmann
2614 ee3aedff Michael Hanselmann
2615 ee3aedff Michael Hanselmann
class _QueryColumnFormatter:
2616 ee3aedff Michael Hanselmann
  """Callable class for formatting fields of a query.
2617 ee3aedff Michael Hanselmann

2618 ee3aedff Michael Hanselmann
  """
2619 f0b1bafe Iustin Pop
  def __init__(self, fn, status_fn, verbose):
2620 ee3aedff Michael Hanselmann
    """Initializes this class.
2621 ee3aedff Michael Hanselmann

2622 ee3aedff Michael Hanselmann
    @type fn: callable
2623 ee3aedff Michael Hanselmann
    @param fn: Formatting function
2624 ee3aedff Michael Hanselmann
    @type status_fn: callable
2625 ee3aedff Michael Hanselmann
    @param status_fn: Function to report fields' status
2626 f0b1bafe Iustin Pop
    @type verbose: boolean
2627 f0b1bafe Iustin Pop
    @param verbose: whether to use verbose field descriptions or not
2628 ee3aedff Michael Hanselmann

2629 ee3aedff Michael Hanselmann
    """
2630 ee3aedff Michael Hanselmann
    self._fn = fn
2631 ee3aedff Michael Hanselmann
    self._status_fn = status_fn
2632 cbfa4f0f Michael Hanselmann
    self._verbose = verbose
2633 ee3aedff Michael Hanselmann
2634 ee3aedff Michael Hanselmann
  def __call__(self, data):
2635 ee3aedff Michael Hanselmann
    """Returns a field's string representation.
2636 ee3aedff Michael Hanselmann

2637 ee3aedff Michael Hanselmann
    """
2638 ee3aedff Michael Hanselmann
    (status, value) = data
2639 ee3aedff Michael Hanselmann
2640 ee3aedff Michael Hanselmann
    # Report status
2641 ee3aedff Michael Hanselmann
    self._status_fn(status)
2642 ee3aedff Michael Hanselmann
2643 cfb084ae René Nussbaumer
    if status == constants.RS_NORMAL:
2644 ee3aedff Michael Hanselmann
      return self._fn(value)
2645 ee3aedff Michael Hanselmann
2646 ee3aedff Michael Hanselmann
    assert value is None, \
2647 ee3aedff Michael Hanselmann
           "Found value %r for abnormal status %s" % (value, status)
2648 ee3aedff Michael Hanselmann
2649 f2c6673d Michael Hanselmann
    return FormatResultError(status, self._verbose)
2650 ee3aedff Michael Hanselmann
2651 ee3aedff Michael Hanselmann
2652 f2c6673d Michael Hanselmann
def FormatResultError(status, verbose):
2653 ae95e419 René Nussbaumer
  """Formats result status other than L{constants.RS_NORMAL}.
2654 ee3aedff Michael Hanselmann

2655 ae95e419 René Nussbaumer
  @param status: The result status
2656 f2c6673d Michael Hanselmann
  @type verbose: boolean
2657 f2c6673d Michael Hanselmann
  @param verbose: Whether to return the verbose text
2658 ae95e419 René Nussbaumer
  @return: Text of result status
2659 a6070ef7 Michael Hanselmann

2660 ae95e419 René Nussbaumer
  """
2661 ae95e419 René Nussbaumer
  assert status != constants.RS_NORMAL, \
2662 cbfa4f0f Michael Hanselmann
         "FormatResultError called with status equal to constants.RS_NORMAL"
2663 ae95e419 René Nussbaumer
  try:
2664 cbfa4f0f Michael Hanselmann
    (verbose_text, normal_text) = constants.RSS_DESCRIPTION[status]
2665 ae95e419 René Nussbaumer
  except KeyError:
2666 ee3aedff Michael Hanselmann
    raise NotImplementedError("Unknown status %s" % status)
2667 cbfa4f0f Michael Hanselmann
  else:
2668 cbfa4f0f Michael Hanselmann
    if verbose:
2669 cbfa4f0f Michael Hanselmann
      return verbose_text
2670 cbfa4f0f Michael Hanselmann
    return normal_text
2671 ee3aedff Michael Hanselmann
2672 ee3aedff Michael Hanselmann
2673 ee3aedff Michael Hanselmann
def FormatQueryResult(result, unit=None, format_override=None, separator=None,
2674 f0b1bafe Iustin Pop
                      header=False, verbose=False):
2675 ee3aedff Michael Hanselmann
  """Formats data in L{objects.QueryResponse}.
2676 ee3aedff Michael Hanselmann

2677 ee3aedff Michael Hanselmann
  @type result: L{objects.QueryResponse}
2678 ee3aedff Michael Hanselmann
  @param result: result of query operation
2679 ee3aedff Michael Hanselmann
  @type unit: string
2680 ee3aedff Michael Hanselmann
  @param unit: Unit used for formatting fields of type L{constants.QFT_UNIT},
2681 18009c1e Iustin Pop
    see L{utils.text.FormatUnit}
2682 ee3aedff Michael Hanselmann
  @type format_override: dict
2683 ee3aedff Michael Hanselmann
  @param format_override: Dictionary for overriding field formatting functions,
2684 ee3aedff Michael Hanselmann
    indexed by field name, contents like L{_DEFAULT_FORMAT_QUERY}
2685 ee3aedff Michael Hanselmann
  @type separator: string or None
2686 ee3aedff Michael Hanselmann
  @param separator: String used to separate fields
2687 ee3aedff Michael Hanselmann
  @type header: bool
2688 ee3aedff Michael Hanselmann
  @param header: Whether to output header row
2689 f0b1bafe Iustin Pop
  @type verbose: boolean
2690 f0b1bafe Iustin Pop
  @param verbose: whether to use verbose field descriptions or not
2691 ee3aedff Michael Hanselmann

2692 ee3aedff Michael Hanselmann
  """
2693 ee3aedff Michael Hanselmann
  if unit is None:
2694 ee3aedff Michael Hanselmann
    if separator:
2695 ee3aedff Michael Hanselmann
      unit = "m"
2696 ee3aedff Michael Hanselmann
    else:
2697 ee3aedff Michael Hanselmann
      unit = "h"
2698 ee3aedff Michael Hanselmann
2699 ee3aedff Michael Hanselmann
  if format_override is None:
2700 ee3aedff Michael Hanselmann
    format_override = {}
2701 ee3aedff Michael Hanselmann
2702 cfb084ae René Nussbaumer
  stats = dict.fromkeys(constants.RS_ALL, 0)
2703 ee3aedff Michael Hanselmann
2704 ee3aedff Michael Hanselmann
  def _RecordStatus(status):
2705 ee3aedff Michael Hanselmann
    if status in stats:
2706 ee3aedff Michael Hanselmann
      stats[status] += 1
2707 ee3aedff Michael Hanselmann
2708 ee3aedff Michael Hanselmann
  columns = []
2709 ee3aedff Michael Hanselmann
  for fdef in result.fields:
2710 ee3aedff Michael Hanselmann
    assert fdef.title and fdef.name
2711 ee3aedff Michael Hanselmann
    (fn, align_right) = _GetColumnFormatter(fdef, format_override, unit)
2712 ee3aedff Michael Hanselmann
    columns.append(TableColumn(fdef.title,
2713 f0b1bafe Iustin Pop
                               _QueryColumnFormatter(fn, _RecordStatus,
2714 f0b1bafe Iustin Pop
                                                     verbose),
2715 ee3aedff Michael Hanselmann
                               align_right))
2716 ee3aedff Michael Hanselmann
2717 ee3aedff Michael Hanselmann
  table = FormatTable(result.data, columns, header, separator)
2718 ee3aedff Michael Hanselmann
2719 ee3aedff Michael Hanselmann
  # Collect statistics
2720 cfb084ae René Nussbaumer
  assert len(stats) == len(constants.RS_ALL)
2721 ee3aedff Michael Hanselmann
  assert compat.all(count >= 0 for count in stats.values())
2722 ee3aedff Michael Hanselmann
2723 ee3aedff Michael Hanselmann
  # Determine overall status. If there was no data, unknown fields must be
2724 ee3aedff Michael Hanselmann
  # detected via the field definitions.
2725 cfb084ae René Nussbaumer
  if (stats[constants.RS_UNKNOWN] or
2726 ee3aedff Michael Hanselmann
      (not result.data and _GetUnknownFields(result.fields))):
2727 ee3aedff Michael Hanselmann
    status = QR_UNKNOWN
2728 ee3aedff Michael Hanselmann
  elif compat.any(count > 0 for key, count in stats.items()
2729 cfb084ae René Nussbaumer
                  if key != constants.RS_NORMAL):
2730 ee3aedff Michael Hanselmann
    status = QR_INCOMPLETE
2731 ee3aedff Michael Hanselmann
  else:
2732 ee3aedff Michael Hanselmann
    status = QR_NORMAL
2733 ee3aedff Michael Hanselmann
2734 ee3aedff Michael Hanselmann
  return (status, table)
2735 ee3aedff Michael Hanselmann
2736 ee3aedff Michael Hanselmann
2737 ee3aedff Michael Hanselmann
def _GetUnknownFields(fdefs):
2738 ee3aedff Michael Hanselmann
  """Returns list of unknown fields included in C{fdefs}.
2739 ee3aedff Michael Hanselmann

2740 ee3aedff Michael Hanselmann
  @type fdefs: list of L{objects.QueryFieldDefinition}
2741 ee3aedff Michael Hanselmann

2742 ee3aedff Michael Hanselmann
  """
2743 ee3aedff Michael Hanselmann
  return [fdef for fdef in fdefs
2744 ee3aedff Michael Hanselmann
          if fdef.kind == constants.QFT_UNKNOWN]
2745 ee3aedff Michael Hanselmann
2746 ee3aedff Michael Hanselmann
2747 ee3aedff Michael Hanselmann
def _WarnUnknownFields(fdefs):
2748 ee3aedff Michael Hanselmann
  """Prints a warning to stderr if a query included unknown fields.
2749 ee3aedff Michael Hanselmann

2750 ee3aedff Michael Hanselmann
  @type fdefs: list of L{objects.QueryFieldDefinition}
2751 ee3aedff Michael Hanselmann

2752 ee3aedff Michael Hanselmann
  """
2753 ee3aedff Michael Hanselmann
  unknown = _GetUnknownFields(fdefs)
2754 ee3aedff Michael Hanselmann
  if unknown:
2755 ee3aedff Michael Hanselmann
    ToStderr("Warning: Queried for unknown fields %s",
2756 ee3aedff Michael Hanselmann
             utils.CommaJoin(fdef.name for fdef in unknown))
2757 ee3aedff Michael Hanselmann
    return True
2758 ee3aedff Michael Hanselmann
2759 ee3aedff Michael Hanselmann
  return False
2760 ee3aedff Michael Hanselmann
2761 ee3aedff Michael Hanselmann
2762 ee3aedff Michael Hanselmann
def GenericList(resource, fields, names, unit, separator, header, cl=None,
2763 2928de47 Michael Hanselmann
                format_override=None, verbose=False, force_filter=False):
2764 ee3aedff Michael Hanselmann
  """Generic implementation for listing all items of a resource.
2765 ee3aedff Michael Hanselmann

2766 abd66bf8 Michael Hanselmann
  @param resource: One of L{constants.QR_VIA_LUXI}
2767 ee3aedff Michael Hanselmann
  @type fields: list of strings
2768 ee3aedff Michael Hanselmann
  @param fields: List of fields to query for
2769 ee3aedff Michael Hanselmann
  @type names: list of strings
2770 ee3aedff Michael Hanselmann
  @param names: Names of items to query for
2771 ee3aedff Michael Hanselmann
  @type unit: string or None
2772 ee3aedff Michael Hanselmann
  @param unit: Unit used for formatting fields of type L{constants.QFT_UNIT} or
2773 ee3aedff Michael Hanselmann
    None for automatic choice (human-readable for non-separator usage,
2774 ee3aedff Michael Hanselmann
    otherwise megabytes); this is a one-letter string
2775 ee3aedff Michael Hanselmann
  @type separator: string or None
2776 ee3aedff Michael Hanselmann
  @param separator: String used to separate fields
2777 ee3aedff Michael Hanselmann
  @type header: bool
2778 ee3aedff Michael Hanselmann
  @param header: Whether to show header row
2779 2928de47 Michael Hanselmann
  @type force_filter: bool
2780 2928de47 Michael Hanselmann
  @param force_filter: Whether to always treat names as filter
2781 ee3aedff Michael Hanselmann
  @type format_override: dict
2782 ee3aedff Michael Hanselmann
  @param format_override: Dictionary for overriding field formatting functions,
2783 ee3aedff Michael Hanselmann
    indexed by field name, contents like L{_DEFAULT_FORMAT_QUERY}
2784 f0b1bafe Iustin Pop
  @type verbose: boolean
2785 f0b1bafe Iustin Pop
  @param verbose: whether to use verbose field descriptions or not
2786 ee3aedff Michael Hanselmann

2787 ee3aedff Michael Hanselmann
  """
2788 ee3aedff Michael Hanselmann
  if not names:
2789 ee3aedff Michael Hanselmann
    names = None
2790 ee3aedff Michael Hanselmann
2791 2e5c33db Iustin Pop
  qfilter = qlang.MakeFilter(names, force_filter)
2792 2928de47 Michael Hanselmann
2793 727274dd Iustin Pop
  if cl is None:
2794 727274dd Iustin Pop
    cl = GetClient()
2795 727274dd Iustin Pop
2796 2e5c33db Iustin Pop
  response = cl.Query(resource, fields, qfilter)
2797 ee3aedff Michael Hanselmann
2798 ee3aedff Michael Hanselmann
  found_unknown = _WarnUnknownFields(response.fields)
2799 ee3aedff Michael Hanselmann
2800 ee3aedff Michael Hanselmann
  (status, data) = FormatQueryResult(response, unit=unit, separator=separator,
2801 ee3aedff Michael Hanselmann
                                     header=header,
2802 f0b1bafe Iustin Pop
                                     format_override=format_override,
2803 f0b1bafe Iustin Pop
                                     verbose=verbose)
2804 ee3aedff Michael Hanselmann
2805 ee3aedff Michael Hanselmann
  for line in data:
2806 ee3aedff Michael Hanselmann
    ToStdout(line)
2807 ee3aedff Michael Hanselmann
2808 ee3aedff Michael Hanselmann
  assert ((found_unknown and status == QR_UNKNOWN) or
2809 ee3aedff Michael Hanselmann
          (not found_unknown and status != QR_UNKNOWN))
2810 ee3aedff Michael Hanselmann
2811 ee3aedff Michael Hanselmann
  if status == QR_UNKNOWN:
2812 ee3aedff Michael Hanselmann
    return constants.EXIT_UNKNOWN_FIELD
2813 ee3aedff Michael Hanselmann
2814 ee3aedff Michael Hanselmann
  # TODO: Should the list command fail if not all data could be collected?
2815 ee3aedff Michael Hanselmann
  return constants.EXIT_SUCCESS
2816 ee3aedff Michael Hanselmann
2817 ee3aedff Michael Hanselmann
2818 ee3aedff Michael Hanselmann
def GenericListFields(resource, fields, separator, header, cl=None):
2819 ee3aedff Michael Hanselmann
  """Generic implementation for listing fields for a resource.
2820 ee3aedff Michael Hanselmann

2821 abd66bf8 Michael Hanselmann
  @param resource: One of L{constants.QR_VIA_LUXI}
2822 ee3aedff Michael Hanselmann
  @type fields: list of strings
2823 ee3aedff Michael Hanselmann
  @param fields: List of fields to query for
2824 ee3aedff Michael Hanselmann
  @type separator: string or None
2825 ee3aedff Michael Hanselmann
  @param separator: String used to separate fields
2826 ee3aedff Michael Hanselmann
  @type header: bool
2827 ee3aedff Michael Hanselmann
  @param header: Whether to show header row
2828 ee3aedff Michael Hanselmann

2829 ee3aedff Michael Hanselmann
  """
2830 ee3aedff Michael Hanselmann
  if cl is None:
2831 ee3aedff Michael Hanselmann
    cl = GetClient()
2832 ee3aedff Michael Hanselmann
2833 ee3aedff Michael Hanselmann
  if not fields:
2834 ee3aedff Michael Hanselmann
    fields = None
2835 ee3aedff Michael Hanselmann
2836 ee3aedff Michael Hanselmann
  response = cl.QueryFields(resource, fields)
2837 ee3aedff Michael Hanselmann
2838 ee3aedff Michael Hanselmann
  found_unknown = _WarnUnknownFields(response.fields)
2839 ee3aedff Michael Hanselmann
2840 ee3aedff Michael Hanselmann
  columns = [
2841 ee3aedff Michael Hanselmann
    TableColumn("Name", str, False),
2842 ee3aedff Michael Hanselmann
    TableColumn("Title", str, False),
2843 ea1440c1 Michael Hanselmann
    TableColumn("Description", str, False),
2844 ee3aedff Michael Hanselmann
    ]
2845 ee3aedff Michael Hanselmann
2846 ea1440c1 Michael Hanselmann
  rows = [[fdef.name, fdef.title, fdef.doc] for fdef in response.fields]
2847 ee3aedff Michael Hanselmann
2848 ee3aedff Michael Hanselmann
  for line in FormatTable(rows, columns, header, separator):
2849 ee3aedff Michael Hanselmann
    ToStdout(line)
2850 ee3aedff Michael Hanselmann
2851 ee3aedff Michael Hanselmann
  if found_unknown:
2852 ee3aedff Michael Hanselmann
    return constants.EXIT_UNKNOWN_FIELD
2853 ee3aedff Michael Hanselmann
2854 ee3aedff Michael Hanselmann
  return constants.EXIT_SUCCESS
2855 ee3aedff Michael Hanselmann
2856 ee3aedff Michael Hanselmann
2857 ee3aedff Michael Hanselmann
class TableColumn:
2858 ee3aedff Michael Hanselmann
  """Describes a column for L{FormatTable}.
2859 ee3aedff Michael Hanselmann

2860 ee3aedff Michael Hanselmann
  """
2861 ee3aedff Michael Hanselmann
  def __init__(self, title, fn, align_right):
2862 ee3aedff Michael Hanselmann
    """Initializes this class.
2863 ee3aedff Michael Hanselmann

2864 ee3aedff Michael Hanselmann
    @type title: string
2865 ee3aedff Michael Hanselmann
    @param title: Column title
2866 ee3aedff Michael Hanselmann
    @type fn: callable
2867 ee3aedff Michael Hanselmann
    @param fn: Formatting function
2868 ee3aedff Michael Hanselmann
    @type align_right: bool
2869 ee3aedff Michael Hanselmann
    @param align_right: Whether to align values on the right-hand side
2870 ee3aedff Michael Hanselmann

2871 ee3aedff Michael Hanselmann
    """
2872 ee3aedff Michael Hanselmann
    self.title = title
2873 ee3aedff Michael Hanselmann
    self.format = fn
2874 ee3aedff Michael Hanselmann
    self.align_right = align_right
2875 ee3aedff Michael Hanselmann
2876 ee3aedff Michael Hanselmann
2877 ee3aedff Michael Hanselmann
def _GetColFormatString(width, align_right):
2878 ee3aedff Michael Hanselmann
  """Returns the format string for a field.
2879 ee3aedff Michael Hanselmann

2880 ee3aedff Michael Hanselmann
  """
2881 ee3aedff Michael Hanselmann
  if align_right:
2882 ee3aedff Michael Hanselmann
    sign = ""
2883 ee3aedff Michael Hanselmann
  else:
2884 ee3aedff Michael Hanselmann
    sign = "-"
2885 ee3aedff Michael Hanselmann
2886 ee3aedff Michael Hanselmann
  return "%%%s%ss" % (sign, width)
2887 ee3aedff Michael Hanselmann
2888 ee3aedff Michael Hanselmann
2889 ee3aedff Michael Hanselmann
def FormatTable(rows, columns, header, separator):
2890 ee3aedff Michael Hanselmann
  """Formats data as a table.
2891 ee3aedff Michael Hanselmann

2892 ee3aedff Michael Hanselmann
  @type rows: list of lists
2893 ee3aedff Michael Hanselmann
  @param rows: Row data, one list per row
2894 ee3aedff Michael Hanselmann
  @type columns: list of L{TableColumn}
2895 ee3aedff Michael Hanselmann
  @param columns: Column descriptions
2896 ee3aedff Michael Hanselmann
  @type header: bool
2897 ee3aedff Michael Hanselmann
  @param header: Whether to show header row
2898 ee3aedff Michael Hanselmann
  @type separator: string or None
2899 ee3aedff Michael Hanselmann
  @param separator: String used to separate columns
2900 ee3aedff Michael Hanselmann

2901 ee3aedff Michael Hanselmann
  """
2902 ee3aedff Michael Hanselmann
  if header:
2903 ee3aedff Michael Hanselmann
    data = [[col.title for col in columns]]
2904 ee3aedff Michael Hanselmann
    colwidth = [len(col.title) for col in columns]
2905 ee3aedff Michael Hanselmann
  else:
2906 ee3aedff Michael Hanselmann
    data = []
2907 ee3aedff Michael Hanselmann
    colwidth = [0 for _ in columns]
2908 ee3aedff Michael Hanselmann
2909 ee3aedff Michael Hanselmann
  # Format row data
2910 ee3aedff Michael Hanselmann
  for row in rows:
2911 ee3aedff Michael Hanselmann
    assert len(row) == len(columns)
2912 ee3aedff Michael Hanselmann
2913 ee3aedff Michael Hanselmann
    formatted = [col.format(value) for value, col in zip(row, columns)]
2914 ee3aedff Michael Hanselmann
2915 ee3aedff Michael Hanselmann
    if separator is None:
2916 ee3aedff Michael Hanselmann
      # Update column widths
2917 ee3aedff Michael Hanselmann
      for idx, (oldwidth, value) in enumerate(zip(colwidth, formatted)):
2918 ee3aedff Michael Hanselmann
        # Modifying a list's items while iterating is fine
2919 ee3aedff Michael Hanselmann
        colwidth[idx] = max(oldwidth, len(value))
2920 ee3aedff Michael Hanselmann
2921 ee3aedff Michael Hanselmann
    data.append(formatted)
2922 ee3aedff Michael Hanselmann
2923 ee3aedff Michael Hanselmann
  if separator is not None:
2924 ee3aedff Michael Hanselmann
    # Return early if a separator is used
2925 ee3aedff Michael Hanselmann
    return [separator.join(row) for row in data]
2926 ee3aedff Michael Hanselmann
2927 ee3aedff Michael Hanselmann
  if columns and not columns[-1].align_right:
2928 ee3aedff Michael Hanselmann
    # Avoid unnecessary spaces at end of line
2929 ee3aedff Michael Hanselmann
    colwidth[-1] = 0
2930 ee3aedff Michael Hanselmann
2931 ee3aedff Michael Hanselmann
  # Build format string
2932 ee3aedff Michael Hanselmann
  fmt = " ".join([_GetColFormatString(width, col.align_right)
2933 ee3aedff Michael Hanselmann
                  for col, width in zip(columns, colwidth)])
2934 ee3aedff Michael Hanselmann
2935 ee3aedff Michael Hanselmann
  return [fmt % tuple(row) for row in data]
2936 ee3aedff Michael Hanselmann
2937 ee3aedff Michael Hanselmann
2938 3386e7a9 Iustin Pop
def FormatTimestamp(ts):
2939 3386e7a9 Iustin Pop
  """Formats a given timestamp.
2940 3386e7a9 Iustin Pop

2941 3386e7a9 Iustin Pop
  @type ts: timestamp
2942 3386e7a9 Iustin Pop
  @param ts: a timeval-type timestamp, a tuple of seconds and microseconds
2943 3386e7a9 Iustin Pop

2944 3386e7a9 Iustin Pop
  @rtype: string
2945 5fcc718f Iustin Pop
  @return: a string with the formatted timestamp
2946 3386e7a9 Iustin Pop

2947 3386e7a9 Iustin Pop
  """
2948 e687ec01 Michael Hanselmann
  if not isinstance(ts, (tuple, list)) or len(ts) != 2:
2949 d0c8c01d Iustin Pop
    return "?"
2950 3386e7a9 Iustin Pop
  sec, usec = ts
2951 3386e7a9 Iustin Pop
  return time.strftime("%F %T", time.localtime(sec)) + ".%06d" % usec
2952 2241e2b9 Iustin Pop
2953 2241e2b9 Iustin Pop
2954 2241e2b9 Iustin Pop
def ParseTimespec(value):
2955 2241e2b9 Iustin Pop
  """Parse a time specification.
2956 2241e2b9 Iustin Pop

2957 2241e2b9 Iustin Pop
  The following suffixed will be recognized:
2958 2241e2b9 Iustin Pop

2959 2241e2b9 Iustin Pop
    - s: seconds
2960 2241e2b9 Iustin Pop
    - m: minutes
2961 2241e2b9 Iustin Pop
    - h: hours
2962 2241e2b9 Iustin Pop
    - d: day
2963 2241e2b9 Iustin Pop
    - w: weeks
2964 2241e2b9 Iustin Pop

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

2967 2241e2b9 Iustin Pop
  """
2968 2241e2b9 Iustin Pop
  value = str(value)
2969 2241e2b9 Iustin Pop
  if not value:
2970 2241e2b9 Iustin Pop
    raise errors.OpPrereqError("Empty time specification passed")
2971 2241e2b9 Iustin Pop
  suffix_map = {
2972 d0c8c01d Iustin Pop
    "s": 1,
2973 d0c8c01d Iustin Pop
    "m": 60,
2974 d0c8c01d Iustin Pop
    "h": 3600,
2975 d0c8c01d Iustin Pop
    "d": 86400,
2976 d0c8c01d Iustin Pop
    "w": 604800,
2977 2241e2b9 Iustin Pop
    }
2978 2241e2b9 Iustin Pop
  if value[-1] not in suffix_map:
2979 2241e2b9 Iustin Pop
    try:
2980 2241e2b9 Iustin Pop
      value = int(value)
2981 691744c4 Iustin Pop
    except (TypeError, ValueError):
2982 2241e2b9 Iustin Pop
      raise errors.OpPrereqError("Invalid time specification '%s'" % value)
2983 2241e2b9 Iustin Pop
  else:
2984 2241e2b9 Iustin Pop
    multiplier = suffix_map[value[-1]]
2985 2241e2b9 Iustin Pop
    value = value[:-1]
2986 2241e2b9 Iustin Pop
    if not value: # no data left after stripping the suffix
2987 2241e2b9 Iustin Pop
      raise errors.OpPrereqError("Invalid time specification (only"
2988 2241e2b9 Iustin Pop
                                 " suffix passed)")
2989 2241e2b9 Iustin Pop
    try:
2990 2241e2b9 Iustin Pop
      value = int(value) * multiplier
2991 691744c4 Iustin Pop
    except (TypeError, ValueError):
2992 2241e2b9 Iustin Pop
      raise errors.OpPrereqError("Invalid time specification '%s'" % value)
2993 2241e2b9 Iustin Pop
  return value
2994 46fbdd04 Iustin Pop
2995 46fbdd04 Iustin Pop
2996 e9e26bb3 Iustin Pop
def GetOnlineNodes(nodes, cl=None, nowarn=False, secondary_ips=False,
2997 05484a24 Michael Hanselmann
                   filter_master=False, nodegroup=None):
2998 4040a784 Iustin Pop
  """Returns the names of online nodes.
2999 4040a784 Iustin Pop

3000 4040a784 Iustin Pop
  This function will also log a warning on stderr with the names of
3001 4040a784 Iustin Pop
  the online nodes.
3002 4040a784 Iustin Pop

3003 4040a784 Iustin Pop
  @param nodes: if not empty, use only this subset of nodes (minus the
3004 4040a784 Iustin Pop
      offline ones)
3005 4040a784 Iustin Pop
  @param cl: if not None, luxi client to use
3006 4040a784 Iustin Pop
  @type nowarn: boolean
3007 4040a784 Iustin Pop
  @param nowarn: by default, this function will output a note with the
3008 4040a784 Iustin Pop
      offline nodes that are skipped; if this parameter is True the
3009 4040a784 Iustin Pop
      note is not displayed
3010 e9e26bb3 Iustin Pop
  @type secondary_ips: boolean
3011 e9e26bb3 Iustin Pop
  @param secondary_ips: if True, return the secondary IPs instead of the
3012 e9e26bb3 Iustin Pop
      names, useful for doing network traffic over the replication interface
3013 e9e26bb3 Iustin Pop
      (if any)
3014 e9e26bb3 Iustin Pop
  @type filter_master: boolean
3015 e9e26bb3 Iustin Pop
  @param filter_master: if True, do not return the master node in the list
3016 e9e26bb3 Iustin Pop
      (useful in coordination with secondary_ips where we cannot check our
3017 e9e26bb3 Iustin Pop
      node name against the list)
3018 05484a24 Michael Hanselmann
  @type nodegroup: string
3019 05484a24 Michael Hanselmann
  @param nodegroup: If set, only return nodes in this node group
3020 4040a784 Iustin Pop

3021 4040a784 Iustin Pop
  """
3022 4040a784 Iustin Pop
  if cl is None:
3023 4040a784 Iustin Pop
    cl = GetClient()
3024 4040a784 Iustin Pop
3025 2e5c33db Iustin Pop
  qfilter = []
3026 05484a24 Michael Hanselmann
3027 05484a24 Michael Hanselmann
  if nodes:
3028 2e5c33db Iustin Pop
    qfilter.append(qlang.MakeSimpleFilter("name", nodes))
3029 05484a24 Michael Hanselmann
3030 05484a24 Michael Hanselmann
  if nodegroup is not None:
3031 2e5c33db Iustin Pop
    qfilter.append([qlang.OP_OR, [qlang.OP_EQUAL, "group", nodegroup],
3032 05484a24 Michael Hanselmann
                                 [qlang.OP_EQUAL, "group.uuid", nodegroup]])
3033 e9e26bb3 Iustin Pop
3034 e9e26bb3 Iustin Pop
  if filter_master:
3035 2e5c33db Iustin Pop
    qfilter.append([qlang.OP_NOT, [qlang.OP_TRUE, "master"]])
3036 05484a24 Michael Hanselmann
3037 2e5c33db Iustin Pop
  if qfilter:
3038 2e5c33db Iustin Pop
    if len(qfilter) > 1:
3039 2e5c33db Iustin Pop
      final_filter = [qlang.OP_AND] + qfilter
3040 05484a24 Michael Hanselmann
    else:
3041 2e5c33db Iustin Pop
      assert len(qfilter) == 1
3042 2e5c33db Iustin Pop
      final_filter = qfilter[0]
3043 e9e26bb3 Iustin Pop
  else:
3044 05484a24 Michael Hanselmann
    final_filter = None
3045 05484a24 Michael Hanselmann
3046 05484a24 Michael Hanselmann
  result = cl.Query(constants.QR_NODE, ["name", "offline", "sip"], final_filter)
3047 05484a24 Michael Hanselmann
3048 05484a24 Michael Hanselmann
  def _IsOffline(row):
3049 05484a24 Michael Hanselmann
    (_, (_, offline), _) = row
3050 05484a24 Michael Hanselmann
    return offline
3051 05484a24 Michael Hanselmann
3052 05484a24 Michael Hanselmann
  def _GetName(row):
3053 05484a24 Michael Hanselmann
    ((_, name), _, _) = row
3054 05484a24 Michael Hanselmann
    return name
3055 05484a24 Michael Hanselmann
3056 05484a24 Michael Hanselmann
  def _GetSip(row):
3057 05484a24 Michael Hanselmann
    (_, _, (_, sip)) = row
3058 05484a24 Michael Hanselmann
    return sip
3059 05484a24 Michael Hanselmann
3060 05484a24 Michael Hanselmann
  (offline, online) = compat.partition(result.data, _IsOffline)
3061 e9e26bb3 Iustin Pop
3062 4040a784 Iustin Pop
  if offline and not nowarn:
3063 05484a24 Michael Hanselmann
    ToStderr("Note: skipping offline node(s): %s" %
3064 05484a24 Michael Hanselmann
             utils.CommaJoin(map(_GetName, offline)))
3065 05484a24 Michael Hanselmann
3066 05484a24 Michael Hanselmann
  if secondary_ips:
3067 05484a24 Michael Hanselmann
    fn = _GetSip
3068 05484a24 Michael Hanselmann
  else:
3069 05484a24 Michael Hanselmann
    fn = _GetName
3070 05484a24 Michael Hanselmann
3071 05484a24 Michael Hanselmann
  return map(fn, online)
3072 4040a784 Iustin Pop
3073 4040a784 Iustin Pop
3074 46fbdd04 Iustin Pop
def _ToStream(stream, txt, *args):
3075 46fbdd04 Iustin Pop
  """Write a message to a stream, bypassing the logging system
3076 46fbdd04 Iustin Pop

3077 46fbdd04 Iustin Pop
  @type stream: file object
3078 46fbdd04 Iustin Pop
  @param stream: the file to which we should write
3079 46fbdd04 Iustin Pop
  @type txt: str
3080 46fbdd04 Iustin Pop
  @param txt: the message
3081 46fbdd04 Iustin Pop

3082 46fbdd04 Iustin Pop
  """
3083 225e2544 Iustin Pop
  try:
3084 225e2544 Iustin Pop
    if args:
3085 225e2544 Iustin Pop
      args = tuple(args)
3086 225e2544 Iustin Pop
      stream.write(txt % args)
3087 225e2544 Iustin Pop
    else:
3088 225e2544 Iustin Pop
      stream.write(txt)
3089 d0c8c01d Iustin Pop
    stream.write("\n")
3090 225e2544 Iustin Pop
    stream.flush()
3091 225e2544 Iustin Pop
  except IOError, err:
3092 225e2544 Iustin Pop
    if err.errno == errno.EPIPE:
3093 225e2544 Iustin Pop
      # our terminal went away, we'll exit
3094 225e2544 Iustin Pop
      sys.exit(constants.EXIT_FAILURE)
3095 225e2544 Iustin Pop
    else:
3096 225e2544 Iustin Pop
      raise
3097 46fbdd04 Iustin Pop
3098 46fbdd04 Iustin Pop
3099 46fbdd04 Iustin Pop
def ToStdout(txt, *args):
3100 46fbdd04 Iustin Pop
  """Write a message to stdout only, bypassing the logging system
3101 46fbdd04 Iustin Pop

3102 46fbdd04 Iustin Pop
  This is just a wrapper over _ToStream.
3103 46fbdd04 Iustin Pop

3104 46fbdd04 Iustin Pop
  @type txt: str
3105 46fbdd04 Iustin Pop
  @param txt: the message
3106 46fbdd04 Iustin Pop

3107 46fbdd04 Iustin Pop
  """
3108 46fbdd04 Iustin Pop
  _ToStream(sys.stdout, txt, *args)
3109 46fbdd04 Iustin Pop
3110 46fbdd04 Iustin Pop
3111 46fbdd04 Iustin Pop
def ToStderr(txt, *args):
3112 46fbdd04 Iustin Pop
  """Write a message to stderr only, bypassing the logging system
3113 46fbdd04 Iustin Pop

3114 46fbdd04 Iustin Pop
  This is just a wrapper over _ToStream.
3115 46fbdd04 Iustin Pop

3116 46fbdd04 Iustin Pop
  @type txt: str
3117 46fbdd04 Iustin Pop
  @param txt: the message
3118 46fbdd04 Iustin Pop

3119 46fbdd04 Iustin Pop
  """
3120 46fbdd04 Iustin Pop
  _ToStream(sys.stderr, txt, *args)
3121 479636a3 Iustin Pop
3122 479636a3 Iustin Pop
3123 479636a3 Iustin Pop
class JobExecutor(object):
3124 479636a3 Iustin Pop
  """Class which manages the submission and execution of multiple jobs.
3125 479636a3 Iustin Pop

3126 479636a3 Iustin Pop
  Note that instances of this class should not be reused between
3127 479636a3 Iustin Pop
  GetResults() calls.
3128 479636a3 Iustin Pop

3129 479636a3 Iustin Pop
  """
3130 919ca415 Iustin Pop
  def __init__(self, cl=None, verbose=True, opts=None, feedback_fn=None):
3131 479636a3 Iustin Pop
    self.queue = []
3132 479636a3 Iustin Pop
    if cl is None:
3133 479636a3 Iustin Pop
      cl = GetClient()
3134 479636a3 Iustin Pop
    self.cl = cl
3135 479636a3 Iustin Pop
    self.verbose = verbose
3136 23b4b983 Iustin Pop
    self.jobs = []
3137 cff5fa7f Iustin Pop
    self.opts = opts
3138 919ca415 Iustin Pop
    self.feedback_fn = feedback_fn
3139 60452edf Michael Hanselmann
    self._counter = itertools.count()
3140 479636a3 Iustin Pop
3141 8d99a8bf Michael Hanselmann
  @staticmethod
3142 8d99a8bf Michael Hanselmann
  def _IfName(name, fmt):
3143 8d99a8bf Michael Hanselmann
    """Helper function for formatting name.
3144 8d99a8bf Michael Hanselmann

3145 8d99a8bf Michael Hanselmann
    """
3146 8d99a8bf Michael Hanselmann
    if name:
3147 8d99a8bf Michael Hanselmann
      return fmt % name
3148 8d99a8bf Michael Hanselmann
3149 8d99a8bf Michael Hanselmann
    return ""
3150 8d99a8bf Michael Hanselmann
3151 479636a3 Iustin Pop
  def QueueJob(self, name, *ops):
3152 23b4b983 Iustin Pop
    """Record a job for later submit.
3153 479636a3 Iustin Pop

3154 479636a3 Iustin Pop
    @type name: string
3155 479636a3 Iustin Pop
    @param name: a description of the job, will be used in WaitJobSet
3156 8d99a8bf Michael Hanselmann

3157 479636a3 Iustin Pop
    """
3158 cff5fa7f Iustin Pop
    SetGenericOpcodeOpts(ops, self.opts)
3159 60452edf Michael Hanselmann
    self.queue.append((self._counter.next(), name, ops))
3160 23b4b983 Iustin Pop
3161 8d99a8bf Michael Hanselmann
  def AddJobId(self, name, status, job_id):
3162 8d99a8bf Michael Hanselmann
    """Adds a job ID to the internal queue.
3163 8d99a8bf Michael Hanselmann

3164 8d99a8bf Michael Hanselmann
    """
3165 8d99a8bf Michael Hanselmann
    self.jobs.append((self._counter.next(), status, job_id, name))
3166 8d99a8bf Michael Hanselmann
3167 66ecc479 Guido Trotter
  def SubmitPending(self, each=False):
3168 23b4b983 Iustin Pop
    """Submit all pending jobs.
3169 23b4b983 Iustin Pop

3170 23b4b983 Iustin Pop
    """
3171 66ecc479 Guido Trotter
    if each:
3172 66ecc479 Guido Trotter
      results = []
3173 60452edf Michael Hanselmann
      for (_, _, ops) in self.queue:
3174 66ecc479 Guido Trotter
        # SubmitJob will remove the success status, but raise an exception if
3175 66ecc479 Guido Trotter
        # the submission fails, so we'll notice that anyway.
3176 519fafa1 Andrea Spadaccini
        results.append([True, self.cl.SubmitJob(ops)[0]])
3177 66ecc479 Guido Trotter
    else:
3178 60452edf Michael Hanselmann
      results = self.cl.SubmitManyJobs([ops for (_, _, ops) in self.queue])
3179 60452edf Michael Hanselmann
    for ((status, data), (idx, name, _)) in zip(results, self.queue):
3180 5299e61f Iustin Pop
      self.jobs.append((idx, status, data, name))
3181 5299e61f Iustin Pop
3182 5299e61f Iustin Pop
  def _ChooseJob(self):
3183 5299e61f Iustin Pop
    """Choose a non-waiting/queued job to poll next.
3184 5299e61f Iustin Pop

3185 5299e61f Iustin Pop
    """
3186 5299e61f Iustin Pop
    assert self.jobs, "_ChooseJob called with empty job list"
3187 5299e61f Iustin Pop
3188 11705e3d Iustin Pop
    result = self.cl.QueryJobs([i[2] for i in self.jobs[:_CHOOSE_BATCH]],
3189 11705e3d Iustin Pop
                               ["status"])
3190 5299e61f Iustin Pop
    assert result
3191 5299e61f Iustin Pop
3192 5299e61f Iustin Pop
    for job_data, status in zip(self.jobs, result):
3193 91c622a8 Iustin Pop
      if (isinstance(status, list) and status and
3194 91c622a8 Iustin Pop
          status[0] in (constants.JOB_STATUS_QUEUED,
3195 47099cd1 Michael Hanselmann
                        constants.JOB_STATUS_WAITING,
3196 91c622a8 Iustin Pop
                        constants.JOB_STATUS_CANCELING)):
3197 91c622a8 Iustin Pop
        # job is still present and waiting
3198 5299e61f Iustin Pop
        continue
3199 91c622a8 Iustin Pop
      # good candidate found (either running job or lost job)
3200 5299e61f Iustin Pop
      self.jobs.remove(job_data)
3201 5299e61f Iustin Pop
      return job_data
3202 5299e61f Iustin Pop
3203 5299e61f Iustin Pop
    # no job found
3204 5299e61f Iustin Pop
    return self.jobs.pop(0)
3205 479636a3 Iustin Pop
3206 479636a3 Iustin Pop
  def GetResults(self):
3207 479636a3 Iustin Pop
    """Wait for and return the results of all jobs.
3208 479636a3 Iustin Pop

3209 479636a3 Iustin Pop
    @rtype: list
3210 479636a3 Iustin Pop
    @return: list of tuples (success, job results), in the same order
3211 479636a3 Iustin Pop
        as the submitted jobs; if a job has failed, instead of the result
3212 479636a3 Iustin Pop
        there will be the error message
3213 479636a3 Iustin Pop

3214 479636a3 Iustin Pop
    """
3215 23b4b983 Iustin Pop
    if not self.jobs:
3216 23b4b983 Iustin Pop
      self.SubmitPending()
3217 479636a3 Iustin Pop
    results = []
3218 479636a3 Iustin Pop
    if self.verbose:
3219 5299e61f Iustin Pop
      ok_jobs = [row[2] for row in self.jobs if row[1]]
3220 23b4b983 Iustin Pop
      if ok_jobs:
3221 4474f112 Iustin Pop
        ToStdout("Submitted jobs %s", utils.CommaJoin(ok_jobs))
3222 5299e61f Iustin Pop
3223 5299e61f Iustin Pop
    # first, remove any non-submitted jobs
3224 cea881e5 Michael Hanselmann
    self.jobs, failures = compat.partition(self.jobs, lambda x: x[1])
3225 5299e61f Iustin Pop
    for idx, _, jid, name in failures:
3226 4474f112 Iustin Pop
      ToStderr("Failed to submit job%s: %s", self._IfName(name, " for %s"), jid)
3227 c63355f2 Iustin Pop
      results.append((idx, False, jid))
3228 5299e61f Iustin Pop
3229 5299e61f Iustin Pop
    while self.jobs:
3230 5299e61f Iustin Pop
      (idx, _, jid, name) = self._ChooseJob()
3231 4474f112 Iustin Pop
      ToStdout("Waiting for job %s%s ...", jid, self._IfName(name, " for %s"))
3232 479636a3 Iustin Pop
      try:
3233 919ca415 Iustin Pop
        job_result = PollJob(jid, cl=self.cl, feedback_fn=self.feedback_fn)
3234 479636a3 Iustin Pop
        success = True
3235 91c622a8 Iustin Pop
      except errors.JobLost, err:
3236 91c622a8 Iustin Pop
        _, job_result = FormatError(err)
3237 4474f112 Iustin Pop
        ToStderr("Job %s%s has been archived, cannot check its result",
3238 4474f112 Iustin Pop
                 jid, self._IfName(name, " for %s"))
3239 91c622a8 Iustin Pop
        success = False
3240 479636a3 Iustin Pop
      except (errors.GenericError, luxi.ProtocolError), err:
3241 479636a3 Iustin Pop
        _, job_result = FormatError(err)
3242 479636a3 Iustin Pop
        success = False
3243 479636a3 Iustin Pop
        # the error message will always be shown, verbose or not
3244 4474f112 Iustin Pop
        ToStderr("Job %s%s has failed: %s",
3245 4474f112 Iustin Pop
                 jid, self._IfName(name, " for %s"), job_result)
3246 479636a3 Iustin Pop
3247 5299e61f Iustin Pop
      results.append((idx, success, job_result))
3248 5299e61f Iustin Pop
3249 5299e61f Iustin Pop
    # sort based on the index, then drop it
3250 5299e61f Iustin Pop
    results.sort()
3251 5299e61f Iustin Pop
    results = [i[1:] for i in results]
3252 5299e61f Iustin Pop
3253 479636a3 Iustin Pop
    return results
3254 479636a3 Iustin Pop
3255 479636a3 Iustin Pop
  def WaitOrShow(self, wait):
3256 479636a3 Iustin Pop
    """Wait for job results or only print the job IDs.
3257 479636a3 Iustin Pop

3258 479636a3 Iustin Pop
    @type wait: boolean
3259 479636a3 Iustin Pop
    @param wait: whether to wait or not
3260 479636a3 Iustin Pop

3261 479636a3 Iustin Pop
    """
3262 479636a3 Iustin Pop
    if wait:
3263 479636a3 Iustin Pop
      return self.GetResults()
3264 479636a3 Iustin Pop
    else:
3265 23b4b983 Iustin Pop
      if not self.jobs:
3266 23b4b983 Iustin Pop
        self.SubmitPending()
3267 71834b2a Guido Trotter
      for _, status, result, name in self.jobs:
3268 23b4b983 Iustin Pop
        if status:
3269 4474f112 Iustin Pop
          ToStdout("%s: %s", result, name)
3270 23b4b983 Iustin Pop
        else:
3271 4474f112 Iustin Pop
          ToStderr("Failure for %s: %s", name, result)
3272 53a8a54d Iustin Pop
      return [row[1:3] for row in self.jobs]
3273 acd19189 René Nussbaumer
3274 acd19189 René Nussbaumer
3275 acd19189 René Nussbaumer
def FormatParameterDict(buf, param_dict, actual, level=1):
3276 acd19189 René Nussbaumer
  """Formats a parameter dictionary.
3277 acd19189 René Nussbaumer

3278 acd19189 René Nussbaumer
  @type buf: L{StringIO}
3279 acd19189 René Nussbaumer
  @param buf: the buffer into which to write
3280 acd19189 René Nussbaumer
  @type param_dict: dict
3281 acd19189 René Nussbaumer
  @param param_dict: the own parameters
3282 acd19189 René Nussbaumer
  @type actual: dict
3283 acd19189 René Nussbaumer
  @param actual: the current parameter set (including defaults)
3284 acd19189 René Nussbaumer
  @param level: Level of indent
3285 acd19189 René Nussbaumer

3286 acd19189 René Nussbaumer
  """
3287 acd19189 René Nussbaumer
  indent = "  " * level
3288 acd19189 René Nussbaumer
  for key in sorted(actual):
3289 acd19189 René Nussbaumer
    val = param_dict.get(key, "default (%s)" % actual[key])
3290 acd19189 René Nussbaumer
    buf.write("%s- %s: %s\n" % (indent, key, val))
3291 25bd815c René Nussbaumer
3292 25bd815c René Nussbaumer
3293 25bd815c René Nussbaumer
def ConfirmOperation(names, list_type, text, extra=""):
3294 25bd815c René Nussbaumer
  """Ask the user to confirm an operation on a list of list_type.
3295 25bd815c René Nussbaumer

3296 25bd815c René Nussbaumer
  This function is used to request confirmation for doing an operation
3297 25bd815c René Nussbaumer
  on a given list of list_type.
3298 25bd815c René Nussbaumer

3299 25bd815c René Nussbaumer
  @type names: list
3300 25bd815c René Nussbaumer
  @param names: the list of names that we display when
3301 25bd815c René Nussbaumer
      we ask for confirmation
3302 25bd815c René Nussbaumer
  @type list_type: str
3303 25bd815c René Nussbaumer
  @param list_type: Human readable name for elements in the list (e.g. nodes)
3304 25bd815c René Nussbaumer
  @type text: str
3305 25bd815c René Nussbaumer
  @param text: the operation that the user should confirm
3306 25bd815c René Nussbaumer
  @rtype: boolean
3307 25bd815c René Nussbaumer
  @return: True or False depending on user's confirmation.
3308 25bd815c René Nussbaumer

3309 25bd815c René Nussbaumer
  """
3310 25bd815c René Nussbaumer
  count = len(names)
3311 25bd815c René Nussbaumer
  msg = ("The %s will operate on %d %s.\n%s"
3312 25bd815c René Nussbaumer
         "Do you want to continue?" % (text, count, list_type, extra))
3313 25bd815c René Nussbaumer
  affected = (("\nAffected %s:\n" % list_type) +
3314 25bd815c René Nussbaumer
              "\n".join(["  %s" % name for name in names]))
3315 25bd815c René Nussbaumer
3316 25bd815c René Nussbaumer
  choices = [("y", True, "Yes, execute the %s" % text),
3317 25bd815c René Nussbaumer
             ("n", False, "No, abort the %s" % text)]
3318 25bd815c René Nussbaumer
3319 25bd815c René Nussbaumer
  if count > 20:
3320 25bd815c René Nussbaumer
    choices.insert(1, ("v", "v", "View the list of affected %s" % list_type))
3321 25bd815c René Nussbaumer
    question = msg
3322 25bd815c René Nussbaumer
  else:
3323 25bd815c René Nussbaumer
    question = msg + affected
3324 25bd815c René Nussbaumer
3325 25bd815c René Nussbaumer
  choice = AskUser(question, choices)
3326 25bd815c René Nussbaumer
  if choice == "v":
3327 25bd815c René Nussbaumer
    choices.pop(1)
3328 25bd815c René Nussbaumer
    choice = AskUser(msg + affected, choices)
3329 25bd815c René Nussbaumer
  return choice