Statistics
| Branch: | Tag: | Revision:

root / lib / cli.py @ 70817cee

History | View | Annotate | Download (115.5 kB)

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

316 863d7f46 Michael Hanselmann
  Value can be any of the ones passed to the constructor.
317 863d7f46 Michael Hanselmann

318 863d7f46 Michael Hanselmann
  """
319 b459a848 Andrea Spadaccini
  # pylint: disable=W0622
320 863d7f46 Michael Hanselmann
  def __init__(self, min=0, max=None, choices=None):
321 863d7f46 Michael Hanselmann
    _Argument.__init__(self, min=min, max=max)
322 863d7f46 Michael Hanselmann
    self.choices = choices
323 863d7f46 Michael Hanselmann
324 863d7f46 Michael Hanselmann
  def __repr__(self):
325 863d7f46 Michael Hanselmann
    return ("<%s min=%s max=%s choices=%r>" %
326 863d7f46 Michael Hanselmann
            (self.__class__.__name__, self.min, self.max, self.choices))
327 863d7f46 Michael Hanselmann
328 863d7f46 Michael Hanselmann
329 863d7f46 Michael Hanselmann
class ArgChoice(ArgSuggest):
330 863d7f46 Michael Hanselmann
  """Choice argument.
331 863d7f46 Michael Hanselmann

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

335 863d7f46 Michael Hanselmann
  """
336 863d7f46 Michael Hanselmann
337 863d7f46 Michael Hanselmann
338 863d7f46 Michael Hanselmann
class ArgUnknown(_Argument):
339 863d7f46 Michael Hanselmann
  """Unknown argument to program (e.g. determined at runtime).
340 863d7f46 Michael Hanselmann

341 863d7f46 Michael Hanselmann
  """
342 863d7f46 Michael Hanselmann
343 863d7f46 Michael Hanselmann
344 863d7f46 Michael Hanselmann
class ArgInstance(_Argument):
345 863d7f46 Michael Hanselmann
  """Instances argument.
346 863d7f46 Michael Hanselmann

347 863d7f46 Michael Hanselmann
  """
348 863d7f46 Michael Hanselmann
349 863d7f46 Michael Hanselmann
350 863d7f46 Michael Hanselmann
class ArgNode(_Argument):
351 863d7f46 Michael Hanselmann
  """Node argument.
352 863d7f46 Michael Hanselmann

353 863d7f46 Michael Hanselmann
  """
354 863d7f46 Michael Hanselmann
355 667dbd6b Adeodato Simo
356 667dbd6b Adeodato Simo
class ArgGroup(_Argument):
357 667dbd6b Adeodato Simo
  """Node group argument.
358 667dbd6b Adeodato Simo

359 667dbd6b Adeodato Simo
  """
360 667dbd6b Adeodato Simo
361 667dbd6b Adeodato Simo
362 863d7f46 Michael Hanselmann
class ArgJobId(_Argument):
363 863d7f46 Michael Hanselmann
  """Job ID argument.
364 863d7f46 Michael Hanselmann

365 863d7f46 Michael Hanselmann
  """
366 863d7f46 Michael Hanselmann
367 863d7f46 Michael Hanselmann
368 863d7f46 Michael Hanselmann
class ArgFile(_Argument):
369 863d7f46 Michael Hanselmann
  """File path argument.
370 863d7f46 Michael Hanselmann

371 863d7f46 Michael Hanselmann
  """
372 863d7f46 Michael Hanselmann
373 863d7f46 Michael Hanselmann
374 863d7f46 Michael Hanselmann
class ArgCommand(_Argument):
375 863d7f46 Michael Hanselmann
  """Command argument.
376 863d7f46 Michael Hanselmann

377 863d7f46 Michael Hanselmann
  """
378 863d7f46 Michael Hanselmann
379 863d7f46 Michael Hanselmann
380 83ec7961 Michael Hanselmann
class ArgHost(_Argument):
381 83ec7961 Michael Hanselmann
  """Host argument.
382 83ec7961 Michael Hanselmann

383 83ec7961 Michael Hanselmann
  """
384 83ec7961 Michael Hanselmann
385 83ec7961 Michael Hanselmann
386 f9faf9c3 René Nussbaumer
class ArgOs(_Argument):
387 f9faf9c3 René Nussbaumer
  """OS argument.
388 f9faf9c3 René Nussbaumer

389 f9faf9c3 René Nussbaumer
  """
390 f9faf9c3 René Nussbaumer
391 f9faf9c3 René Nussbaumer
392 4a265c08 Michael Hanselmann
ARGS_NONE = []
393 4a265c08 Michael Hanselmann
ARGS_MANY_INSTANCES = [ArgInstance()]
394 4a265c08 Michael Hanselmann
ARGS_MANY_NODES = [ArgNode()]
395 667dbd6b Adeodato Simo
ARGS_MANY_GROUPS = [ArgGroup()]
396 4a265c08 Michael Hanselmann
ARGS_ONE_INSTANCE = [ArgInstance(min=1, max=1)]
397 4a265c08 Michael Hanselmann
ARGS_ONE_NODE = [ArgNode(min=1, max=1)]
398 dadf6b7d Michael Hanselmann
# TODO
399 dadf6b7d Michael Hanselmann
ARGS_ONE_GROUP = [ArgGroup(min=1, max=1)]
400 f9faf9c3 René Nussbaumer
ARGS_ONE_OS = [ArgOs(min=1, max=1)]
401 4a265c08 Michael Hanselmann
402 4a265c08 Michael Hanselmann
403 846baef9 Iustin Pop
def _ExtractTagsObject(opts, args):
404 846baef9 Iustin Pop
  """Extract the tag type object.
405 846baef9 Iustin Pop

406 846baef9 Iustin Pop
  Note that this function will modify its args parameter.
407 846baef9 Iustin Pop

408 846baef9 Iustin Pop
  """
409 846baef9 Iustin Pop
  if not hasattr(opts, "tag_type"):
410 846baef9 Iustin Pop
    raise errors.ProgrammerError("tag_type not passed to _ExtractTagsObject")
411 846baef9 Iustin Pop
  kind = opts.tag_type
412 846baef9 Iustin Pop
  if kind == constants.TAG_CLUSTER:
413 846baef9 Iustin Pop
    retval = kind, kind
414 819cbfe5 Michael Hanselmann
  elif kind in (constants.TAG_NODEGROUP,
415 819cbfe5 Michael Hanselmann
                constants.TAG_NODE,
416 819cbfe5 Michael Hanselmann
                constants.TAG_INSTANCE):
417 846baef9 Iustin Pop
    if not args:
418 0c434948 Iustin Pop
      raise errors.OpPrereqError("no arguments passed to the command")
419 846baef9 Iustin Pop
    name = args.pop(0)
420 846baef9 Iustin Pop
    retval = kind, name
421 846baef9 Iustin Pop
  else:
422 846baef9 Iustin Pop
    raise errors.ProgrammerError("Unhandled tag type '%s'" % kind)
423 846baef9 Iustin Pop
  return retval
424 846baef9 Iustin Pop
425 846baef9 Iustin Pop
426 810c50b7 Iustin Pop
def _ExtendTags(opts, args):
427 810c50b7 Iustin Pop
  """Extend the args if a source file has been given.
428 810c50b7 Iustin Pop

429 810c50b7 Iustin Pop
  This function will extend the tags with the contents of the file
430 810c50b7 Iustin Pop
  passed in the 'tags_source' attribute of the opts parameter. A file
431 810c50b7 Iustin Pop
  named '-' will be replaced by stdin.
432 810c50b7 Iustin Pop

433 810c50b7 Iustin Pop
  """
434 810c50b7 Iustin Pop
  fname = opts.tags_source
435 810c50b7 Iustin Pop
  if fname is None:
436 810c50b7 Iustin Pop
    return
437 810c50b7 Iustin Pop
  if fname == "-":
438 810c50b7 Iustin Pop
    new_fh = sys.stdin
439 810c50b7 Iustin Pop
  else:
440 810c50b7 Iustin Pop
    new_fh = open(fname, "r")
441 810c50b7 Iustin Pop
  new_data = []
442 810c50b7 Iustin Pop
  try:
443 810c50b7 Iustin Pop
    # we don't use the nice 'new_data = [line.strip() for line in fh]'
444 810c50b7 Iustin Pop
    # because of python bug 1633941
445 810c50b7 Iustin Pop
    while True:
446 810c50b7 Iustin Pop
      line = new_fh.readline()
447 810c50b7 Iustin Pop
      if not line:
448 810c50b7 Iustin Pop
        break
449 810c50b7 Iustin Pop
      new_data.append(line.strip())
450 810c50b7 Iustin Pop
  finally:
451 810c50b7 Iustin Pop
    new_fh.close()
452 810c50b7 Iustin Pop
  args.extend(new_data)
453 810c50b7 Iustin Pop
454 810c50b7 Iustin Pop
455 846baef9 Iustin Pop
def ListTags(opts, args):
456 846baef9 Iustin Pop
  """List the tags on a given object.
457 846baef9 Iustin Pop

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

463 846baef9 Iustin Pop
  """
464 846baef9 Iustin Pop
  kind, name = _ExtractTagsObject(opts, args)
465 7699c3af Iustin Pop
  cl = GetClient()
466 7699c3af Iustin Pop
  result = cl.QueryTags(kind, name)
467 846baef9 Iustin Pop
  result = list(result)
468 846baef9 Iustin Pop
  result.sort()
469 846baef9 Iustin Pop
  for tag in result:
470 03298ebe Michael Hanselmann
    ToStdout(tag)
471 846baef9 Iustin Pop
472 846baef9 Iustin Pop
473 846baef9 Iustin Pop
def AddTags(opts, args):
474 846baef9 Iustin Pop
  """Add tags on a given object.
475 846baef9 Iustin Pop

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

481 846baef9 Iustin Pop
  """
482 846baef9 Iustin Pop
  kind, name = _ExtractTagsObject(opts, args)
483 810c50b7 Iustin Pop
  _ExtendTags(opts, args)
484 846baef9 Iustin Pop
  if not args:
485 846baef9 Iustin Pop
    raise errors.OpPrereqError("No tags to be added")
486 d1602edc Iustin Pop
  op = opcodes.OpTagsSet(kind=kind, name=name, tags=args)
487 6bc3ed14 Michael Hanselmann
  SubmitOrSend(op, opts)
488 846baef9 Iustin Pop
489 846baef9 Iustin Pop
490 846baef9 Iustin Pop
def RemoveTags(opts, args):
491 846baef9 Iustin Pop
  """Remove tags from a given object.
492 846baef9 Iustin Pop

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

498 846baef9 Iustin Pop
  """
499 846baef9 Iustin Pop
  kind, name = _ExtractTagsObject(opts, args)
500 810c50b7 Iustin Pop
  _ExtendTags(opts, args)
501 846baef9 Iustin Pop
  if not args:
502 846baef9 Iustin Pop
    raise errors.OpPrereqError("No tags to be removed")
503 3f0ab95f Iustin Pop
  op = opcodes.OpTagsDel(kind=kind, name=name, tags=args)
504 6bc3ed14 Michael Hanselmann
  SubmitOrSend(op, opts)
505 846baef9 Iustin Pop
506 a8083063 Iustin Pop
507 b459a848 Andrea Spadaccini
def check_unit(option, opt, value): # pylint: disable=W0613
508 65fe4693 Iustin Pop
  """OptParsers custom converter for units.
509 65fe4693 Iustin Pop

510 65fe4693 Iustin Pop
  """
511 a8083063 Iustin Pop
  try:
512 a8083063 Iustin Pop
    return utils.ParseUnit(value)
513 a8083063 Iustin Pop
  except errors.UnitParseError, err:
514 3ecf6786 Iustin Pop
    raise OptionValueError("option %s: %s" % (opt, err))
515 a8083063 Iustin Pop
516 a8083063 Iustin Pop
517 a8469393 Iustin Pop
def _SplitKeyVal(opt, data):
518 a8469393 Iustin Pop
  """Convert a KeyVal string into a dict.
519 a8469393 Iustin Pop

520 a8469393 Iustin Pop
  This function will convert a key=val[,...] string into a dict. Empty
521 a8469393 Iustin Pop
  values will be converted specially: keys which have the prefix 'no_'
522 a8469393 Iustin Pop
  will have the value=False and the prefix stripped, the others will
523 a8469393 Iustin Pop
  have value=True.
524 a8469393 Iustin Pop

525 a8469393 Iustin Pop
  @type opt: string
526 a8469393 Iustin Pop
  @param opt: a string holding the option name for which we process the
527 a8469393 Iustin Pop
      data, used in building error messages
528 a8469393 Iustin Pop
  @type data: string
529 a8469393 Iustin Pop
  @param data: a string of the format key=val,key=val,...
530 a8469393 Iustin Pop
  @rtype: dict
531 a8469393 Iustin Pop
  @return: {key=val, key=val}
532 a8469393 Iustin Pop
  @raises errors.ParameterError: if there are duplicate keys
533 a8469393 Iustin Pop

534 a8469393 Iustin Pop
  """
535 a8469393 Iustin Pop
  kv_dict = {}
536 4f31882e Guido Trotter
  if data:
537 1b3a7656 Iustin Pop
    for elem in utils.UnescapeAndSplit(data, sep=","):
538 4f31882e Guido Trotter
      if "=" in elem:
539 4f31882e Guido Trotter
        key, val = elem.split("=", 1)
540 a8469393 Iustin Pop
      else:
541 4f31882e Guido Trotter
        if elem.startswith(NO_PREFIX):
542 4f31882e Guido Trotter
          key, val = elem[len(NO_PREFIX):], False
543 4f31882e Guido Trotter
        elif elem.startswith(UN_PREFIX):
544 4f31882e Guido Trotter
          key, val = elem[len(UN_PREFIX):], None
545 4f31882e Guido Trotter
        else:
546 4f31882e Guido Trotter
          key, val = elem, True
547 4f31882e Guido Trotter
      if key in kv_dict:
548 4f31882e Guido Trotter
        raise errors.ParameterError("Duplicate key '%s' in option %s" %
549 4f31882e Guido Trotter
                                    (key, opt))
550 4f31882e Guido Trotter
      kv_dict[key] = val
551 a8469393 Iustin Pop
  return kv_dict
552 a8469393 Iustin Pop
553 a8469393 Iustin Pop
554 b459a848 Andrea Spadaccini
def check_ident_key_val(option, opt, value):  # pylint: disable=W0613
555 552c8dff Michael Hanselmann
  """Custom parser for ident:key=val,key=val options.
556 552c8dff Michael Hanselmann

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

560 a8469393 Iustin Pop
  """
561 a8469393 Iustin Pop
  if ":" not in value:
562 d0c8c01d Iustin Pop
    ident, rest = value, ""
563 a8469393 Iustin Pop
  else:
564 a8469393 Iustin Pop
    ident, rest = value.split(":", 1)
565 8b46606c Guido Trotter
566 8b46606c Guido Trotter
  if ident.startswith(NO_PREFIX):
567 8b46606c Guido Trotter
    if rest:
568 8b46606c Guido Trotter
      msg = "Cannot pass options when removing parameter groups: %s" % value
569 8b46606c Guido Trotter
      raise errors.ParameterError(msg)
570 8b46606c Guido Trotter
    retval = (ident[len(NO_PREFIX):], False)
571 956631b6 Michael Hanselmann
  elif (ident.startswith(UN_PREFIX) and
572 956631b6 Michael Hanselmann
        (len(ident) <= len(UN_PREFIX) or
573 956631b6 Michael Hanselmann
         not ident[len(UN_PREFIX)][0].isdigit())):
574 8b46606c Guido Trotter
    if rest:
575 8b46606c Guido Trotter
      msg = "Cannot pass options when removing parameter groups: %s" % value
576 8b46606c Guido Trotter
      raise errors.ParameterError(msg)
577 8b46606c Guido Trotter
    retval = (ident[len(UN_PREFIX):], None)
578 8b46606c Guido Trotter
  else:
579 a8469393 Iustin Pop
    kv_dict = _SplitKeyVal(opt, rest)
580 a8469393 Iustin Pop
    retval = (ident, kv_dict)
581 a8469393 Iustin Pop
  return retval
582 a8469393 Iustin Pop
583 a8469393 Iustin Pop
584 b459a848 Andrea Spadaccini
def check_key_val(option, opt, value):  # pylint: disable=W0613
585 552c8dff Michael Hanselmann
  """Custom parser class for key=val,key=val options.
586 552c8dff Michael Hanselmann

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

589 a8469393 Iustin Pop
  """
590 a8469393 Iustin Pop
  return _SplitKeyVal(opt, value)
591 a8469393 Iustin Pop
592 a8469393 Iustin Pop
593 b459a848 Andrea Spadaccini
def check_bool(option, opt, value): # pylint: disable=W0613
594 e7b61bb0 Iustin Pop
  """Custom parser for yes/no options.
595 e7b61bb0 Iustin Pop

596 e7b61bb0 Iustin Pop
  This will store the parsed value as either True or False.
597 e7b61bb0 Iustin Pop

598 e7b61bb0 Iustin Pop
  """
599 e7b61bb0 Iustin Pop
  value = value.lower()
600 e7b61bb0 Iustin Pop
  if value == constants.VALUE_FALSE or value == "no":
601 e7b61bb0 Iustin Pop
    return False
602 e7b61bb0 Iustin Pop
  elif value == constants.VALUE_TRUE or value == "yes":
603 e7b61bb0 Iustin Pop
    return True
604 e7b61bb0 Iustin Pop
  else:
605 e7b61bb0 Iustin Pop
    raise errors.ParameterError("Invalid boolean value '%s'" % value)
606 e7b61bb0 Iustin Pop
607 e7b61bb0 Iustin Pop
608 499eb088 Iustin Pop
def check_list(option, opt, value): # pylint: disable=W0613
609 499eb088 Iustin Pop
  """Custom parser for comma-separated lists.
610 499eb088 Iustin Pop

611 499eb088 Iustin Pop
  """
612 499eb088 Iustin Pop
  # we have to make this explicit check since "".split(",") is [""],
613 499eb088 Iustin Pop
  # not an empty list :(
614 499eb088 Iustin Pop
  if not value:
615 499eb088 Iustin Pop
    return []
616 499eb088 Iustin Pop
  else:
617 499eb088 Iustin Pop
    return utils.UnescapeAndSplit(value)
618 499eb088 Iustin Pop
619 499eb088 Iustin Pop
620 cd415612 René Nussbaumer
def check_maybefloat(option, opt, value): # pylint: disable=W0613
621 cd415612 René Nussbaumer
  """Custom parser for float numbers which might be also defaults.
622 cd415612 René Nussbaumer

623 cd415612 René Nussbaumer
  """
624 cd415612 René Nussbaumer
  value = value.lower()
625 cd415612 René Nussbaumer
626 cd415612 René Nussbaumer
  if value == constants.VALUE_DEFAULT:
627 cd415612 René Nussbaumer
    return value
628 cd415612 René Nussbaumer
  else:
629 cd415612 René Nussbaumer
    return float(value)
630 cd415612 René Nussbaumer
631 cd415612 René Nussbaumer
632 63d44c55 Michael Hanselmann
# completion_suggestion is normally a list. Using numeric values not evaluating
633 63d44c55 Michael Hanselmann
# to False for dynamic completion.
634 63d44c55 Michael Hanselmann
(OPT_COMPL_MANY_NODES,
635 63d44c55 Michael Hanselmann
 OPT_COMPL_ONE_NODE,
636 63d44c55 Michael Hanselmann
 OPT_COMPL_ONE_INSTANCE,
637 63d44c55 Michael Hanselmann
 OPT_COMPL_ONE_OS,
638 2d3ed64b Michael Hanselmann
 OPT_COMPL_ONE_IALLOCATOR,
639 36e247e1 Guido Trotter
 OPT_COMPL_INST_ADD_NODES,
640 36e247e1 Guido Trotter
 OPT_COMPL_ONE_NODEGROUP) = range(100, 107)
641 63d44c55 Michael Hanselmann
642 63d44c55 Michael Hanselmann
OPT_COMPL_ALL = frozenset([
643 63d44c55 Michael Hanselmann
  OPT_COMPL_MANY_NODES,
644 63d44c55 Michael Hanselmann
  OPT_COMPL_ONE_NODE,
645 63d44c55 Michael Hanselmann
  OPT_COMPL_ONE_INSTANCE,
646 63d44c55 Michael Hanselmann
  OPT_COMPL_ONE_OS,
647 63d44c55 Michael Hanselmann
  OPT_COMPL_ONE_IALLOCATOR,
648 2d3ed64b Michael Hanselmann
  OPT_COMPL_INST_ADD_NODES,
649 36e247e1 Guido Trotter
  OPT_COMPL_ONE_NODEGROUP,
650 63d44c55 Michael Hanselmann
  ])
651 63d44c55 Michael Hanselmann
652 63d44c55 Michael Hanselmann
653 552c8dff Michael Hanselmann
class CliOption(Option):
654 552c8dff Michael Hanselmann
  """Custom option class for optparse.
655 a8469393 Iustin Pop

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

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

1480 c41eea6e Iustin Pop
  @param argv: the command line
1481 c41eea6e Iustin Pop
  @param commands: dictionary with special contents, see the design
1482 c41eea6e Iustin Pop
      doc for cmdline handling
1483 c41eea6e Iustin Pop
  @param aliases: dictionary with command aliases {'alias': 'target, ...}
1484 ef9fa5b9 René Nussbaumer
  @param env_override: list of env variables allowed for default args
1485 098c0958 Michael Hanselmann

1486 a8083063 Iustin Pop
  """
1487 ef9fa5b9 René Nussbaumer
  assert not (env_override - set(commands))
1488 ef9fa5b9 René Nussbaumer
1489 a8083063 Iustin Pop
  if len(argv) == 0:
1490 a8083063 Iustin Pop
    binary = "<command>"
1491 a8083063 Iustin Pop
  else:
1492 a8083063 Iustin Pop
    binary = argv[0].split("/")[-1]
1493 a8083063 Iustin Pop
1494 a8083063 Iustin Pop
  if len(argv) > 1 and argv[1] == "--version":
1495 84a12e40 Iustin Pop
    ToStdout("%s (ganeti %s) %s", binary, constants.VCS_VERSION,
1496 84a12e40 Iustin Pop
             constants.RELEASE_VERSION)
1497 a8083063 Iustin Pop
    # Quit right away. That way we don't have to care about this special
1498 a8083063 Iustin Pop
    # argument. optparse.py does it the same.
1499 a8083063 Iustin Pop
    sys.exit(0)
1500 a8083063 Iustin Pop
1501 de47cf8f Guido Trotter
  if len(argv) < 2 or not (argv[1] in commands or
1502 70a35b6f Guido Trotter
                           argv[1] in aliases):
1503 a8083063 Iustin Pop
    # let's do a nice thing
1504 a8083063 Iustin Pop
    sortedcmds = commands.keys()
1505 a8083063 Iustin Pop
    sortedcmds.sort()
1506 03298ebe Michael Hanselmann
1507 03298ebe Michael Hanselmann
    ToStdout("Usage: %s {command} [options...] [argument...]", binary)
1508 03298ebe Michael Hanselmann
    ToStdout("%s <command> --help to see details, or man %s", binary, binary)
1509 03298ebe Michael Hanselmann
    ToStdout("")
1510 03298ebe Michael Hanselmann
1511 a8083063 Iustin Pop
    # compute the max line length for cmd + usage
1512 4e713df6 Iustin Pop
    mlen = max([len(" %s" % cmd) for cmd in commands])
1513 a8083063 Iustin Pop
    mlen = min(60, mlen) # should not get here...
1514 03298ebe Michael Hanselmann
1515 a8083063 Iustin Pop
    # and format a nice command list
1516 03298ebe Michael Hanselmann
    ToStdout("Commands:")
1517 a8083063 Iustin Pop
    for cmd in sortedcmds:
1518 4e713df6 Iustin Pop
      cmdstr = " %s" % (cmd,)
1519 9a033156 Iustin Pop
      help_text = commands[cmd][4]
1520 03298ebe Michael Hanselmann
      help_lines = textwrap.wrap(help_text, 79 - 3 - mlen)
1521 03298ebe Michael Hanselmann
      ToStdout("%-*s - %s", mlen, cmdstr, help_lines.pop(0))
1522 a8083063 Iustin Pop
      for line in help_lines:
1523 03298ebe Michael Hanselmann
        ToStdout("%-*s   %s", mlen, "", line)
1524 03298ebe Michael Hanselmann
1525 03298ebe Michael Hanselmann
    ToStdout("")
1526 03298ebe Michael Hanselmann
1527 a8083063 Iustin Pop
    return None, None, None
1528 de47cf8f Guido Trotter
1529 de47cf8f Guido Trotter
  # get command, unalias it, and look it up in commands
1530 a8083063 Iustin Pop
  cmd = argv.pop(1)
1531 de47cf8f Guido Trotter
  if cmd in aliases:
1532 de47cf8f Guido Trotter
    if cmd in commands:
1533 de47cf8f Guido Trotter
      raise errors.ProgrammerError("Alias '%s' overrides an existing"
1534 de47cf8f Guido Trotter
                                   " command" % cmd)
1535 de47cf8f Guido Trotter
1536 de47cf8f Guido Trotter
    if aliases[cmd] not in commands:
1537 de47cf8f Guido Trotter
      raise errors.ProgrammerError("Alias '%s' maps to non-existing"
1538 de47cf8f Guido Trotter
                                   " command '%s'" % (cmd, aliases[cmd]))
1539 de47cf8f Guido Trotter
1540 de47cf8f Guido Trotter
    cmd = aliases[cmd]
1541 de47cf8f Guido Trotter
1542 ef9fa5b9 René Nussbaumer
  if cmd in env_override:
1543 ef9fa5b9 René Nussbaumer
    args_env_name = ("%s_%s" % (binary.replace("-", "_"), cmd)).upper()
1544 ef9fa5b9 René Nussbaumer
    env_args = os.environ.get(args_env_name)
1545 ef9fa5b9 René Nussbaumer
    if env_args:
1546 ef9fa5b9 René Nussbaumer
      argv = utils.InsertAtPos(argv, 1, shlex.split(env_args))
1547 ef9fa5b9 René Nussbaumer
1548 a8005e17 Michael Hanselmann
  func, args_def, parser_opts, usage, description = commands[cmd]
1549 bf5338b3 Michael Hanselmann
  parser = OptionParser(option_list=parser_opts + COMMON_OPTS,
1550 bf5338b3 Michael Hanselmann
                        description=description,
1551 bf5338b3 Michael Hanselmann
                        formatter=TitledHelpFormatter(),
1552 bf5338b3 Michael Hanselmann
                        usage="%%prog %s %s" % (cmd, usage))
1553 a8083063 Iustin Pop
  parser.disable_interspersed_args()
1554 ef9fa5b9 René Nussbaumer
  options, args = parser.parse_args(args=argv[1:])
1555 a8005e17 Michael Hanselmann
1556 a8005e17 Michael Hanselmann
  if not _CheckArguments(cmd, args_def, args):
1557 a8083063 Iustin Pop
    return None, None, None
1558 a8083063 Iustin Pop
1559 a8083063 Iustin Pop
  return func, options, args
1560 a8083063 Iustin Pop
1561 a8083063 Iustin Pop
1562 a8005e17 Michael Hanselmann
def _CheckArguments(cmd, args_def, args):
1563 a8005e17 Michael Hanselmann
  """Verifies the arguments using the argument definition.
1564 a8005e17 Michael Hanselmann

1565 a8005e17 Michael Hanselmann
  Algorithm:
1566 a8005e17 Michael Hanselmann

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

1569 a8005e17 Michael Hanselmann
    1. For each argument in definition
1570 a8005e17 Michael Hanselmann

1571 a8005e17 Michael Hanselmann
      1. Keep running count of minimum number of values (min_count)
1572 a8005e17 Michael Hanselmann
      1. Keep running count of maximum number of values (max_count)
1573 a8005e17 Michael Hanselmann
      1. If it has an unlimited number of values
1574 a8005e17 Michael Hanselmann

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

1577 a8005e17 Michael Hanselmann
    1. If last argument has limited number of values
1578 a8005e17 Michael Hanselmann

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

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

1583 a8005e17 Michael Hanselmann
  """
1584 a8005e17 Michael Hanselmann
  if args and not args_def:
1585 a8005e17 Michael Hanselmann
    ToStderr("Error: Command %s expects no arguments", cmd)
1586 a8005e17 Michael Hanselmann
    return False
1587 a8005e17 Michael Hanselmann
1588 a8005e17 Michael Hanselmann
  min_count = None
1589 a8005e17 Michael Hanselmann
  max_count = None
1590 a8005e17 Michael Hanselmann
  check_max = None
1591 a8005e17 Michael Hanselmann
1592 a8005e17 Michael Hanselmann
  last_idx = len(args_def) - 1
1593 a8005e17 Michael Hanselmann
1594 a8005e17 Michael Hanselmann
  for idx, arg in enumerate(args_def):
1595 a8005e17 Michael Hanselmann
    if min_count is None:
1596 a8005e17 Michael Hanselmann
      min_count = arg.min
1597 a8005e17 Michael Hanselmann
    elif arg.min is not None:
1598 a8005e17 Michael Hanselmann
      min_count += arg.min
1599 a8005e17 Michael Hanselmann
1600 a8005e17 Michael Hanselmann
    if max_count is None:
1601 a8005e17 Michael Hanselmann
      max_count = arg.max
1602 a8005e17 Michael Hanselmann
    elif arg.max is not None:
1603 a8005e17 Michael Hanselmann
      max_count += arg.max
1604 a8005e17 Michael Hanselmann
1605 a8005e17 Michael Hanselmann
    if idx == last_idx:
1606 a8005e17 Michael Hanselmann
      check_max = (arg.max is not None)
1607 a8005e17 Michael Hanselmann
1608 a8005e17 Michael Hanselmann
    elif arg.max is None:
1609 a8005e17 Michael Hanselmann
      raise errors.ProgrammerError("Only the last argument can have max=None")
1610 a8005e17 Michael Hanselmann
1611 a8005e17 Michael Hanselmann
  if check_max:
1612 a8005e17 Michael Hanselmann
    # Command with exact number of arguments
1613 a8005e17 Michael Hanselmann
    if (min_count is not None and max_count is not None and
1614 a8005e17 Michael Hanselmann
        min_count == max_count and len(args) != min_count):
1615 a8005e17 Michael Hanselmann
      ToStderr("Error: Command %s expects %d argument(s)", cmd, min_count)
1616 a8005e17 Michael Hanselmann
      return False
1617 a8005e17 Michael Hanselmann
1618 a8005e17 Michael Hanselmann
    # Command with limited number of arguments
1619 a8005e17 Michael Hanselmann
    if max_count is not None and len(args) > max_count:
1620 a8005e17 Michael Hanselmann
      ToStderr("Error: Command %s expects only %d argument(s)",
1621 a8005e17 Michael Hanselmann
               cmd, max_count)
1622 a8005e17 Michael Hanselmann
      return False
1623 a8005e17 Michael Hanselmann
1624 a8005e17 Michael Hanselmann
  # Command with some required arguments
1625 a8005e17 Michael Hanselmann
  if min_count is not None and len(args) < min_count:
1626 a8005e17 Michael Hanselmann
    ToStderr("Error: Command %s expects at least %d argument(s)",
1627 a8005e17 Michael Hanselmann
             cmd, min_count)
1628 a8005e17 Michael Hanselmann
    return False
1629 a8005e17 Michael Hanselmann
1630 a8005e17 Michael Hanselmann
  return True
1631 a8005e17 Michael Hanselmann
1632 a8005e17 Michael Hanselmann
1633 60d49723 Michael Hanselmann
def SplitNodeOption(value):
1634 60d49723 Michael Hanselmann
  """Splits the value of a --node option.
1635 60d49723 Michael Hanselmann

1636 60d49723 Michael Hanselmann
  """
1637 d0c8c01d Iustin Pop
  if value and ":" in value:
1638 d0c8c01d Iustin Pop
    return value.split(":", 1)
1639 60d49723 Michael Hanselmann
  else:
1640 60d49723 Michael Hanselmann
    return (value, None)
1641 60d49723 Michael Hanselmann
1642 60d49723 Michael Hanselmann
1643 07150497 Guido Trotter
def CalculateOSNames(os_name, os_variants):
1644 07150497 Guido Trotter
  """Calculates all the names an OS can be called, according to its variants.
1645 07150497 Guido Trotter

1646 07150497 Guido Trotter
  @type os_name: string
1647 07150497 Guido Trotter
  @param os_name: base name of the os
1648 07150497 Guido Trotter
  @type os_variants: list or None
1649 07150497 Guido Trotter
  @param os_variants: list of supported variants
1650 07150497 Guido Trotter
  @rtype: list
1651 07150497 Guido Trotter
  @return: list of valid names
1652 07150497 Guido Trotter

1653 07150497 Guido Trotter
  """
1654 07150497 Guido Trotter
  if os_variants:
1655 d0c8c01d Iustin Pop
    return ["%s+%s" % (os_name, v) for v in os_variants]
1656 07150497 Guido Trotter
  else:
1657 07150497 Guido Trotter
    return [os_name]
1658 07150497 Guido Trotter
1659 07150497 Guido Trotter
1660 a4ebd726 Michael Hanselmann
def ParseFields(selected, default):
1661 a4ebd726 Michael Hanselmann
  """Parses the values of "--field"-like options.
1662 a4ebd726 Michael Hanselmann

1663 a4ebd726 Michael Hanselmann
  @type selected: string or None
1664 a4ebd726 Michael Hanselmann
  @param selected: User-selected options
1665 a4ebd726 Michael Hanselmann
  @type default: list
1666 a4ebd726 Michael Hanselmann
  @param default: Default fields
1667 a4ebd726 Michael Hanselmann

1668 a4ebd726 Michael Hanselmann
  """
1669 a4ebd726 Michael Hanselmann
  if selected is None:
1670 a4ebd726 Michael Hanselmann
    return default
1671 a4ebd726 Michael Hanselmann
1672 a4ebd726 Michael Hanselmann
  if selected.startswith("+"):
1673 a4ebd726 Michael Hanselmann
    return default + selected[1:].split(",")
1674 a4ebd726 Michael Hanselmann
1675 a4ebd726 Michael Hanselmann
  return selected.split(",")
1676 a4ebd726 Michael Hanselmann
1677 a4ebd726 Michael Hanselmann
1678 e0e916fe Iustin Pop
UsesRPC = rpc.RunWithRPC
1679 4331f6cd Michael Hanselmann
1680 4331f6cd Michael Hanselmann
1681 47988778 Iustin Pop
def AskUser(text, choices=None):
1682 47988778 Iustin Pop
  """Ask the user a question.
1683 a8083063 Iustin Pop

1684 c41eea6e Iustin Pop
  @param text: the question to ask
1685 a8083063 Iustin Pop

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

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

1695 a8083063 Iustin Pop
  """
1696 47988778 Iustin Pop
  if choices is None:
1697 d0c8c01d Iustin Pop
    choices = [("y", True, "Perform the operation"),
1698 d0c8c01d Iustin Pop
               ("n", False, "Do not perform the operation")]
1699 47988778 Iustin Pop
  if not choices or not isinstance(choices, list):
1700 5bbd3f7f Michael Hanselmann
    raise errors.ProgrammerError("Invalid choices argument to AskUser")
1701 47988778 Iustin Pop
  for entry in choices:
1702 d0c8c01d Iustin Pop
    if not isinstance(entry, tuple) or len(entry) < 3 or entry[0] == "?":
1703 5bbd3f7f Michael Hanselmann
      raise errors.ProgrammerError("Invalid choices element to AskUser")
1704 47988778 Iustin Pop
1705 47988778 Iustin Pop
  answer = choices[-1][1]
1706 47988778 Iustin Pop
  new_text = []
1707 47988778 Iustin Pop
  for line in text.splitlines():
1708 47988778 Iustin Pop
    new_text.append(textwrap.fill(line, 70, replace_whitespace=False))
1709 47988778 Iustin Pop
  text = "\n".join(new_text)
1710 a8083063 Iustin Pop
  try:
1711 3023170f Iustin Pop
    f = file("/dev/tty", "a+")
1712 a8083063 Iustin Pop
  except IOError:
1713 47988778 Iustin Pop
    return answer
1714 a8083063 Iustin Pop
  try:
1715 47988778 Iustin Pop
    chars = [entry[0] for entry in choices]
1716 47988778 Iustin Pop
    chars[-1] = "[%s]" % chars[-1]
1717 d0c8c01d Iustin Pop
    chars.append("?")
1718 47988778 Iustin Pop
    maps = dict([(entry[0], entry[1]) for entry in choices])
1719 47988778 Iustin Pop
    while True:
1720 47988778 Iustin Pop
      f.write(text)
1721 d0c8c01d Iustin Pop
      f.write("\n")
1722 47988778 Iustin Pop
      f.write("/".join(chars))
1723 47988778 Iustin Pop
      f.write(": ")
1724 47988778 Iustin Pop
      line = f.readline(2).strip().lower()
1725 47988778 Iustin Pop
      if line in maps:
1726 47988778 Iustin Pop
        answer = maps[line]
1727 47988778 Iustin Pop
        break
1728 d0c8c01d Iustin Pop
      elif line == "?":
1729 47988778 Iustin Pop
        for entry in choices:
1730 47988778 Iustin Pop
          f.write(" %s - %s\n" % (entry[0], entry[2]))
1731 47988778 Iustin Pop
        f.write("\n")
1732 47988778 Iustin Pop
        continue
1733 a8083063 Iustin Pop
  finally:
1734 a8083063 Iustin Pop
    f.close()
1735 a8083063 Iustin Pop
  return answer
1736 a8083063 Iustin Pop
1737 a8083063 Iustin Pop
1738 e9d741b6 Iustin Pop
class JobSubmittedException(Exception):
1739 e9d741b6 Iustin Pop
  """Job was submitted, client should exit.
1740 e9d741b6 Iustin Pop

1741 e9d741b6 Iustin Pop
  This exception has one argument, the ID of the job that was
1742 e9d741b6 Iustin Pop
  submitted. The handler should print this ID.
1743 e9d741b6 Iustin Pop

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

1746 e9d741b6 Iustin Pop
  """
1747 e9d741b6 Iustin Pop
1748 e9d741b6 Iustin Pop
1749 0a1e74d9 Iustin Pop
def SendJob(ops, cl=None):
1750 0a1e74d9 Iustin Pop
  """Function to submit an opcode without waiting for the results.
1751 a8083063 Iustin Pop

1752 0a1e74d9 Iustin Pop
  @type ops: list
1753 0a1e74d9 Iustin Pop
  @param ops: list of opcodes
1754 0a1e74d9 Iustin Pop
  @type cl: luxi.Client
1755 0a1e74d9 Iustin Pop
  @param cl: the luxi client to use for communicating with the master;
1756 0a1e74d9 Iustin Pop
             if None, a new client will be created
1757 a8083063 Iustin Pop

1758 a8083063 Iustin Pop
  """
1759 e2212007 Iustin Pop
  if cl is None:
1760 b33e986b Iustin Pop
    cl = GetClient()
1761 685ee993 Iustin Pop
1762 0a1e74d9 Iustin Pop
  job_id = cl.SubmitJob(ops)
1763 0a1e74d9 Iustin Pop
1764 0a1e74d9 Iustin Pop
  return job_id
1765 0a1e74d9 Iustin Pop
1766 0a1e74d9 Iustin Pop
1767 4e338533 Michael Hanselmann
def GenericPollJob(job_id, cbs, report_cbs):
1768 4e338533 Michael Hanselmann
  """Generic job-polling function.
1769 0a1e74d9 Iustin Pop

1770 4e338533 Michael Hanselmann
  @type job_id: number
1771 4e338533 Michael Hanselmann
  @param job_id: Job ID
1772 4e338533 Michael Hanselmann
  @type cbs: Instance of L{JobPollCbBase}
1773 4e338533 Michael Hanselmann
  @param cbs: Data callbacks
1774 4e338533 Michael Hanselmann
  @type report_cbs: Instance of L{JobPollReportCbBase}
1775 4e338533 Michael Hanselmann
  @param report_cbs: Reporting callbacks
1776 0a1e74d9 Iustin Pop

1777 0a1e74d9 Iustin Pop
  """
1778 6c5a7090 Michael Hanselmann
  prev_job_info = None
1779 6c5a7090 Michael Hanselmann
  prev_logmsg_serial = None
1780 6c5a7090 Michael Hanselmann
1781 f4484122 Michael Hanselmann
  status = None
1782 f4484122 Michael Hanselmann
1783 685ee993 Iustin Pop
  while True:
1784 4e338533 Michael Hanselmann
    result = cbs.WaitForJobChangeOnce(job_id, ["status"], prev_job_info,
1785 4e338533 Michael Hanselmann
                                      prev_logmsg_serial)
1786 6c5a7090 Michael Hanselmann
    if not result:
1787 685ee993 Iustin Pop
      # job not found, go away!
1788 0bbe448c Michael Hanselmann
      raise errors.JobLost("Job with id %s lost" % job_id)
1789 4e338533 Michael Hanselmann
1790 4e338533 Michael Hanselmann
    if result == constants.JOB_NOTCHANGED:
1791 4e338533 Michael Hanselmann
      report_cbs.ReportNotChanged(job_id, status)
1792 f4484122 Michael Hanselmann
1793 f4484122 Michael Hanselmann
      # Wait again
1794 f4484122 Michael Hanselmann
      continue
1795 685ee993 Iustin Pop
1796 6c5a7090 Michael Hanselmann
    # Split result, a tuple of (field values, log entries)
1797 6c5a7090 Michael Hanselmann
    (job_info, log_entries) = result
1798 6c5a7090 Michael Hanselmann
    (status, ) = job_info
1799 6c5a7090 Michael Hanselmann
1800 6c5a7090 Michael Hanselmann
    if log_entries:
1801 6c5a7090 Michael Hanselmann
      for log_entry in log_entries:
1802 4e338533 Michael Hanselmann
        (serial, timestamp, log_type, message) = log_entry
1803 4e338533 Michael Hanselmann
        report_cbs.ReportLogMessage(job_id, serial, timestamp,
1804 4e338533 Michael Hanselmann
                                    log_type, message)
1805 6c5a7090 Michael Hanselmann
        prev_logmsg_serial = max(prev_logmsg_serial, serial)
1806 6c5a7090 Michael Hanselmann
1807 0bbe448c Michael Hanselmann
    # TODO: Handle canceled and archived jobs
1808 fbf0262f Michael Hanselmann
    elif status in (constants.JOB_STATUS_SUCCESS,
1809 fbf0262f Michael Hanselmann
                    constants.JOB_STATUS_ERROR,
1810 fbf0262f Michael Hanselmann
                    constants.JOB_STATUS_CANCELING,
1811 fbf0262f Michael Hanselmann
                    constants.JOB_STATUS_CANCELED):
1812 685ee993 Iustin Pop
      break
1813 6c5a7090 Michael Hanselmann
1814 6c5a7090 Michael Hanselmann
    prev_job_info = job_info
1815 685ee993 Iustin Pop
1816 4e338533 Michael Hanselmann
  jobs = cbs.QueryJobs([job_id], ["status", "opstatus", "opresult"])
1817 0bbe448c Michael Hanselmann
  if not jobs:
1818 0bbe448c Michael Hanselmann
    raise errors.JobLost("Job with id %s lost" % job_id)
1819 685ee993 Iustin Pop
1820 0e050889 Iustin Pop
  status, opstatus, result = jobs[0]
1821 4e338533 Michael Hanselmann
1822 0bbe448c Michael Hanselmann
  if status == constants.JOB_STATUS_SUCCESS:
1823 53c04d04 Iustin Pop
    return result
1824 4e338533 Michael Hanselmann
1825 4e338533 Michael Hanselmann
  if status in (constants.JOB_STATUS_CANCELING, constants.JOB_STATUS_CANCELED):
1826 fbf0262f Michael Hanselmann
    raise errors.OpExecError("Job was canceled")
1827 4e338533 Michael Hanselmann
1828 4e338533 Michael Hanselmann
  has_ok = False
1829 4e338533 Michael Hanselmann
  for idx, (status, msg) in enumerate(zip(opstatus, result)):
1830 4e338533 Michael Hanselmann
    if status == constants.OP_STATUS_SUCCESS:
1831 4e338533 Michael Hanselmann
      has_ok = True
1832 4e338533 Michael Hanselmann
    elif status == constants.OP_STATUS_ERROR:
1833 4e338533 Michael Hanselmann
      errors.MaybeRaise(msg)
1834 4e338533 Michael Hanselmann
1835 4e338533 Michael Hanselmann
      if has_ok:
1836 4e338533 Michael Hanselmann
        raise errors.OpExecError("partial failure (opcode %d): %s" %
1837 4e338533 Michael Hanselmann
                                 (idx, msg))
1838 4e338533 Michael Hanselmann
1839 4e338533 Michael Hanselmann
      raise errors.OpExecError(str(msg))
1840 4e338533 Michael Hanselmann
1841 4e338533 Michael Hanselmann
  # default failure mode
1842 4e338533 Michael Hanselmann
  raise errors.OpExecError(result)
1843 4e338533 Michael Hanselmann
1844 4e338533 Michael Hanselmann
1845 4e338533 Michael Hanselmann
class JobPollCbBase:
1846 4e338533 Michael Hanselmann
  """Base class for L{GenericPollJob} callbacks.
1847 4e338533 Michael Hanselmann

1848 4e338533 Michael Hanselmann
  """
1849 4e338533 Michael Hanselmann
  def __init__(self):
1850 4e338533 Michael Hanselmann
    """Initializes this class.
1851 4e338533 Michael Hanselmann

1852 4e338533 Michael Hanselmann
    """
1853 4e338533 Michael Hanselmann
1854 4e338533 Michael Hanselmann
  def WaitForJobChangeOnce(self, job_id, fields,
1855 4e338533 Michael Hanselmann
                           prev_job_info, prev_log_serial):
1856 4e338533 Michael Hanselmann
    """Waits for changes on a job.
1857 4e338533 Michael Hanselmann

1858 4e338533 Michael Hanselmann
    """
1859 4e338533 Michael Hanselmann
    raise NotImplementedError()
1860 4e338533 Michael Hanselmann
1861 4e338533 Michael Hanselmann
  def QueryJobs(self, job_ids, fields):
1862 4e338533 Michael Hanselmann
    """Returns the selected fields for the selected job IDs.
1863 4e338533 Michael Hanselmann

1864 4e338533 Michael Hanselmann
    @type job_ids: list of numbers
1865 4e338533 Michael Hanselmann
    @param job_ids: Job IDs
1866 4e338533 Michael Hanselmann
    @type fields: list of strings
1867 4e338533 Michael Hanselmann
    @param fields: Fields
1868 4e338533 Michael Hanselmann

1869 4e338533 Michael Hanselmann
    """
1870 4e338533 Michael Hanselmann
    raise NotImplementedError()
1871 4e338533 Michael Hanselmann
1872 4e338533 Michael Hanselmann
1873 4e338533 Michael Hanselmann
class JobPollReportCbBase:
1874 4e338533 Michael Hanselmann
  """Base class for L{GenericPollJob} reporting callbacks.
1875 4e338533 Michael Hanselmann

1876 4e338533 Michael Hanselmann
  """
1877 4e338533 Michael Hanselmann
  def __init__(self):
1878 4e338533 Michael Hanselmann
    """Initializes this class.
1879 4e338533 Michael Hanselmann

1880 4e338533 Michael Hanselmann
    """
1881 4e338533 Michael Hanselmann
1882 4e338533 Michael Hanselmann
  def ReportLogMessage(self, job_id, serial, timestamp, log_type, log_msg):
1883 4e338533 Michael Hanselmann
    """Handles a log message.
1884 4e338533 Michael Hanselmann

1885 4e338533 Michael Hanselmann
    """
1886 4e338533 Michael Hanselmann
    raise NotImplementedError()
1887 4e338533 Michael Hanselmann
1888 4e338533 Michael Hanselmann
  def ReportNotChanged(self, job_id, status):
1889 4e338533 Michael Hanselmann
    """Called for if a job hasn't changed in a while.
1890 4e338533 Michael Hanselmann

1891 4e338533 Michael Hanselmann
    @type job_id: number
1892 4e338533 Michael Hanselmann
    @param job_id: Job ID
1893 4e338533 Michael Hanselmann
    @type status: string or None
1894 4e338533 Michael Hanselmann
    @param status: Job status if available
1895 4e338533 Michael Hanselmann

1896 4e338533 Michael Hanselmann
    """
1897 4e338533 Michael Hanselmann
    raise NotImplementedError()
1898 4e338533 Michael Hanselmann
1899 4e338533 Michael Hanselmann
1900 4e338533 Michael Hanselmann
class _LuxiJobPollCb(JobPollCbBase):
1901 4e338533 Michael Hanselmann
  def __init__(self, cl):
1902 4e338533 Michael Hanselmann
    """Initializes this class.
1903 4e338533 Michael Hanselmann

1904 4e338533 Michael Hanselmann
    """
1905 4e338533 Michael Hanselmann
    JobPollCbBase.__init__(self)
1906 4e338533 Michael Hanselmann
    self.cl = cl
1907 4e338533 Michael Hanselmann
1908 4e338533 Michael Hanselmann
  def WaitForJobChangeOnce(self, job_id, fields,
1909 4e338533 Michael Hanselmann
                           prev_job_info, prev_log_serial):
1910 4e338533 Michael Hanselmann
    """Waits for changes on a job.
1911 4e338533 Michael Hanselmann

1912 4e338533 Michael Hanselmann
    """
1913 4e338533 Michael Hanselmann
    return self.cl.WaitForJobChangeOnce(job_id, fields,
1914 4e338533 Michael Hanselmann
                                        prev_job_info, prev_log_serial)
1915 4e338533 Michael Hanselmann
1916 4e338533 Michael Hanselmann
  def QueryJobs(self, job_ids, fields):
1917 4e338533 Michael Hanselmann
    """Returns the selected fields for the selected job IDs.
1918 4e338533 Michael Hanselmann

1919 4e338533 Michael Hanselmann
    """
1920 4e338533 Michael Hanselmann
    return self.cl.QueryJobs(job_ids, fields)
1921 4e338533 Michael Hanselmann
1922 4e338533 Michael Hanselmann
1923 4e338533 Michael Hanselmann
class FeedbackFnJobPollReportCb(JobPollReportCbBase):
1924 4e338533 Michael Hanselmann
  def __init__(self, feedback_fn):
1925 4e338533 Michael Hanselmann
    """Initializes this class.
1926 4e338533 Michael Hanselmann

1927 4e338533 Michael Hanselmann
    """
1928 4e338533 Michael Hanselmann
    JobPollReportCbBase.__init__(self)
1929 4e338533 Michael Hanselmann
1930 4e338533 Michael Hanselmann
    self.feedback_fn = feedback_fn
1931 4e338533 Michael Hanselmann
1932 4e338533 Michael Hanselmann
    assert callable(feedback_fn)
1933 4e338533 Michael Hanselmann
1934 4e338533 Michael Hanselmann
  def ReportLogMessage(self, job_id, serial, timestamp, log_type, log_msg):
1935 4e338533 Michael Hanselmann
    """Handles a log message.
1936 4e338533 Michael Hanselmann

1937 4e338533 Michael Hanselmann
    """
1938 4e338533 Michael Hanselmann
    self.feedback_fn((timestamp, log_type, log_msg))
1939 4e338533 Michael Hanselmann
1940 4e338533 Michael Hanselmann
  def ReportNotChanged(self, job_id, status):
1941 4e338533 Michael Hanselmann
    """Called if a job hasn't changed in a while.
1942 4e338533 Michael Hanselmann

1943 4e338533 Michael Hanselmann
    """
1944 4e338533 Michael Hanselmann
    # Ignore
1945 4e338533 Michael Hanselmann
1946 4e338533 Michael Hanselmann
1947 4e338533 Michael Hanselmann
class StdioJobPollReportCb(JobPollReportCbBase):
1948 4e338533 Michael Hanselmann
  def __init__(self):
1949 4e338533 Michael Hanselmann
    """Initializes this class.
1950 4e338533 Michael Hanselmann

1951 4e338533 Michael Hanselmann
    """
1952 4e338533 Michael Hanselmann
    JobPollReportCbBase.__init__(self)
1953 4e338533 Michael Hanselmann
1954 4e338533 Michael Hanselmann
    self.notified_queued = False
1955 4e338533 Michael Hanselmann
    self.notified_waitlock = False
1956 4e338533 Michael Hanselmann
1957 4e338533 Michael Hanselmann
  def ReportLogMessage(self, job_id, serial, timestamp, log_type, log_msg):
1958 4e338533 Michael Hanselmann
    """Handles a log message.
1959 4e338533 Michael Hanselmann

1960 4e338533 Michael Hanselmann
    """
1961 4e338533 Michael Hanselmann
    ToStdout("%s %s", time.ctime(utils.MergeTime(timestamp)),
1962 8a7f1c61 Michael Hanselmann
             FormatLogMessage(log_type, log_msg))
1963 4e338533 Michael Hanselmann
1964 4e338533 Michael Hanselmann
  def ReportNotChanged(self, job_id, status):
1965 4e338533 Michael Hanselmann
    """Called if a job hasn't changed in a while.
1966 4e338533 Michael Hanselmann

1967 4e338533 Michael Hanselmann
    """
1968 4e338533 Michael Hanselmann
    if status is None:
1969 4e338533 Michael Hanselmann
      return
1970 4e338533 Michael Hanselmann
1971 4e338533 Michael Hanselmann
    if status == constants.JOB_STATUS_QUEUED and not self.notified_queued:
1972 4e338533 Michael Hanselmann
      ToStderr("Job %s is waiting in queue", job_id)
1973 4e338533 Michael Hanselmann
      self.notified_queued = True
1974 4e338533 Michael Hanselmann
1975 47099cd1 Michael Hanselmann
    elif status == constants.JOB_STATUS_WAITING and not self.notified_waitlock:
1976 4e338533 Michael Hanselmann
      ToStderr("Job %s is trying to acquire all necessary locks", job_id)
1977 4e338533 Michael Hanselmann
      self.notified_waitlock = True
1978 4e338533 Michael Hanselmann
1979 4e338533 Michael Hanselmann
1980 8a7f1c61 Michael Hanselmann
def FormatLogMessage(log_type, log_msg):
1981 8a7f1c61 Michael Hanselmann
  """Formats a job message according to its type.
1982 8a7f1c61 Michael Hanselmann

1983 8a7f1c61 Michael Hanselmann
  """
1984 8a7f1c61 Michael Hanselmann
  if log_type != constants.ELOG_MESSAGE:
1985 8a7f1c61 Michael Hanselmann
    log_msg = str(log_msg)
1986 8a7f1c61 Michael Hanselmann
1987 8a7f1c61 Michael Hanselmann
  return utils.SafeEncode(log_msg)
1988 8a7f1c61 Michael Hanselmann
1989 8a7f1c61 Michael Hanselmann
1990 583163a6 Michael Hanselmann
def PollJob(job_id, cl=None, feedback_fn=None, reporter=None):
1991 4e338533 Michael Hanselmann
  """Function to poll for the result of a job.
1992 4e338533 Michael Hanselmann

1993 4e338533 Michael Hanselmann
  @type job_id: job identified
1994 4e338533 Michael Hanselmann
  @param job_id: the job to poll for results
1995 4e338533 Michael Hanselmann
  @type cl: luxi.Client
1996 4e338533 Michael Hanselmann
  @param cl: the luxi client to use for communicating with the master;
1997 4e338533 Michael Hanselmann
             if None, a new client will be created
1998 4e338533 Michael Hanselmann

1999 4e338533 Michael Hanselmann
  """
2000 4e338533 Michael Hanselmann
  if cl is None:
2001 4e338533 Michael Hanselmann
    cl = GetClient()
2002 4e338533 Michael Hanselmann
2003 583163a6 Michael Hanselmann
  if reporter is None:
2004 583163a6 Michael Hanselmann
    if feedback_fn:
2005 583163a6 Michael Hanselmann
      reporter = FeedbackFnJobPollReportCb(feedback_fn)
2006 583163a6 Michael Hanselmann
    else:
2007 583163a6 Michael Hanselmann
      reporter = StdioJobPollReportCb()
2008 583163a6 Michael Hanselmann
  elif feedback_fn:
2009 583163a6 Michael Hanselmann
    raise errors.ProgrammerError("Can't specify reporter and feedback function")
2010 4e338533 Michael Hanselmann
2011 4e338533 Michael Hanselmann
  return GenericPollJob(job_id, _LuxiJobPollCb(cl), reporter)
2012 ceab32dd Iustin Pop
2013 ceab32dd Iustin Pop
2014 583163a6 Michael Hanselmann
def SubmitOpCode(op, cl=None, feedback_fn=None, opts=None, reporter=None):
2015 0a1e74d9 Iustin Pop
  """Legacy function to submit an opcode.
2016 0a1e74d9 Iustin Pop

2017 0a1e74d9 Iustin Pop
  This is just a simple wrapper over the construction of the processor
2018 0a1e74d9 Iustin Pop
  instance. It should be extended to better handle feedback and
2019 0a1e74d9 Iustin Pop
  interaction functions.
2020 0a1e74d9 Iustin Pop

2021 0a1e74d9 Iustin Pop
  """
2022 0a1e74d9 Iustin Pop
  if cl is None:
2023 0a1e74d9 Iustin Pop
    cl = GetClient()
2024 0a1e74d9 Iustin Pop
2025 293ba2d8 Iustin Pop
  SetGenericOpcodeOpts([op], opts)
2026 293ba2d8 Iustin Pop
2027 5d297d8a Michael Hanselmann
  job_id = SendJob([op], cl=cl)
2028 0a1e74d9 Iustin Pop
2029 583163a6 Michael Hanselmann
  op_results = PollJob(job_id, cl=cl, feedback_fn=feedback_fn,
2030 583163a6 Michael Hanselmann
                       reporter=reporter)
2031 53c04d04 Iustin Pop
2032 53c04d04 Iustin Pop
  return op_results[0]
2033 0a1e74d9 Iustin Pop
2034 0a1e74d9 Iustin Pop
2035 94428652 Iustin Pop
def SubmitOrSend(op, opts, cl=None, feedback_fn=None):
2036 94428652 Iustin Pop
  """Wrapper around SubmitOpCode or SendJob.
2037 94428652 Iustin Pop

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

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

2046 94428652 Iustin Pop
  """
2047 94428652 Iustin Pop
  if opts and opts.submit_only:
2048 293ba2d8 Iustin Pop
    job = [op]
2049 293ba2d8 Iustin Pop
    SetGenericOpcodeOpts(job, opts)
2050 293ba2d8 Iustin Pop
    job_id = SendJob(job, cl=cl)
2051 e9d741b6 Iustin Pop
    raise JobSubmittedException(job_id)
2052 94428652 Iustin Pop
  else:
2053 293ba2d8 Iustin Pop
    return SubmitOpCode(op, cl=cl, feedback_fn=feedback_fn, opts=opts)
2054 293ba2d8 Iustin Pop
2055 293ba2d8 Iustin Pop
2056 293ba2d8 Iustin Pop
def SetGenericOpcodeOpts(opcode_list, options):
2057 293ba2d8 Iustin Pop
  """Processor for generic options.
2058 293ba2d8 Iustin Pop

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

2062 293ba2d8 Iustin Pop
  @param opcode_list: list of opcodes
2063 293ba2d8 Iustin Pop
  @param options: command line options or None
2064 293ba2d8 Iustin Pop
  @return: None (in-place modification)
2065 293ba2d8 Iustin Pop

2066 293ba2d8 Iustin Pop
  """
2067 293ba2d8 Iustin Pop
  if not options:
2068 293ba2d8 Iustin Pop
    return
2069 293ba2d8 Iustin Pop
  for op in opcode_list:
2070 aa06f8c6 Michael Hanselmann
    op.debug_level = options.debug
2071 a0a6ff34 Iustin Pop
    if hasattr(options, "dry_run"):
2072 a0a6ff34 Iustin Pop
      op.dry_run = options.dry_run
2073 aa06f8c6 Michael Hanselmann
    if getattr(options, "priority", None) is not None:
2074 aa06f8c6 Michael Hanselmann
      op.priority = _PRIONAME_TO_VALUE[options.priority]
2075 94428652 Iustin Pop
2076 94428652 Iustin Pop
2077 af30b2fd Michael Hanselmann
def GetClient():
2078 af30b2fd Michael Hanselmann
  # TODO: Cache object?
2079 b33e986b Iustin Pop
  try:
2080 b33e986b Iustin Pop
    client = luxi.Client()
2081 b33e986b Iustin Pop
  except luxi.NoMasterError:
2082 d9a51679 Michael Hanselmann
    ss = ssconf.SimpleStore()
2083 d9a51679 Michael Hanselmann
2084 d9a51679 Michael Hanselmann
    # Try to read ssconf file
2085 d9a51679 Michael Hanselmann
    try:
2086 d9a51679 Michael Hanselmann
      ss.GetMasterNode()
2087 d9a51679 Michael Hanselmann
    except errors.ConfigurationError:
2088 d9a51679 Michael Hanselmann
      raise errors.OpPrereqError("Cluster not initialized or this machine is"
2089 d9a51679 Michael Hanselmann
                                 " not part of a cluster")
2090 d9a51679 Michael Hanselmann
2091 d9a51679 Michael Hanselmann
    master, myself = ssconf.GetMasterAndMyself(ss=ss)
2092 b33e986b Iustin Pop
    if master != myself:
2093 b33e986b Iustin Pop
      raise errors.OpPrereqError("This is not the master node, please connect"
2094 b33e986b Iustin Pop
                                 " to node '%s' and rerun the command" %
2095 b33e986b Iustin Pop
                                 master)
2096 d9a51679 Michael Hanselmann
    raise
2097 b33e986b Iustin Pop
  return client
2098 af30b2fd Michael Hanselmann
2099 af30b2fd Michael Hanselmann
2100 73702ee7 Iustin Pop
def FormatError(err):
2101 73702ee7 Iustin Pop
  """Return a formatted error message for a given error.
2102 73702ee7 Iustin Pop

2103 73702ee7 Iustin Pop
  This function takes an exception instance and returns a tuple
2104 73702ee7 Iustin Pop
  consisting of two values: first, the recommended exit code, and
2105 73702ee7 Iustin Pop
  second, a string describing the error message (not
2106 73702ee7 Iustin Pop
  newline-terminated).
2107 73702ee7 Iustin Pop

2108 73702ee7 Iustin Pop
  """
2109 73702ee7 Iustin Pop
  retcode = 1
2110 73702ee7 Iustin Pop
  obuf = StringIO()
2111 e2e521d0 Iustin Pop
  msg = str(err)
2112 73702ee7 Iustin Pop
  if isinstance(err, errors.ConfigurationError):
2113 e2e521d0 Iustin Pop
    txt = "Corrupt configuration file: %s" % msg
2114 46fbdd04 Iustin Pop
    logging.error(txt)
2115 e2e521d0 Iustin Pop
    obuf.write(txt + "\n")
2116 73702ee7 Iustin Pop
    obuf.write("Aborting.")
2117 73702ee7 Iustin Pop
    retcode = 2
2118 73702ee7 Iustin Pop
  elif isinstance(err, errors.HooksAbort):
2119 73702ee7 Iustin Pop
    obuf.write("Failure: hooks execution failed:\n")
2120 73702ee7 Iustin Pop
    for node, script, out in err.args[0]:
2121 73702ee7 Iustin Pop
      if out:
2122 73702ee7 Iustin Pop
        obuf.write("  node: %s, script: %s, output: %s\n" %
2123 73702ee7 Iustin Pop
                   (node, script, out))
2124 73702ee7 Iustin Pop
      else:
2125 73702ee7 Iustin Pop
        obuf.write("  node: %s, script: %s (no output)\n" %
2126 73702ee7 Iustin Pop
                   (node, script))
2127 73702ee7 Iustin Pop
  elif isinstance(err, errors.HooksFailure):
2128 e2e521d0 Iustin Pop
    obuf.write("Failure: hooks general failure: %s" % msg)
2129 73702ee7 Iustin Pop
  elif isinstance(err, errors.ResolverError):
2130 b705c7a6 Manuel Franceschini
    this_host = netutils.Hostname.GetSysName()
2131 73702ee7 Iustin Pop
    if err.args[0] == this_host:
2132 73702ee7 Iustin Pop
      msg = "Failure: can't resolve my own hostname ('%s')"
2133 73702ee7 Iustin Pop
    else:
2134 73702ee7 Iustin Pop
      msg = "Failure: can't resolve hostname '%s'"
2135 73702ee7 Iustin Pop
    obuf.write(msg % err.args[0])
2136 73702ee7 Iustin Pop
  elif isinstance(err, errors.OpPrereqError):
2137 5c983ee5 Iustin Pop
    if len(err.args) == 2:
2138 5c983ee5 Iustin Pop
      obuf.write("Failure: prerequisites not met for this"
2139 5c983ee5 Iustin Pop
               " operation:\nerror type: %s, error details:\n%s" %
2140 5c983ee5 Iustin Pop
                 (err.args[1], err.args[0]))
2141 5c983ee5 Iustin Pop
    else:
2142 5c983ee5 Iustin Pop
      obuf.write("Failure: prerequisites not met for this"
2143 5c983ee5 Iustin Pop
                 " operation:\n%s" % msg)
2144 73702ee7 Iustin Pop
  elif isinstance(err, errors.OpExecError):
2145 e2e521d0 Iustin Pop
    obuf.write("Failure: command execution error:\n%s" % msg)
2146 73702ee7 Iustin Pop
  elif isinstance(err, errors.TagError):
2147 e2e521d0 Iustin Pop
    obuf.write("Failure: invalid tag(s) given:\n%s" % msg)
2148 686d7433 Iustin Pop
  elif isinstance(err, errors.JobQueueDrainError):
2149 686d7433 Iustin Pop
    obuf.write("Failure: the job queue is marked for drain and doesn't"
2150 686d7433 Iustin Pop
               " accept new requests\n")
2151 f87b405e Michael Hanselmann
  elif isinstance(err, errors.JobQueueFull):
2152 f87b405e Michael Hanselmann
    obuf.write("Failure: the job queue is full and doesn't accept new"
2153 f87b405e Michael Hanselmann
               " job submissions until old jobs are archived\n")
2154 a5728081 Guido Trotter
  elif isinstance(err, errors.TypeEnforcementError):
2155 a5728081 Guido Trotter
    obuf.write("Parameter Error: %s" % msg)
2156 c1ce76bb Iustin Pop
  elif isinstance(err, errors.ParameterError):
2157 c1ce76bb Iustin Pop
    obuf.write("Failure: unknown/wrong parameter name '%s'" % msg)
2158 03a8dbdc Iustin Pop
  elif isinstance(err, luxi.NoMasterError):
2159 03a8dbdc Iustin Pop
    obuf.write("Cannot communicate with the master daemon.\nIs it running"
2160 082c5adb Michael Hanselmann
               " and listening for connections?")
2161 03a8dbdc Iustin Pop
  elif isinstance(err, luxi.TimeoutError):
2162 cd4c86a8 Michael Hanselmann
    obuf.write("Timeout while talking to the master daemon. Jobs might have"
2163 cd4c86a8 Michael Hanselmann
               " been submitted and will continue to run even if the call"
2164 cd4c86a8 Michael Hanselmann
               " timed out. Useful commands in this situation are \"gnt-job"
2165 cd4c86a8 Michael Hanselmann
               " list\", \"gnt-job cancel\" and \"gnt-job watch\". Error:\n")
2166 cd4c86a8 Michael Hanselmann
    obuf.write(msg)
2167 5a1c22fe Iustin Pop
  elif isinstance(err, luxi.PermissionError):
2168 5a1c22fe Iustin Pop
    obuf.write("It seems you don't have permissions to connect to the"
2169 5a1c22fe Iustin Pop
               " master daemon.\nPlease retry as a different user.")
2170 03a8dbdc Iustin Pop
  elif isinstance(err, luxi.ProtocolError):
2171 03a8dbdc Iustin Pop
    obuf.write("Unhandled protocol error while talking to the master daemon:\n"
2172 03a8dbdc Iustin Pop
               "%s" % msg)
2173 91c622a8 Iustin Pop
  elif isinstance(err, errors.JobLost):
2174 91c622a8 Iustin Pop
    obuf.write("Error checking job status: %s" % msg)
2175 cb1e6c3c Michael Hanselmann
  elif isinstance(err, errors.QueryFilterParseError):
2176 cb1e6c3c Michael Hanselmann
    obuf.write("Error while parsing query filter: %s\n" % err.args[0])
2177 cb1e6c3c Michael Hanselmann
    obuf.write("\n".join(err.GetDetails()))
2178 797506fc Michael Hanselmann
  elif isinstance(err, errors.GenericError):
2179 797506fc Michael Hanselmann
    obuf.write("Unhandled Ganeti error: %s" % msg)
2180 e9d741b6 Iustin Pop
  elif isinstance(err, JobSubmittedException):
2181 e9d741b6 Iustin Pop
    obuf.write("JobID: %s\n" % err.args[0])
2182 e9d741b6 Iustin Pop
    retcode = 0
2183 73702ee7 Iustin Pop
  else:
2184 e2e521d0 Iustin Pop
    obuf.write("Unhandled exception: %s" % msg)
2185 d0c8c01d Iustin Pop
  return retcode, obuf.getvalue().rstrip("\n")
2186 73702ee7 Iustin Pop
2187 73702ee7 Iustin Pop
2188 ef9fa5b9 René Nussbaumer
def GenericMain(commands, override=None, aliases=None,
2189 ef9fa5b9 René Nussbaumer
                env_override=frozenset()):
2190 a8083063 Iustin Pop
  """Generic main function for all the gnt-* commands.
2191 a8083063 Iustin Pop

2192 ef9fa5b9 René Nussbaumer
  @param commands: a dictionary with a special structure, see the design doc
2193 ef9fa5b9 René Nussbaumer
                   for command line handling.
2194 ef9fa5b9 René Nussbaumer
  @param override: if not None, we expect a dictionary with keys that will
2195 ef9fa5b9 René Nussbaumer
                   override command line options; this can be used to pass
2196 ef9fa5b9 René Nussbaumer
                   options from the scripts to generic functions
2197 ef9fa5b9 René Nussbaumer
  @param aliases: dictionary with command aliases {'alias': 'target, ...}
2198 ef9fa5b9 René Nussbaumer
  @param env_override: list of environment names which are allowed to submit
2199 ef9fa5b9 René Nussbaumer
                       default args for commands
2200 a8083063 Iustin Pop

2201 a8083063 Iustin Pop
  """
2202 a8083063 Iustin Pop
  # save the program name and the entire command line for later logging
2203 a8083063 Iustin Pop
  if sys.argv:
2204 c1f19851 Michael Hanselmann
    binary = os.path.basename(sys.argv[0])
2205 c1f19851 Michael Hanselmann
    if not binary:
2206 c1f19851 Michael Hanselmann
      binary = sys.argv[0]
2207 c1f19851 Michael Hanselmann
2208 a8083063 Iustin Pop
    if len(sys.argv) >= 2:
2209 c1f19851 Michael Hanselmann
      logname = utils.ShellQuoteArgs([binary, sys.argv[1]])
2210 a8083063 Iustin Pop
    else:
2211 c1f19851 Michael Hanselmann
      logname = binary
2212 c1f19851 Michael Hanselmann
2213 c1f19851 Michael Hanselmann
    cmdline = utils.ShellQuoteArgs([binary] + sys.argv[1:])
2214 a8083063 Iustin Pop
  else:
2215 a8083063 Iustin Pop
    binary = "<unknown program>"
2216 c1f19851 Michael Hanselmann
    cmdline = "<unknown>"
2217 a8083063 Iustin Pop
2218 de47cf8f Guido Trotter
  if aliases is None:
2219 de47cf8f Guido Trotter
    aliases = {}
2220 de47cf8f Guido Trotter
2221 3126878d Guido Trotter
  try:
2222 ef9fa5b9 René Nussbaumer
    func, options, args = _ParseArgs(sys.argv, commands, aliases, env_override)
2223 3126878d Guido Trotter
  except errors.ParameterError, err:
2224 3126878d Guido Trotter
    result, err_msg = FormatError(err)
2225 3126878d Guido Trotter
    ToStderr(err_msg)
2226 3126878d Guido Trotter
    return 1
2227 3126878d Guido Trotter
2228 a8083063 Iustin Pop
  if func is None: # parse error
2229 a8083063 Iustin Pop
    return 1
2230 a8083063 Iustin Pop
2231 334d1483 Iustin Pop
  if override is not None:
2232 334d1483 Iustin Pop
    for key, val in override.iteritems():
2233 334d1483 Iustin Pop
      setattr(options, key, val)
2234 334d1483 Iustin Pop
2235 c1f19851 Michael Hanselmann
  utils.SetupLogging(constants.LOG_COMMANDS, logname, debug=options.debug,
2236 cfcc79c6 Michael Hanselmann
                     stderr_logging=True)
2237 a8083063 Iustin Pop
2238 c1f19851 Michael Hanselmann
  logging.info("Command line: %s", cmdline)
2239 a8083063 Iustin Pop
2240 a8083063 Iustin Pop
  try:
2241 a4af651e Iustin Pop
    result = func(options, args)
2242 d8353c3a Iustin Pop
  except (errors.GenericError, luxi.ProtocolError,
2243 d8353c3a Iustin Pop
          JobSubmittedException), err:
2244 a4af651e Iustin Pop
    result, err_msg = FormatError(err)
2245 5bbd3f7f Michael Hanselmann
    logging.exception("Error during command processing")
2246 46fbdd04 Iustin Pop
    ToStderr(err_msg)
2247 8a53b55f Iustin Pop
  except KeyboardInterrupt:
2248 8a53b55f Iustin Pop
    result = constants.EXIT_FAILURE
2249 8a53b55f Iustin Pop
    ToStderr("Aborted. Note that if the operation created any jobs, they"
2250 8a53b55f Iustin Pop
             " might have been submitted and"
2251 8a53b55f Iustin Pop
             " will continue to run in the background.")
2252 225e2544 Iustin Pop
  except IOError, err:
2253 225e2544 Iustin Pop
    if err.errno == errno.EPIPE:
2254 225e2544 Iustin Pop
      # our terminal went away, we'll exit
2255 225e2544 Iustin Pop
      sys.exit(constants.EXIT_FAILURE)
2256 225e2544 Iustin Pop
    else:
2257 225e2544 Iustin Pop
      raise
2258 a8083063 Iustin Pop
2259 a8083063 Iustin Pop
  return result
2260 137161c9 Michael Hanselmann
2261 137161c9 Michael Hanselmann
2262 845c79d8 Michael Hanselmann
def ParseNicOption(optvalue):
2263 845c79d8 Michael Hanselmann
  """Parses the value of the --net option(s).
2264 845c79d8 Michael Hanselmann

2265 845c79d8 Michael Hanselmann
  """
2266 845c79d8 Michael Hanselmann
  try:
2267 845c79d8 Michael Hanselmann
    nic_max = max(int(nidx[0]) + 1 for nidx in optvalue)
2268 845c79d8 Michael Hanselmann
  except (TypeError, ValueError), err:
2269 845c79d8 Michael Hanselmann
    raise errors.OpPrereqError("Invalid NIC index passed: %s" % str(err))
2270 845c79d8 Michael Hanselmann
2271 845c79d8 Michael Hanselmann
  nics = [{}] * nic_max
2272 845c79d8 Michael Hanselmann
  for nidx, ndict in optvalue:
2273 845c79d8 Michael Hanselmann
    nidx = int(nidx)
2274 845c79d8 Michael Hanselmann
2275 845c79d8 Michael Hanselmann
    if not isinstance(ndict, dict):
2276 845c79d8 Michael Hanselmann
      raise errors.OpPrereqError("Invalid nic/%d value: expected dict,"
2277 845c79d8 Michael Hanselmann
                                 " got %s" % (nidx, ndict))
2278 845c79d8 Michael Hanselmann
2279 845c79d8 Michael Hanselmann
    utils.ForceDictType(ndict, constants.INIC_PARAMS_TYPES)
2280 845c79d8 Michael Hanselmann
2281 845c79d8 Michael Hanselmann
    nics[nidx] = ndict
2282 845c79d8 Michael Hanselmann
2283 845c79d8 Michael Hanselmann
  return nics
2284 845c79d8 Michael Hanselmann
2285 845c79d8 Michael Hanselmann
2286 d77490c5 Iustin Pop
def GenericInstanceCreate(mode, opts, args):
2287 d77490c5 Iustin Pop
  """Add an instance to the cluster via either creation or import.
2288 d77490c5 Iustin Pop

2289 d77490c5 Iustin Pop
  @param mode: constants.INSTANCE_CREATE or constants.INSTANCE_IMPORT
2290 d77490c5 Iustin Pop
  @param opts: the command line options selected by the user
2291 d77490c5 Iustin Pop
  @type args: list
2292 d77490c5 Iustin Pop
  @param args: should contain only one element, the new instance name
2293 d77490c5 Iustin Pop
  @rtype: int
2294 d77490c5 Iustin Pop
  @return: the desired exit code
2295 d77490c5 Iustin Pop

2296 d77490c5 Iustin Pop
  """
2297 d77490c5 Iustin Pop
  instance = args[0]
2298 d77490c5 Iustin Pop
2299 d77490c5 Iustin Pop
  (pnode, snode) = SplitNodeOption(opts.node)
2300 d77490c5 Iustin Pop
2301 d77490c5 Iustin Pop
  hypervisor = None
2302 d77490c5 Iustin Pop
  hvparams = {}
2303 d77490c5 Iustin Pop
  if opts.hypervisor:
2304 d77490c5 Iustin Pop
    hypervisor, hvparams = opts.hypervisor
2305 d77490c5 Iustin Pop
2306 d77490c5 Iustin Pop
  if opts.nics:
2307 845c79d8 Michael Hanselmann
    nics = ParseNicOption(opts.nics)
2308 d77490c5 Iustin Pop
  elif opts.no_nics:
2309 d77490c5 Iustin Pop
    # no nics
2310 d77490c5 Iustin Pop
    nics = []
2311 0af0f641 Iustin Pop
  elif mode == constants.INSTANCE_CREATE:
2312 d77490c5 Iustin Pop
    # default of one nic, all auto
2313 d77490c5 Iustin Pop
    nics = [{}]
2314 0af0f641 Iustin Pop
  else:
2315 0af0f641 Iustin Pop
    # mode == import
2316 0af0f641 Iustin Pop
    nics = []
2317 d77490c5 Iustin Pop
2318 d77490c5 Iustin Pop
  if opts.disk_template == constants.DT_DISKLESS:
2319 d77490c5 Iustin Pop
    if opts.disks or opts.sd_size is not None:
2320 d77490c5 Iustin Pop
      raise errors.OpPrereqError("Diskless instance but disk"
2321 d77490c5 Iustin Pop
                                 " information passed")
2322 d77490c5 Iustin Pop
    disks = []
2323 d77490c5 Iustin Pop
  else:
2324 9b12ed0f Iustin Pop
    if (not opts.disks and not opts.sd_size
2325 9b12ed0f Iustin Pop
        and mode == constants.INSTANCE_CREATE):
2326 d77490c5 Iustin Pop
      raise errors.OpPrereqError("No disk information specified")
2327 d77490c5 Iustin Pop
    if opts.disks and opts.sd_size is not None:
2328 d77490c5 Iustin Pop
      raise errors.OpPrereqError("Please use either the '--disk' or"
2329 d77490c5 Iustin Pop
                                 " '-s' option")
2330 d77490c5 Iustin Pop
    if opts.sd_size is not None:
2331 ccfa86ba Michael Hanselmann
      opts.disks = [(0, {constants.IDISK_SIZE: opts.sd_size})]
2332 9b12ed0f Iustin Pop
2333 9b12ed0f Iustin Pop
    if opts.disks:
2334 9b12ed0f Iustin Pop
      try:
2335 9b12ed0f Iustin Pop
        disk_max = max(int(didx[0]) + 1 for didx in opts.disks)
2336 9b12ed0f Iustin Pop
      except ValueError, err:
2337 9b12ed0f Iustin Pop
        raise errors.OpPrereqError("Invalid disk index passed: %s" % str(err))
2338 9b12ed0f Iustin Pop
      disks = [{}] * disk_max
2339 9b12ed0f Iustin Pop
    else:
2340 9b12ed0f Iustin Pop
      disks = []
2341 d77490c5 Iustin Pop
    for didx, ddict in opts.disks:
2342 d77490c5 Iustin Pop
      didx = int(didx)
2343 d77490c5 Iustin Pop
      if not isinstance(ddict, dict):
2344 d77490c5 Iustin Pop
        msg = "Invalid disk/%d value: expected dict, got %s" % (didx, ddict)
2345 d77490c5 Iustin Pop
        raise errors.OpPrereqError(msg)
2346 ccfa86ba Michael Hanselmann
      elif constants.IDISK_SIZE in ddict:
2347 ccfa86ba Michael Hanselmann
        if constants.IDISK_ADOPT in ddict:
2348 5029db65 Iustin Pop
          raise errors.OpPrereqError("Only one of 'size' and 'adopt' allowed"
2349 5029db65 Iustin Pop
                                     " (disk %d)" % didx)
2350 5029db65 Iustin Pop
        try:
2351 ccfa86ba Michael Hanselmann
          ddict[constants.IDISK_SIZE] = \
2352 ccfa86ba Michael Hanselmann
            utils.ParseUnit(ddict[constants.IDISK_SIZE])
2353 5029db65 Iustin Pop
        except ValueError, err:
2354 5029db65 Iustin Pop
          raise errors.OpPrereqError("Invalid disk size for disk %d: %s" %
2355 5029db65 Iustin Pop
                                     (didx, err))
2356 ccfa86ba Michael Hanselmann
      elif constants.IDISK_ADOPT in ddict:
2357 5029db65 Iustin Pop
        if mode == constants.INSTANCE_IMPORT:
2358 5029db65 Iustin Pop
          raise errors.OpPrereqError("Disk adoption not allowed for instance"
2359 5029db65 Iustin Pop
                                     " import")
2360 ccfa86ba Michael Hanselmann
        ddict[constants.IDISK_SIZE] = 0
2361 5029db65 Iustin Pop
      else:
2362 5029db65 Iustin Pop
        raise errors.OpPrereqError("Missing size or adoption source for"
2363 5029db65 Iustin Pop
                                   " disk %d" % didx)
2364 d77490c5 Iustin Pop
      disks[didx] = ddict
2365 d77490c5 Iustin Pop
2366 a57981c5 Apollon Oikonomopoulos
  if opts.tags is not None:
2367 0f8810df Michael Hanselmann
    tags = opts.tags.split(",")
2368 a57981c5 Apollon Oikonomopoulos
  else:
2369 a57981c5 Apollon Oikonomopoulos
    tags = []
2370 a57981c5 Apollon Oikonomopoulos
2371 b2e233a5 Guido Trotter
  utils.ForceDictType(opts.beparams, constants.BES_PARAMETER_COMPAT)
2372 d77490c5 Iustin Pop
  utils.ForceDictType(hvparams, constants.HVS_PARAMETER_TYPES)
2373 d77490c5 Iustin Pop
2374 d77490c5 Iustin Pop
  if mode == constants.INSTANCE_CREATE:
2375 d77490c5 Iustin Pop
    start = opts.start
2376 d77490c5 Iustin Pop
    os_type = opts.os
2377 1ee8e01a Guido Trotter
    force_variant = opts.force_variant
2378 d77490c5 Iustin Pop
    src_node = None
2379 d77490c5 Iustin Pop
    src_path = None
2380 25a8792c Iustin Pop
    no_install = opts.no_install
2381 e588764d Iustin Pop
    identify_defaults = False
2382 d77490c5 Iustin Pop
  elif mode == constants.INSTANCE_IMPORT:
2383 d77490c5 Iustin Pop
    start = False
2384 d77490c5 Iustin Pop
    os_type = None
2385 1ee8e01a Guido Trotter
    force_variant = False
2386 d77490c5 Iustin Pop
    src_node = opts.src_node
2387 d77490c5 Iustin Pop
    src_path = opts.src_dir
2388 25a8792c Iustin Pop
    no_install = None
2389 e588764d Iustin Pop
    identify_defaults = opts.identify_defaults
2390 d77490c5 Iustin Pop
  else:
2391 d77490c5 Iustin Pop
    raise errors.ProgrammerError("Invalid creation mode %s" % mode)
2392 d77490c5 Iustin Pop
2393 e1530b10 Iustin Pop
  op = opcodes.OpInstanceCreate(instance_name=instance,
2394 d77490c5 Iustin Pop
                                disks=disks,
2395 d77490c5 Iustin Pop
                                disk_template=opts.disk_template,
2396 d77490c5 Iustin Pop
                                nics=nics,
2397 d77490c5 Iustin Pop
                                pnode=pnode, snode=snode,
2398 d77490c5 Iustin Pop
                                ip_check=opts.ip_check,
2399 460d22be Iustin Pop
                                name_check=opts.name_check,
2400 d77490c5 Iustin Pop
                                wait_for_sync=opts.wait_for_sync,
2401 d77490c5 Iustin Pop
                                file_storage_dir=opts.file_storage_dir,
2402 d77490c5 Iustin Pop
                                file_driver=opts.file_driver,
2403 d77490c5 Iustin Pop
                                iallocator=opts.iallocator,
2404 d77490c5 Iustin Pop
                                hypervisor=hypervisor,
2405 d77490c5 Iustin Pop
                                hvparams=hvparams,
2406 d77490c5 Iustin Pop
                                beparams=opts.beparams,
2407 062a7100 Iustin Pop
                                osparams=opts.osparams,
2408 d77490c5 Iustin Pop
                                mode=mode,
2409 d77490c5 Iustin Pop
                                start=start,
2410 d77490c5 Iustin Pop
                                os_type=os_type,
2411 1ee8e01a Guido Trotter
                                force_variant=force_variant,
2412 d77490c5 Iustin Pop
                                src_node=src_node,
2413 25a8792c Iustin Pop
                                src_path=src_path,
2414 a57981c5 Apollon Oikonomopoulos
                                tags=tags,
2415 e588764d Iustin Pop
                                no_install=no_install,
2416 10889e0c René Nussbaumer
                                identify_defaults=identify_defaults,
2417 10889e0c René Nussbaumer
                                ignore_ipolicy=opts.ignore_ipolicy)
2418 d77490c5 Iustin Pop
2419 d77490c5 Iustin Pop
  SubmitOrSend(op, opts)
2420 d77490c5 Iustin Pop
  return 0
2421 d77490c5 Iustin Pop
2422 d77490c5 Iustin Pop
2423 7e49b6ce Michael Hanselmann
class _RunWhileClusterStoppedHelper:
2424 7e49b6ce Michael Hanselmann
  """Helper class for L{RunWhileClusterStopped} to simplify state management
2425 7e49b6ce Michael Hanselmann

2426 7e49b6ce Michael Hanselmann
  """
2427 7e49b6ce Michael Hanselmann
  def __init__(self, feedback_fn, cluster_name, master_node, online_nodes):
2428 7e49b6ce Michael Hanselmann
    """Initializes this class.
2429 7e49b6ce Michael Hanselmann

2430 7e49b6ce Michael Hanselmann
    @type feedback_fn: callable
2431 7e49b6ce Michael Hanselmann
    @param feedback_fn: Feedback function
2432 7e49b6ce Michael Hanselmann
    @type cluster_name: string
2433 7e49b6ce Michael Hanselmann
    @param cluster_name: Cluster name
2434 7e49b6ce Michael Hanselmann
    @type master_node: string
2435 7e49b6ce Michael Hanselmann
    @param master_node Master node name
2436 7e49b6ce Michael Hanselmann
    @type online_nodes: list
2437 7e49b6ce Michael Hanselmann
    @param online_nodes: List of names of online nodes
2438 7e49b6ce Michael Hanselmann

2439 7e49b6ce Michael Hanselmann
    """
2440 7e49b6ce Michael Hanselmann
    self.feedback_fn = feedback_fn
2441 7e49b6ce Michael Hanselmann
    self.cluster_name = cluster_name
2442 7e49b6ce Michael Hanselmann
    self.master_node = master_node
2443 7e49b6ce Michael Hanselmann
    self.online_nodes = online_nodes
2444 7e49b6ce Michael Hanselmann
2445 7e49b6ce Michael Hanselmann
    self.ssh = ssh.SshRunner(self.cluster_name)
2446 7e49b6ce Michael Hanselmann
2447 7e49b6ce Michael Hanselmann
    self.nonmaster_nodes = [name for name in online_nodes
2448 7e49b6ce Michael Hanselmann
                            if name != master_node]
2449 7e49b6ce Michael Hanselmann
2450 7e49b6ce Michael Hanselmann
    assert self.master_node not in self.nonmaster_nodes
2451 7e49b6ce Michael Hanselmann
2452 7e49b6ce Michael Hanselmann
  def _RunCmd(self, node_name, cmd):
2453 7e49b6ce Michael Hanselmann
    """Runs a command on the local or a remote machine.
2454 7e49b6ce Michael Hanselmann

2455 7e49b6ce Michael Hanselmann
    @type node_name: string
2456 7e49b6ce Michael Hanselmann
    @param node_name: Machine name
2457 7e49b6ce Michael Hanselmann
    @type cmd: list
2458 7e49b6ce Michael Hanselmann
    @param cmd: Command
2459 7e49b6ce Michael Hanselmann

2460 7e49b6ce Michael Hanselmann
    """
2461 7e49b6ce Michael Hanselmann
    if node_name is None or node_name == self.master_node:
2462 7e49b6ce Michael Hanselmann
      # No need to use SSH
2463 7e49b6ce Michael Hanselmann
      result = utils.RunCmd(cmd)
2464 7e49b6ce Michael Hanselmann
    else:
2465 7e49b6ce Michael Hanselmann
      result = self.ssh.Run(node_name, "root", utils.ShellQuoteArgs(cmd))
2466 7e49b6ce Michael Hanselmann
2467 7e49b6ce Michael Hanselmann
    if result.failed:
2468 7e49b6ce Michael Hanselmann
      errmsg = ["Failed to run command %s" % result.cmd]
2469 7e49b6ce Michael Hanselmann
      if node_name:
2470 7e49b6ce Michael Hanselmann
        errmsg.append("on node %s" % node_name)
2471 7e49b6ce Michael Hanselmann
      errmsg.append(": exitcode %s and error %s" %
2472 7e49b6ce Michael Hanselmann
                    (result.exit_code, result.output))
2473 7e49b6ce Michael Hanselmann
      raise errors.OpExecError(" ".join(errmsg))
2474 7e49b6ce Michael Hanselmann
2475 7e49b6ce Michael Hanselmann
  def Call(self, fn, *args):
2476 7e49b6ce Michael Hanselmann
    """Call function while all daemons are stopped.
2477 7e49b6ce Michael Hanselmann

2478 7e49b6ce Michael Hanselmann
    @type fn: callable
2479 7e49b6ce Michael Hanselmann
    @param fn: Function to be called
2480 7e49b6ce Michael Hanselmann

2481 7e49b6ce Michael Hanselmann
    """
2482 7e49b6ce Michael Hanselmann
    # Pause watcher by acquiring an exclusive lock on watcher state file
2483 7e49b6ce Michael Hanselmann
    self.feedback_fn("Blocking watcher")
2484 16e0b9c9 Michael Hanselmann
    watcher_block = utils.FileLock.Open(constants.WATCHER_LOCK_FILE)
2485 7e49b6ce Michael Hanselmann
    try:
2486 7e49b6ce Michael Hanselmann
      # TODO: Currently, this just blocks. There's no timeout.
2487 7e49b6ce Michael Hanselmann
      # TODO: Should it be a shared lock?
2488 7e49b6ce Michael Hanselmann
      watcher_block.Exclusive(blocking=True)
2489 7e49b6ce Michael Hanselmann
2490 7e49b6ce Michael Hanselmann
      # Stop master daemons, so that no new jobs can come in and all running
2491 7e49b6ce Michael Hanselmann
      # ones are finished
2492 7e49b6ce Michael Hanselmann
      self.feedback_fn("Stopping master daemons")
2493 7e49b6ce Michael Hanselmann
      self._RunCmd(None, [constants.DAEMON_UTIL, "stop-master"])
2494 7e49b6ce Michael Hanselmann
      try:
2495 7e49b6ce Michael Hanselmann
        # Stop daemons on all nodes
2496 7e49b6ce Michael Hanselmann
        for node_name in self.online_nodes:
2497 7e49b6ce Michael Hanselmann
          self.feedback_fn("Stopping daemons on %s" % node_name)
2498 7e49b6ce Michael Hanselmann
          self._RunCmd(node_name, [constants.DAEMON_UTIL, "stop-all"])
2499 7e49b6ce Michael Hanselmann
2500 7e49b6ce Michael Hanselmann
        # All daemons are shut down now
2501 7e49b6ce Michael Hanselmann
        try:
2502 7e49b6ce Michael Hanselmann
          return fn(self, *args)
2503 d512e84b Michael Hanselmann
        except Exception, err:
2504 d512e84b Michael Hanselmann
          _, errmsg = FormatError(err)
2505 7e49b6ce Michael Hanselmann
          logging.exception("Caught exception")
2506 d512e84b Michael Hanselmann
          self.feedback_fn(errmsg)
2507 7e49b6ce Michael Hanselmann
          raise
2508 7e49b6ce Michael Hanselmann
      finally:
2509 7e49b6ce Michael Hanselmann
        # Start cluster again, master node last
2510 7e49b6ce Michael Hanselmann
        for node_name in self.nonmaster_nodes + [self.master_node]:
2511 7e49b6ce Michael Hanselmann
          self.feedback_fn("Starting daemons on %s" % node_name)
2512 7e49b6ce Michael Hanselmann
          self._RunCmd(node_name, [constants.DAEMON_UTIL, "start-all"])
2513 7e49b6ce Michael Hanselmann
    finally:
2514 7e49b6ce Michael Hanselmann
      # Resume watcher
2515 7e49b6ce Michael Hanselmann
      watcher_block.Close()
2516 7e49b6ce Michael Hanselmann
2517 7e49b6ce Michael Hanselmann
2518 7e49b6ce Michael Hanselmann
def RunWhileClusterStopped(feedback_fn, fn, *args):
2519 7e49b6ce Michael Hanselmann
  """Calls a function while all cluster daemons are stopped.
2520 7e49b6ce Michael Hanselmann

2521 7e49b6ce Michael Hanselmann
  @type feedback_fn: callable
2522 7e49b6ce Michael Hanselmann
  @param feedback_fn: Feedback function
2523 7e49b6ce Michael Hanselmann
  @type fn: callable
2524 7e49b6ce Michael Hanselmann
  @param fn: Function to be called when daemons are stopped
2525 7e49b6ce Michael Hanselmann

2526 7e49b6ce Michael Hanselmann
  """
2527 7e49b6ce Michael Hanselmann
  feedback_fn("Gathering cluster information")
2528 7e49b6ce Michael Hanselmann
2529 7e49b6ce Michael Hanselmann
  # This ensures we're running on the master daemon
2530 7e49b6ce Michael Hanselmann
  cl = GetClient()
2531 7e49b6ce Michael Hanselmann
2532 7e49b6ce Michael Hanselmann
  (cluster_name, master_node) = \
2533 7e49b6ce Michael Hanselmann
    cl.QueryConfigValues(["cluster_name", "master_node"])
2534 7e49b6ce Michael Hanselmann
2535 7e49b6ce Michael Hanselmann
  online_nodes = GetOnlineNodes([], cl=cl)
2536 7e49b6ce Michael Hanselmann
2537 7e49b6ce Michael Hanselmann
  # Don't keep a reference to the client. The master daemon will go away.
2538 7e49b6ce Michael Hanselmann
  del cl
2539 7e49b6ce Michael Hanselmann
2540 7e49b6ce Michael Hanselmann
  assert master_node in online_nodes
2541 7e49b6ce Michael Hanselmann
2542 7e49b6ce Michael Hanselmann
  return _RunWhileClusterStoppedHelper(feedback_fn, cluster_name, master_node,
2543 7e49b6ce Michael Hanselmann
                                       online_nodes).Call(fn, *args)
2544 7e49b6ce Michael Hanselmann
2545 7e49b6ce Michael Hanselmann
2546 16be8703 Iustin Pop
def GenerateTable(headers, fields, separator, data,
2547 9fbfbb7b Iustin Pop
                  numfields=None, unitfields=None,
2548 9fbfbb7b Iustin Pop
                  units=None):
2549 137161c9 Michael Hanselmann
  """Prints a table with headers and different fields.
2550 137161c9 Michael Hanselmann

2551 9fbfbb7b Iustin Pop
  @type headers: dict
2552 9fbfbb7b Iustin Pop
  @param headers: dictionary mapping field names to headers for
2553 9fbfbb7b Iustin Pop
      the table
2554 9fbfbb7b Iustin Pop
  @type fields: list
2555 9fbfbb7b Iustin Pop
  @param fields: the field names corresponding to each row in
2556 9fbfbb7b Iustin Pop
      the data field
2557 9fbfbb7b Iustin Pop
  @param separator: the separator to be used; if this is None,
2558 9fbfbb7b Iustin Pop
      the default 'smart' algorithm is used which computes optimal
2559 9fbfbb7b Iustin Pop
      field width, otherwise just the separator is used between
2560 9fbfbb7b Iustin Pop
      each field
2561 9fbfbb7b Iustin Pop
  @type data: list
2562 9fbfbb7b Iustin Pop
  @param data: a list of lists, each sublist being one row to be output
2563 9fbfbb7b Iustin Pop
  @type numfields: list
2564 9fbfbb7b Iustin Pop
  @param numfields: a list with the fields that hold numeric
2565 9fbfbb7b Iustin Pop
      values and thus should be right-aligned
2566 9fbfbb7b Iustin Pop
  @type unitfields: list
2567 9fbfbb7b Iustin Pop
  @param unitfields: a list with the fields that hold numeric
2568 9fbfbb7b Iustin Pop
      values that should be formatted with the units field
2569 9fbfbb7b Iustin Pop
  @type units: string or None
2570 9fbfbb7b Iustin Pop
  @param units: the units we should use for formatting, or None for
2571 9fbfbb7b Iustin Pop
      automatic choice (human-readable for non-separator usage, otherwise
2572 9fbfbb7b Iustin Pop
      megabytes); this is a one-letter string
2573 137161c9 Michael Hanselmann

2574 137161c9 Michael Hanselmann
  """
2575 9fbfbb7b Iustin Pop
  if units is None:
2576 9fbfbb7b Iustin Pop
    if separator:
2577 9fbfbb7b Iustin Pop
      units = "m"
2578 9fbfbb7b Iustin Pop
    else:
2579 9fbfbb7b Iustin Pop
      units = "h"
2580 9fbfbb7b Iustin Pop
2581 137161c9 Michael Hanselmann
  if numfields is None:
2582 137161c9 Michael Hanselmann
    numfields = []
2583 137161c9 Michael Hanselmann
  if unitfields is None:
2584 137161c9 Michael Hanselmann
    unitfields = []
2585 137161c9 Michael Hanselmann
2586 b459a848 Andrea Spadaccini
  numfields = utils.FieldSet(*numfields)   # pylint: disable=W0142
2587 b459a848 Andrea Spadaccini
  unitfields = utils.FieldSet(*unitfields) # pylint: disable=W0142
2588 00430f8e Iustin Pop
2589 137161c9 Michael Hanselmann
  format_fields = []
2590 137161c9 Michael Hanselmann
  for field in fields:
2591 01ca31ae Iustin Pop
    if headers and field not in headers:
2592 ea5a5b74 Guido Trotter
      # TODO: handle better unknown fields (either revert to old
2593 71c1af58 Iustin Pop
      # style of raising exception, or deal more intelligently with
2594 71c1af58 Iustin Pop
      # variable fields)
2595 71c1af58 Iustin Pop
      headers[field] = field
2596 137161c9 Michael Hanselmann
    if separator is not None:
2597 137161c9 Michael Hanselmann
      format_fields.append("%s")
2598 00430f8e Iustin Pop
    elif numfields.Matches(field):
2599 137161c9 Michael Hanselmann
      format_fields.append("%*s")
2600 137161c9 Michael Hanselmann
    else:
2601 137161c9 Michael Hanselmann
      format_fields.append("%-*s")
2602 137161c9 Michael Hanselmann
2603 137161c9 Michael Hanselmann
  if separator is None:
2604 137161c9 Michael Hanselmann
    mlens = [0 for name in fields]
2605 d0c8c01d Iustin Pop
    format_str = " ".join(format_fields)
2606 137161c9 Michael Hanselmann
  else:
2607 c04bc777 Iustin Pop
    format_str = separator.replace("%", "%%").join(format_fields)
2608 137161c9 Michael Hanselmann
2609 137161c9 Michael Hanselmann
  for row in data:
2610 dcbd6288 Guido Trotter
    if row is None:
2611 dcbd6288 Guido Trotter
      continue
2612 137161c9 Michael Hanselmann
    for idx, val in enumerate(row):
2613 00430f8e Iustin Pop
      if unitfields.Matches(fields[idx]):
2614 137161c9 Michael Hanselmann
        try:
2615 137161c9 Michael Hanselmann
          val = int(val)
2616 691744c4 Iustin Pop
        except (TypeError, ValueError):
2617 137161c9 Michael Hanselmann
          pass
2618 137161c9 Michael Hanselmann
        else:
2619 9fbfbb7b Iustin Pop
          val = row[idx] = utils.FormatUnit(val, units)
2620 01ca31ae Iustin Pop
      val = row[idx] = str(val)
2621 137161c9 Michael Hanselmann
      if separator is None:
2622 137161c9 Michael Hanselmann
        mlens[idx] = max(mlens[idx], len(val))
2623 137161c9 Michael Hanselmann
2624 16be8703 Iustin Pop
  result = []
2625 137161c9 Michael Hanselmann
  if headers:
2626 137161c9 Michael Hanselmann
    args = []
2627 137161c9 Michael Hanselmann
    for idx, name in enumerate(fields):
2628 137161c9 Michael Hanselmann
      hdr = headers[name]
2629 137161c9 Michael Hanselmann
      if separator is None:
2630 137161c9 Michael Hanselmann
        mlens[idx] = max(mlens[idx], len(hdr))
2631 137161c9 Michael Hanselmann
        args.append(mlens[idx])
2632 137161c9 Michael Hanselmann
      args.append(hdr)
2633 c04bc777 Iustin Pop
    result.append(format_str % tuple(args))
2634 137161c9 Michael Hanselmann
2635 ec39d63c Michael Hanselmann
  if separator is None:
2636 ec39d63c Michael Hanselmann
    assert len(mlens) == len(fields)
2637 ec39d63c Michael Hanselmann
2638 ec39d63c Michael Hanselmann
    if fields and not numfields.Matches(fields[-1]):
2639 ec39d63c Michael Hanselmann
      mlens[-1] = 0
2640 ec39d63c Michael Hanselmann
2641 137161c9 Michael Hanselmann
  for line in data:
2642 137161c9 Michael Hanselmann
    args = []
2643 dcbd6288 Guido Trotter
    if line is None:
2644 d0c8c01d Iustin Pop
      line = ["-" for _ in fields]
2645 f1501b3f Michael Hanselmann
    for idx in range(len(fields)):
2646 137161c9 Michael Hanselmann
      if separator is None:
2647 137161c9 Michael Hanselmann
        args.append(mlens[idx])
2648 137161c9 Michael Hanselmann
      args.append(line[idx])
2649 c04bc777 Iustin Pop
    result.append(format_str % tuple(args))
2650 16be8703 Iustin Pop
2651 16be8703 Iustin Pop
  return result
2652 3386e7a9 Iustin Pop
2653 3386e7a9 Iustin Pop
2654 ee3aedff Michael Hanselmann
def _FormatBool(value):
2655 ee3aedff Michael Hanselmann
  """Formats a boolean value as a string.
2656 ee3aedff Michael Hanselmann

2657 ee3aedff Michael Hanselmann
  """
2658 ee3aedff Michael Hanselmann
  if value:
2659 ee3aedff Michael Hanselmann
    return "Y"
2660 ee3aedff Michael Hanselmann
  return "N"
2661 ee3aedff Michael Hanselmann
2662 ee3aedff Michael Hanselmann
2663 ee3aedff Michael Hanselmann
#: Default formatting for query results; (callback, align right)
2664 ee3aedff Michael Hanselmann
_DEFAULT_FORMAT_QUERY = {
2665 ee3aedff Michael Hanselmann
  constants.QFT_TEXT: (str, False),
2666 ee3aedff Michael Hanselmann
  constants.QFT_BOOL: (_FormatBool, False),
2667 ee3aedff Michael Hanselmann
  constants.QFT_NUMBER: (str, True),
2668 ee3aedff Michael Hanselmann
  constants.QFT_TIMESTAMP: (utils.FormatTime, False),
2669 ee3aedff Michael Hanselmann
  constants.QFT_OTHER: (str, False),
2670 ee3aedff Michael Hanselmann
  constants.QFT_UNKNOWN: (str, False),
2671 ee3aedff Michael Hanselmann
  }
2672 ee3aedff Michael Hanselmann
2673 ee3aedff Michael Hanselmann
2674 ee3aedff Michael Hanselmann
def _GetColumnFormatter(fdef, override, unit):
2675 ee3aedff Michael Hanselmann
  """Returns formatting function for a field.
2676 ee3aedff Michael Hanselmann

2677 ee3aedff Michael Hanselmann
  @type fdef: L{objects.QueryFieldDefinition}
2678 ee3aedff Michael Hanselmann
  @type override: dict
2679 ee3aedff Michael Hanselmann
  @param override: Dictionary for overriding field formatting functions,
2680 ee3aedff Michael Hanselmann
    indexed by field name, contents like L{_DEFAULT_FORMAT_QUERY}
2681 ee3aedff Michael Hanselmann
  @type unit: string
2682 ee3aedff Michael Hanselmann
  @param unit: Unit used for formatting fields of type L{constants.QFT_UNIT}
2683 ee3aedff Michael Hanselmann
  @rtype: tuple; (callable, bool)
2684 ee3aedff Michael Hanselmann
  @return: Returns the function to format a value (takes one parameter) and a
2685 ee3aedff Michael Hanselmann
    boolean for aligning the value on the right-hand side
2686 ee3aedff Michael Hanselmann

2687 ee3aedff Michael Hanselmann
  """
2688 ee3aedff Michael Hanselmann
  fmt = override.get(fdef.name, None)
2689 ee3aedff Michael Hanselmann
  if fmt is not None:
2690 ee3aedff Michael Hanselmann
    return fmt
2691 ee3aedff Michael Hanselmann
2692 ee3aedff Michael Hanselmann
  assert constants.QFT_UNIT not in _DEFAULT_FORMAT_QUERY
2693 ee3aedff Michael Hanselmann
2694 ee3aedff Michael Hanselmann
  if fdef.kind == constants.QFT_UNIT:
2695 ee3aedff Michael Hanselmann
    # Can't keep this information in the static dictionary
2696 ee3aedff Michael Hanselmann
    return (lambda value: utils.FormatUnit(value, unit), True)
2697 ee3aedff Michael Hanselmann
2698 ee3aedff Michael Hanselmann
  fmt = _DEFAULT_FORMAT_QUERY.get(fdef.kind, None)
2699 ee3aedff Michael Hanselmann
  if fmt is not None:
2700 ee3aedff Michael Hanselmann
    return fmt
2701 ee3aedff Michael Hanselmann
2702 ee3aedff Michael Hanselmann
  raise NotImplementedError("Can't format column type '%s'" % fdef.kind)
2703 ee3aedff Michael Hanselmann
2704 ee3aedff Michael Hanselmann
2705 ee3aedff Michael Hanselmann
class _QueryColumnFormatter:
2706 ee3aedff Michael Hanselmann
  """Callable class for formatting fields of a query.
2707 ee3aedff Michael Hanselmann

2708 ee3aedff Michael Hanselmann
  """
2709 f0b1bafe Iustin Pop
  def __init__(self, fn, status_fn, verbose):
2710 ee3aedff Michael Hanselmann
    """Initializes this class.
2711 ee3aedff Michael Hanselmann

2712 ee3aedff Michael Hanselmann
    @type fn: callable
2713 ee3aedff Michael Hanselmann
    @param fn: Formatting function
2714 ee3aedff Michael Hanselmann
    @type status_fn: callable
2715 ee3aedff Michael Hanselmann
    @param status_fn: Function to report fields' status
2716 f0b1bafe Iustin Pop
    @type verbose: boolean
2717 f0b1bafe Iustin Pop
    @param verbose: whether to use verbose field descriptions or not
2718 ee3aedff Michael Hanselmann

2719 ee3aedff Michael Hanselmann
    """
2720 ee3aedff Michael Hanselmann
    self._fn = fn
2721 ee3aedff Michael Hanselmann
    self._status_fn = status_fn
2722 cbfa4f0f Michael Hanselmann
    self._verbose = verbose
2723 ee3aedff Michael Hanselmann
2724 ee3aedff Michael Hanselmann
  def __call__(self, data):
2725 ee3aedff Michael Hanselmann
    """Returns a field's string representation.
2726 ee3aedff Michael Hanselmann

2727 ee3aedff Michael Hanselmann
    """
2728 ee3aedff Michael Hanselmann
    (status, value) = data
2729 ee3aedff Michael Hanselmann
2730 ee3aedff Michael Hanselmann
    # Report status
2731 ee3aedff Michael Hanselmann
    self._status_fn(status)
2732 ee3aedff Michael Hanselmann
2733 cfb084ae René Nussbaumer
    if status == constants.RS_NORMAL:
2734 ee3aedff Michael Hanselmann
      return self._fn(value)
2735 ee3aedff Michael Hanselmann
2736 ee3aedff Michael Hanselmann
    assert value is None, \
2737 ee3aedff Michael Hanselmann
           "Found value %r for abnormal status %s" % (value, status)
2738 ee3aedff Michael Hanselmann
2739 f2c6673d Michael Hanselmann
    return FormatResultError(status, self._verbose)
2740 ee3aedff Michael Hanselmann
2741 ee3aedff Michael Hanselmann
2742 f2c6673d Michael Hanselmann
def FormatResultError(status, verbose):
2743 ae95e419 René Nussbaumer
  """Formats result status other than L{constants.RS_NORMAL}.
2744 ee3aedff Michael Hanselmann

2745 ae95e419 René Nussbaumer
  @param status: The result status
2746 f2c6673d Michael Hanselmann
  @type verbose: boolean
2747 f2c6673d Michael Hanselmann
  @param verbose: Whether to return the verbose text
2748 ae95e419 René Nussbaumer
  @return: Text of result status
2749 a6070ef7 Michael Hanselmann

2750 ae95e419 René Nussbaumer
  """
2751 ae95e419 René Nussbaumer
  assert status != constants.RS_NORMAL, \
2752 cbfa4f0f Michael Hanselmann
         "FormatResultError called with status equal to constants.RS_NORMAL"
2753 ae95e419 René Nussbaumer
  try:
2754 cbfa4f0f Michael Hanselmann
    (verbose_text, normal_text) = constants.RSS_DESCRIPTION[status]
2755 ae95e419 René Nussbaumer
  except KeyError:
2756 ee3aedff Michael Hanselmann
    raise NotImplementedError("Unknown status %s" % status)
2757 cbfa4f0f Michael Hanselmann
  else:
2758 cbfa4f0f Michael Hanselmann
    if verbose:
2759 cbfa4f0f Michael Hanselmann
      return verbose_text
2760 cbfa4f0f Michael Hanselmann
    return normal_text
2761 ee3aedff Michael Hanselmann
2762 ee3aedff Michael Hanselmann
2763 ee3aedff Michael Hanselmann
def FormatQueryResult(result, unit=None, format_override=None, separator=None,
2764 f0b1bafe Iustin Pop
                      header=False, verbose=False):
2765 ee3aedff Michael Hanselmann
  """Formats data in L{objects.QueryResponse}.
2766 ee3aedff Michael Hanselmann

2767 ee3aedff Michael Hanselmann
  @type result: L{objects.QueryResponse}
2768 ee3aedff Michael Hanselmann
  @param result: result of query operation
2769 ee3aedff Michael Hanselmann
  @type unit: string
2770 ee3aedff Michael Hanselmann
  @param unit: Unit used for formatting fields of type L{constants.QFT_UNIT},
2771 18009c1e Iustin Pop
    see L{utils.text.FormatUnit}
2772 ee3aedff Michael Hanselmann
  @type format_override: dict
2773 ee3aedff Michael Hanselmann
  @param format_override: Dictionary for overriding field formatting functions,
2774 ee3aedff Michael Hanselmann
    indexed by field name, contents like L{_DEFAULT_FORMAT_QUERY}
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 output header row
2779 f0b1bafe Iustin Pop
  @type verbose: boolean
2780 f0b1bafe Iustin Pop
  @param verbose: whether to use verbose field descriptions or not
2781 ee3aedff Michael Hanselmann

2782 ee3aedff Michael Hanselmann
  """
2783 ee3aedff Michael Hanselmann
  if unit is None:
2784 ee3aedff Michael Hanselmann
    if separator:
2785 ee3aedff Michael Hanselmann
      unit = "m"
2786 ee3aedff Michael Hanselmann
    else:
2787 ee3aedff Michael Hanselmann
      unit = "h"
2788 ee3aedff Michael Hanselmann
2789 ee3aedff Michael Hanselmann
  if format_override is None:
2790 ee3aedff Michael Hanselmann
    format_override = {}
2791 ee3aedff Michael Hanselmann
2792 cfb084ae René Nussbaumer
  stats = dict.fromkeys(constants.RS_ALL, 0)
2793 ee3aedff Michael Hanselmann
2794 ee3aedff Michael Hanselmann
  def _RecordStatus(status):
2795 ee3aedff Michael Hanselmann
    if status in stats:
2796 ee3aedff Michael Hanselmann
      stats[status] += 1
2797 ee3aedff Michael Hanselmann
2798 ee3aedff Michael Hanselmann
  columns = []
2799 ee3aedff Michael Hanselmann
  for fdef in result.fields:
2800 ee3aedff Michael Hanselmann
    assert fdef.title and fdef.name
2801 ee3aedff Michael Hanselmann
    (fn, align_right) = _GetColumnFormatter(fdef, format_override, unit)
2802 ee3aedff Michael Hanselmann
    columns.append(TableColumn(fdef.title,
2803 f0b1bafe Iustin Pop
                               _QueryColumnFormatter(fn, _RecordStatus,
2804 f0b1bafe Iustin Pop
                                                     verbose),
2805 ee3aedff Michael Hanselmann
                               align_right))
2806 ee3aedff Michael Hanselmann
2807 ee3aedff Michael Hanselmann
  table = FormatTable(result.data, columns, header, separator)
2808 ee3aedff Michael Hanselmann
2809 ee3aedff Michael Hanselmann
  # Collect statistics
2810 cfb084ae René Nussbaumer
  assert len(stats) == len(constants.RS_ALL)
2811 ee3aedff Michael Hanselmann
  assert compat.all(count >= 0 for count in stats.values())
2812 ee3aedff Michael Hanselmann
2813 ee3aedff Michael Hanselmann
  # Determine overall status. If there was no data, unknown fields must be
2814 ee3aedff Michael Hanselmann
  # detected via the field definitions.
2815 cfb084ae René Nussbaumer
  if (stats[constants.RS_UNKNOWN] or
2816 ee3aedff Michael Hanselmann
      (not result.data and _GetUnknownFields(result.fields))):
2817 ee3aedff Michael Hanselmann
    status = QR_UNKNOWN
2818 ee3aedff Michael Hanselmann
  elif compat.any(count > 0 for key, count in stats.items()
2819 cfb084ae René Nussbaumer
                  if key != constants.RS_NORMAL):
2820 ee3aedff Michael Hanselmann
    status = QR_INCOMPLETE
2821 ee3aedff Michael Hanselmann
  else:
2822 ee3aedff Michael Hanselmann
    status = QR_NORMAL
2823 ee3aedff Michael Hanselmann
2824 ee3aedff Michael Hanselmann
  return (status, table)
2825 ee3aedff Michael Hanselmann
2826 ee3aedff Michael Hanselmann
2827 ee3aedff Michael Hanselmann
def _GetUnknownFields(fdefs):
2828 ee3aedff Michael Hanselmann
  """Returns list of unknown fields included in C{fdefs}.
2829 ee3aedff Michael Hanselmann

2830 ee3aedff Michael Hanselmann
  @type fdefs: list of L{objects.QueryFieldDefinition}
2831 ee3aedff Michael Hanselmann

2832 ee3aedff Michael Hanselmann
  """
2833 ee3aedff Michael Hanselmann
  return [fdef for fdef in fdefs
2834 ee3aedff Michael Hanselmann
          if fdef.kind == constants.QFT_UNKNOWN]
2835 ee3aedff Michael Hanselmann
2836 ee3aedff Michael Hanselmann
2837 ee3aedff Michael Hanselmann
def _WarnUnknownFields(fdefs):
2838 ee3aedff Michael Hanselmann
  """Prints a warning to stderr if a query included unknown fields.
2839 ee3aedff Michael Hanselmann

2840 ee3aedff Michael Hanselmann
  @type fdefs: list of L{objects.QueryFieldDefinition}
2841 ee3aedff Michael Hanselmann

2842 ee3aedff Michael Hanselmann
  """
2843 ee3aedff Michael Hanselmann
  unknown = _GetUnknownFields(fdefs)
2844 ee3aedff Michael Hanselmann
  if unknown:
2845 ee3aedff Michael Hanselmann
    ToStderr("Warning: Queried for unknown fields %s",
2846 ee3aedff Michael Hanselmann
             utils.CommaJoin(fdef.name for fdef in unknown))
2847 ee3aedff Michael Hanselmann
    return True
2848 ee3aedff Michael Hanselmann
2849 ee3aedff Michael Hanselmann
  return False
2850 ee3aedff Michael Hanselmann
2851 ee3aedff Michael Hanselmann
2852 ee3aedff Michael Hanselmann
def GenericList(resource, fields, names, unit, separator, header, cl=None,
2853 03ec545a Michael Hanselmann
                format_override=None, verbose=False, force_filter=False,
2854 f037e9d7 Michael Hanselmann
                namefield=None, qfilter=None):
2855 ee3aedff Michael Hanselmann
  """Generic implementation for listing all items of a resource.
2856 ee3aedff Michael Hanselmann

2857 abd66bf8 Michael Hanselmann
  @param resource: One of L{constants.QR_VIA_LUXI}
2858 ee3aedff Michael Hanselmann
  @type fields: list of strings
2859 ee3aedff Michael Hanselmann
  @param fields: List of fields to query for
2860 ee3aedff Michael Hanselmann
  @type names: list of strings
2861 ee3aedff Michael Hanselmann
  @param names: Names of items to query for
2862 ee3aedff Michael Hanselmann
  @type unit: string or None
2863 ee3aedff Michael Hanselmann
  @param unit: Unit used for formatting fields of type L{constants.QFT_UNIT} or
2864 ee3aedff Michael Hanselmann
    None for automatic choice (human-readable for non-separator usage,
2865 ee3aedff Michael Hanselmann
    otherwise megabytes); this is a one-letter string
2866 ee3aedff Michael Hanselmann
  @type separator: string or None
2867 ee3aedff Michael Hanselmann
  @param separator: String used to separate fields
2868 ee3aedff Michael Hanselmann
  @type header: bool
2869 ee3aedff Michael Hanselmann
  @param header: Whether to show header row
2870 2928de47 Michael Hanselmann
  @type force_filter: bool
2871 2928de47 Michael Hanselmann
  @param force_filter: Whether to always treat names as filter
2872 ee3aedff Michael Hanselmann
  @type format_override: dict
2873 ee3aedff Michael Hanselmann
  @param format_override: Dictionary for overriding field formatting functions,
2874 ee3aedff Michael Hanselmann
    indexed by field name, contents like L{_DEFAULT_FORMAT_QUERY}
2875 f0b1bafe Iustin Pop
  @type verbose: boolean
2876 f0b1bafe Iustin Pop
  @param verbose: whether to use verbose field descriptions or not
2877 03ec545a Michael Hanselmann
  @type namefield: string
2878 03ec545a Michael Hanselmann
  @param namefield: Name of field to use for simple filters (see
2879 03ec545a Michael Hanselmann
    L{qlang.MakeFilter} for details)
2880 f037e9d7 Michael Hanselmann
  @type qfilter: list or None
2881 f037e9d7 Michael Hanselmann
  @param qfilter: Query filter (in addition to names)
2882 ee3aedff Michael Hanselmann

2883 ee3aedff Michael Hanselmann
  """
2884 ee3aedff Michael Hanselmann
  if not names:
2885 ee3aedff Michael Hanselmann
    names = None
2886 ee3aedff Michael Hanselmann
2887 f037e9d7 Michael Hanselmann
  namefilter = qlang.MakeFilter(names, force_filter, namefield=namefield)
2888 f037e9d7 Michael Hanselmann
2889 f037e9d7 Michael Hanselmann
  if qfilter is None:
2890 f037e9d7 Michael Hanselmann
    qfilter = namefilter
2891 f037e9d7 Michael Hanselmann
  elif namefilter is not None:
2892 f037e9d7 Michael Hanselmann
    qfilter = [qlang.OP_AND, namefilter, qfilter]
2893 2928de47 Michael Hanselmann
2894 727274dd Iustin Pop
  if cl is None:
2895 727274dd Iustin Pop
    cl = GetClient()
2896 727274dd Iustin Pop
2897 2e5c33db Iustin Pop
  response = cl.Query(resource, fields, qfilter)
2898 ee3aedff Michael Hanselmann
2899 ee3aedff Michael Hanselmann
  found_unknown = _WarnUnknownFields(response.fields)
2900 ee3aedff Michael Hanselmann
2901 ee3aedff Michael Hanselmann
  (status, data) = FormatQueryResult(response, unit=unit, separator=separator,
2902 ee3aedff Michael Hanselmann
                                     header=header,
2903 f0b1bafe Iustin Pop
                                     format_override=format_override,
2904 f0b1bafe Iustin Pop
                                     verbose=verbose)
2905 ee3aedff Michael Hanselmann
2906 ee3aedff Michael Hanselmann
  for line in data:
2907 ee3aedff Michael Hanselmann
    ToStdout(line)
2908 ee3aedff Michael Hanselmann
2909 ee3aedff Michael Hanselmann
  assert ((found_unknown and status == QR_UNKNOWN) or
2910 ee3aedff Michael Hanselmann
          (not found_unknown and status != QR_UNKNOWN))
2911 ee3aedff Michael Hanselmann
2912 ee3aedff Michael Hanselmann
  if status == QR_UNKNOWN:
2913 ee3aedff Michael Hanselmann
    return constants.EXIT_UNKNOWN_FIELD
2914 ee3aedff Michael Hanselmann
2915 ee3aedff Michael Hanselmann
  # TODO: Should the list command fail if not all data could be collected?
2916 ee3aedff Michael Hanselmann
  return constants.EXIT_SUCCESS
2917 ee3aedff Michael Hanselmann
2918 ee3aedff Michael Hanselmann
2919 ee3aedff Michael Hanselmann
def GenericListFields(resource, fields, separator, header, cl=None):
2920 ee3aedff Michael Hanselmann
  """Generic implementation for listing fields for a resource.
2921 ee3aedff Michael Hanselmann

2922 abd66bf8 Michael Hanselmann
  @param resource: One of L{constants.QR_VIA_LUXI}
2923 ee3aedff Michael Hanselmann
  @type fields: list of strings
2924 ee3aedff Michael Hanselmann
  @param fields: List of fields to query for
2925 ee3aedff Michael Hanselmann
  @type separator: string or None
2926 ee3aedff Michael Hanselmann
  @param separator: String used to separate fields
2927 ee3aedff Michael Hanselmann
  @type header: bool
2928 ee3aedff Michael Hanselmann
  @param header: Whether to show header row
2929 ee3aedff Michael Hanselmann

2930 ee3aedff Michael Hanselmann
  """
2931 ee3aedff Michael Hanselmann
  if cl is None:
2932 ee3aedff Michael Hanselmann
    cl = GetClient()
2933 ee3aedff Michael Hanselmann
2934 ee3aedff Michael Hanselmann
  if not fields:
2935 ee3aedff Michael Hanselmann
    fields = None
2936 ee3aedff Michael Hanselmann
2937 ee3aedff Michael Hanselmann
  response = cl.QueryFields(resource, fields)
2938 ee3aedff Michael Hanselmann
2939 ee3aedff Michael Hanselmann
  found_unknown = _WarnUnknownFields(response.fields)
2940 ee3aedff Michael Hanselmann
2941 ee3aedff Michael Hanselmann
  columns = [
2942 ee3aedff Michael Hanselmann
    TableColumn("Name", str, False),
2943 ee3aedff Michael Hanselmann
    TableColumn("Title", str, False),
2944 ea1440c1 Michael Hanselmann
    TableColumn("Description", str, False),
2945 ee3aedff Michael Hanselmann
    ]
2946 ee3aedff Michael Hanselmann
2947 ea1440c1 Michael Hanselmann
  rows = [[fdef.name, fdef.title, fdef.doc] for fdef in response.fields]
2948 ee3aedff Michael Hanselmann
2949 ee3aedff Michael Hanselmann
  for line in FormatTable(rows, columns, header, separator):
2950 ee3aedff Michael Hanselmann
    ToStdout(line)
2951 ee3aedff Michael Hanselmann
2952 ee3aedff Michael Hanselmann
  if found_unknown:
2953 ee3aedff Michael Hanselmann
    return constants.EXIT_UNKNOWN_FIELD
2954 ee3aedff Michael Hanselmann
2955 ee3aedff Michael Hanselmann
  return constants.EXIT_SUCCESS
2956 ee3aedff Michael Hanselmann
2957 ee3aedff Michael Hanselmann
2958 ee3aedff Michael Hanselmann
class TableColumn:
2959 ee3aedff Michael Hanselmann
  """Describes a column for L{FormatTable}.
2960 ee3aedff Michael Hanselmann

2961 ee3aedff Michael Hanselmann
  """
2962 ee3aedff Michael Hanselmann
  def __init__(self, title, fn, align_right):
2963 ee3aedff Michael Hanselmann
    """Initializes this class.
2964 ee3aedff Michael Hanselmann

2965 ee3aedff Michael Hanselmann
    @type title: string
2966 ee3aedff Michael Hanselmann
    @param title: Column title
2967 ee3aedff Michael Hanselmann
    @type fn: callable
2968 ee3aedff Michael Hanselmann
    @param fn: Formatting function
2969 ee3aedff Michael Hanselmann
    @type align_right: bool
2970 ee3aedff Michael Hanselmann
    @param align_right: Whether to align values on the right-hand side
2971 ee3aedff Michael Hanselmann

2972 ee3aedff Michael Hanselmann
    """
2973 ee3aedff Michael Hanselmann
    self.title = title
2974 ee3aedff Michael Hanselmann
    self.format = fn
2975 ee3aedff Michael Hanselmann
    self.align_right = align_right
2976 ee3aedff Michael Hanselmann
2977 ee3aedff Michael Hanselmann
2978 ee3aedff Michael Hanselmann
def _GetColFormatString(width, align_right):
2979 ee3aedff Michael Hanselmann
  """Returns the format string for a field.
2980 ee3aedff Michael Hanselmann

2981 ee3aedff Michael Hanselmann
  """
2982 ee3aedff Michael Hanselmann
  if align_right:
2983 ee3aedff Michael Hanselmann
    sign = ""
2984 ee3aedff Michael Hanselmann
  else:
2985 ee3aedff Michael Hanselmann
    sign = "-"
2986 ee3aedff Michael Hanselmann
2987 ee3aedff Michael Hanselmann
  return "%%%s%ss" % (sign, width)
2988 ee3aedff Michael Hanselmann
2989 ee3aedff Michael Hanselmann
2990 ee3aedff Michael Hanselmann
def FormatTable(rows, columns, header, separator):
2991 ee3aedff Michael Hanselmann
  """Formats data as a table.
2992 ee3aedff Michael Hanselmann

2993 ee3aedff Michael Hanselmann
  @type rows: list of lists
2994 ee3aedff Michael Hanselmann
  @param rows: Row data, one list per row
2995 ee3aedff Michael Hanselmann
  @type columns: list of L{TableColumn}
2996 ee3aedff Michael Hanselmann
  @param columns: Column descriptions
2997 ee3aedff Michael Hanselmann
  @type header: bool
2998 ee3aedff Michael Hanselmann
  @param header: Whether to show header row
2999 ee3aedff Michael Hanselmann
  @type separator: string or None
3000 ee3aedff Michael Hanselmann
  @param separator: String used to separate columns
3001 ee3aedff Michael Hanselmann

3002 ee3aedff Michael Hanselmann
  """
3003 ee3aedff Michael Hanselmann
  if header:
3004 ee3aedff Michael Hanselmann
    data = [[col.title for col in columns]]
3005 ee3aedff Michael Hanselmann
    colwidth = [len(col.title) for col in columns]
3006 ee3aedff Michael Hanselmann
  else:
3007 ee3aedff Michael Hanselmann
    data = []
3008 ee3aedff Michael Hanselmann
    colwidth = [0 for _ in columns]
3009 ee3aedff Michael Hanselmann
3010 ee3aedff Michael Hanselmann
  # Format row data
3011 ee3aedff Michael Hanselmann
  for row in rows:
3012 ee3aedff Michael Hanselmann
    assert len(row) == len(columns)
3013 ee3aedff Michael Hanselmann
3014 ee3aedff Michael Hanselmann
    formatted = [col.format(value) for value, col in zip(row, columns)]
3015 ee3aedff Michael Hanselmann
3016 ee3aedff Michael Hanselmann
    if separator is None:
3017 ee3aedff Michael Hanselmann
      # Update column widths
3018 ee3aedff Michael Hanselmann
      for idx, (oldwidth, value) in enumerate(zip(colwidth, formatted)):
3019 ee3aedff Michael Hanselmann
        # Modifying a list's items while iterating is fine
3020 ee3aedff Michael Hanselmann
        colwidth[idx] = max(oldwidth, len(value))
3021 ee3aedff Michael Hanselmann
3022 ee3aedff Michael Hanselmann
    data.append(formatted)
3023 ee3aedff Michael Hanselmann
3024 ee3aedff Michael Hanselmann
  if separator is not None:
3025 ee3aedff Michael Hanselmann
    # Return early if a separator is used
3026 ee3aedff Michael Hanselmann
    return [separator.join(row) for row in data]
3027 ee3aedff Michael Hanselmann
3028 ee3aedff Michael Hanselmann
  if columns and not columns[-1].align_right:
3029 ee3aedff Michael Hanselmann
    # Avoid unnecessary spaces at end of line
3030 ee3aedff Michael Hanselmann
    colwidth[-1] = 0
3031 ee3aedff Michael Hanselmann
3032 ee3aedff Michael Hanselmann
  # Build format string
3033 ee3aedff Michael Hanselmann
  fmt = " ".join([_GetColFormatString(width, col.align_right)
3034 ee3aedff Michael Hanselmann
                  for col, width in zip(columns, colwidth)])
3035 ee3aedff Michael Hanselmann
3036 ee3aedff Michael Hanselmann
  return [fmt % tuple(row) for row in data]
3037 ee3aedff Michael Hanselmann
3038 ee3aedff Michael Hanselmann
3039 3386e7a9 Iustin Pop
def FormatTimestamp(ts):
3040 3386e7a9 Iustin Pop
  """Formats a given timestamp.
3041 3386e7a9 Iustin Pop

3042 3386e7a9 Iustin Pop
  @type ts: timestamp
3043 3386e7a9 Iustin Pop
  @param ts: a timeval-type timestamp, a tuple of seconds and microseconds
3044 3386e7a9 Iustin Pop

3045 3386e7a9 Iustin Pop
  @rtype: string
3046 5fcc718f Iustin Pop
  @return: a string with the formatted timestamp
3047 3386e7a9 Iustin Pop

3048 3386e7a9 Iustin Pop
  """
3049 e687ec01 Michael Hanselmann
  if not isinstance(ts, (tuple, list)) or len(ts) != 2:
3050 d0c8c01d Iustin Pop
    return "?"
3051 26a72a48 Michael Hanselmann
3052 26a72a48 Michael Hanselmann
  (sec, usecs) = ts
3053 26a72a48 Michael Hanselmann
  return utils.FormatTime(sec, usecs=usecs)
3054 2241e2b9 Iustin Pop
3055 2241e2b9 Iustin Pop
3056 2241e2b9 Iustin Pop
def ParseTimespec(value):
3057 2241e2b9 Iustin Pop
  """Parse a time specification.
3058 2241e2b9 Iustin Pop

3059 2241e2b9 Iustin Pop
  The following suffixed will be recognized:
3060 2241e2b9 Iustin Pop

3061 2241e2b9 Iustin Pop
    - s: seconds
3062 2241e2b9 Iustin Pop
    - m: minutes
3063 2241e2b9 Iustin Pop
    - h: hours
3064 2241e2b9 Iustin Pop
    - d: day
3065 2241e2b9 Iustin Pop
    - w: weeks
3066 2241e2b9 Iustin Pop

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

3069 2241e2b9 Iustin Pop
  """
3070 2241e2b9 Iustin Pop
  value = str(value)
3071 2241e2b9 Iustin Pop
  if not value:
3072 2241e2b9 Iustin Pop
    raise errors.OpPrereqError("Empty time specification passed")
3073 2241e2b9 Iustin Pop
  suffix_map = {
3074 d0c8c01d Iustin Pop
    "s": 1,
3075 d0c8c01d Iustin Pop
    "m": 60,
3076 d0c8c01d Iustin Pop
    "h": 3600,
3077 d0c8c01d Iustin Pop
    "d": 86400,
3078 d0c8c01d Iustin Pop
    "w": 604800,
3079 2241e2b9 Iustin Pop
    }
3080 2241e2b9 Iustin Pop
  if value[-1] not in suffix_map:
3081 2241e2b9 Iustin Pop
    try:
3082 2241e2b9 Iustin Pop
      value = int(value)
3083 691744c4 Iustin Pop
    except (TypeError, ValueError):
3084 2241e2b9 Iustin Pop
      raise errors.OpPrereqError("Invalid time specification '%s'" % value)
3085 2241e2b9 Iustin Pop
  else:
3086 2241e2b9 Iustin Pop
    multiplier = suffix_map[value[-1]]
3087 2241e2b9 Iustin Pop
    value = value[:-1]
3088 2241e2b9 Iustin Pop
    if not value: # no data left after stripping the suffix
3089 2241e2b9 Iustin Pop
      raise errors.OpPrereqError("Invalid time specification (only"
3090 2241e2b9 Iustin Pop
                                 " suffix passed)")
3091 2241e2b9 Iustin Pop
    try:
3092 2241e2b9 Iustin Pop
      value = int(value) * multiplier
3093 691744c4 Iustin Pop
    except (TypeError, ValueError):
3094 2241e2b9 Iustin Pop
      raise errors.OpPrereqError("Invalid time specification '%s'" % value)
3095 2241e2b9 Iustin Pop
  return value
3096 46fbdd04 Iustin Pop
3097 46fbdd04 Iustin Pop
3098 e9e26bb3 Iustin Pop
def GetOnlineNodes(nodes, cl=None, nowarn=False, secondary_ips=False,
3099 05484a24 Michael Hanselmann
                   filter_master=False, nodegroup=None):
3100 4040a784 Iustin Pop
  """Returns the names of online nodes.
3101 4040a784 Iustin Pop

3102 4040a784 Iustin Pop
  This function will also log a warning on stderr with the names of
3103 4040a784 Iustin Pop
  the online nodes.
3104 4040a784 Iustin Pop

3105 4040a784 Iustin Pop
  @param nodes: if not empty, use only this subset of nodes (minus the
3106 4040a784 Iustin Pop
      offline ones)
3107 4040a784 Iustin Pop
  @param cl: if not None, luxi client to use
3108 4040a784 Iustin Pop
  @type nowarn: boolean
3109 4040a784 Iustin Pop
  @param nowarn: by default, this function will output a note with the
3110 4040a784 Iustin Pop
      offline nodes that are skipped; if this parameter is True the
3111 4040a784 Iustin Pop
      note is not displayed
3112 e9e26bb3 Iustin Pop
  @type secondary_ips: boolean
3113 e9e26bb3 Iustin Pop
  @param secondary_ips: if True, return the secondary IPs instead of the
3114 e9e26bb3 Iustin Pop
      names, useful for doing network traffic over the replication interface
3115 e9e26bb3 Iustin Pop
      (if any)
3116 e9e26bb3 Iustin Pop
  @type filter_master: boolean
3117 e9e26bb3 Iustin Pop
  @param filter_master: if True, do not return the master node in the list
3118 e9e26bb3 Iustin Pop
      (useful in coordination with secondary_ips where we cannot check our
3119 e9e26bb3 Iustin Pop
      node name against the list)
3120 05484a24 Michael Hanselmann
  @type nodegroup: string
3121 05484a24 Michael Hanselmann
  @param nodegroup: If set, only return nodes in this node group
3122 4040a784 Iustin Pop

3123 4040a784 Iustin Pop
  """
3124 4040a784 Iustin Pop
  if cl is None:
3125 4040a784 Iustin Pop
    cl = GetClient()
3126 4040a784 Iustin Pop
3127 2e5c33db Iustin Pop
  qfilter = []
3128 05484a24 Michael Hanselmann
3129 05484a24 Michael Hanselmann
  if nodes:
3130 2e5c33db Iustin Pop
    qfilter.append(qlang.MakeSimpleFilter("name", nodes))
3131 05484a24 Michael Hanselmann
3132 05484a24 Michael Hanselmann
  if nodegroup is not None:
3133 2e5c33db Iustin Pop
    qfilter.append([qlang.OP_OR, [qlang.OP_EQUAL, "group", nodegroup],
3134 05484a24 Michael Hanselmann
                                 [qlang.OP_EQUAL, "group.uuid", nodegroup]])
3135 e9e26bb3 Iustin Pop
3136 e9e26bb3 Iustin Pop
  if filter_master:
3137 2e5c33db Iustin Pop
    qfilter.append([qlang.OP_NOT, [qlang.OP_TRUE, "master"]])
3138 05484a24 Michael Hanselmann
3139 2e5c33db Iustin Pop
  if qfilter:
3140 2e5c33db Iustin Pop
    if len(qfilter) > 1:
3141 2e5c33db Iustin Pop
      final_filter = [qlang.OP_AND] + qfilter
3142 05484a24 Michael Hanselmann
    else:
3143 2e5c33db Iustin Pop
      assert len(qfilter) == 1
3144 2e5c33db Iustin Pop
      final_filter = qfilter[0]
3145 e9e26bb3 Iustin Pop
  else:
3146 05484a24 Michael Hanselmann
    final_filter = None
3147 05484a24 Michael Hanselmann
3148 05484a24 Michael Hanselmann
  result = cl.Query(constants.QR_NODE, ["name", "offline", "sip"], final_filter)
3149 05484a24 Michael Hanselmann
3150 05484a24 Michael Hanselmann
  def _IsOffline(row):
3151 05484a24 Michael Hanselmann
    (_, (_, offline), _) = row
3152 05484a24 Michael Hanselmann
    return offline
3153 05484a24 Michael Hanselmann
3154 05484a24 Michael Hanselmann
  def _GetName(row):
3155 05484a24 Michael Hanselmann
    ((_, name), _, _) = row
3156 05484a24 Michael Hanselmann
    return name
3157 05484a24 Michael Hanselmann
3158 05484a24 Michael Hanselmann
  def _GetSip(row):
3159 05484a24 Michael Hanselmann
    (_, _, (_, sip)) = row
3160 05484a24 Michael Hanselmann
    return sip
3161 05484a24 Michael Hanselmann
3162 05484a24 Michael Hanselmann
  (offline, online) = compat.partition(result.data, _IsOffline)
3163 e9e26bb3 Iustin Pop
3164 4040a784 Iustin Pop
  if offline and not nowarn:
3165 05484a24 Michael Hanselmann
    ToStderr("Note: skipping offline node(s): %s" %
3166 05484a24 Michael Hanselmann
             utils.CommaJoin(map(_GetName, offline)))
3167 05484a24 Michael Hanselmann
3168 05484a24 Michael Hanselmann
  if secondary_ips:
3169 05484a24 Michael Hanselmann
    fn = _GetSip
3170 05484a24 Michael Hanselmann
  else:
3171 05484a24 Michael Hanselmann
    fn = _GetName
3172 05484a24 Michael Hanselmann
3173 05484a24 Michael Hanselmann
  return map(fn, online)
3174 4040a784 Iustin Pop
3175 4040a784 Iustin Pop
3176 46fbdd04 Iustin Pop
def _ToStream(stream, txt, *args):
3177 46fbdd04 Iustin Pop
  """Write a message to a stream, bypassing the logging system
3178 46fbdd04 Iustin Pop

3179 46fbdd04 Iustin Pop
  @type stream: file object
3180 46fbdd04 Iustin Pop
  @param stream: the file to which we should write
3181 46fbdd04 Iustin Pop
  @type txt: str
3182 46fbdd04 Iustin Pop
  @param txt: the message
3183 46fbdd04 Iustin Pop

3184 46fbdd04 Iustin Pop
  """
3185 225e2544 Iustin Pop
  try:
3186 225e2544 Iustin Pop
    if args:
3187 225e2544 Iustin Pop
      args = tuple(args)
3188 225e2544 Iustin Pop
      stream.write(txt % args)
3189 225e2544 Iustin Pop
    else:
3190 225e2544 Iustin Pop
      stream.write(txt)
3191 d0c8c01d Iustin Pop
    stream.write("\n")
3192 225e2544 Iustin Pop
    stream.flush()
3193 225e2544 Iustin Pop
  except IOError, err:
3194 225e2544 Iustin Pop
    if err.errno == errno.EPIPE:
3195 225e2544 Iustin Pop
      # our terminal went away, we'll exit
3196 225e2544 Iustin Pop
      sys.exit(constants.EXIT_FAILURE)
3197 225e2544 Iustin Pop
    else:
3198 225e2544 Iustin Pop
      raise
3199 46fbdd04 Iustin Pop
3200 46fbdd04 Iustin Pop
3201 46fbdd04 Iustin Pop
def ToStdout(txt, *args):
3202 46fbdd04 Iustin Pop
  """Write a message to stdout only, bypassing the logging system
3203 46fbdd04 Iustin Pop

3204 46fbdd04 Iustin Pop
  This is just a wrapper over _ToStream.
3205 46fbdd04 Iustin Pop

3206 46fbdd04 Iustin Pop
  @type txt: str
3207 46fbdd04 Iustin Pop
  @param txt: the message
3208 46fbdd04 Iustin Pop

3209 46fbdd04 Iustin Pop
  """
3210 46fbdd04 Iustin Pop
  _ToStream(sys.stdout, txt, *args)
3211 46fbdd04 Iustin Pop
3212 46fbdd04 Iustin Pop
3213 46fbdd04 Iustin Pop
def ToStderr(txt, *args):
3214 46fbdd04 Iustin Pop
  """Write a message to stderr only, bypassing the logging system
3215 46fbdd04 Iustin Pop

3216 46fbdd04 Iustin Pop
  This is just a wrapper over _ToStream.
3217 46fbdd04 Iustin Pop

3218 46fbdd04 Iustin Pop
  @type txt: str
3219 46fbdd04 Iustin Pop
  @param txt: the message
3220 46fbdd04 Iustin Pop

3221 46fbdd04 Iustin Pop
  """
3222 46fbdd04 Iustin Pop
  _ToStream(sys.stderr, txt, *args)
3223 479636a3 Iustin Pop
3224 479636a3 Iustin Pop
3225 479636a3 Iustin Pop
class JobExecutor(object):
3226 479636a3 Iustin Pop
  """Class which manages the submission and execution of multiple jobs.
3227 479636a3 Iustin Pop

3228 479636a3 Iustin Pop
  Note that instances of this class should not be reused between
3229 479636a3 Iustin Pop
  GetResults() calls.
3230 479636a3 Iustin Pop

3231 479636a3 Iustin Pop
  """
3232 919ca415 Iustin Pop
  def __init__(self, cl=None, verbose=True, opts=None, feedback_fn=None):
3233 479636a3 Iustin Pop
    self.queue = []
3234 479636a3 Iustin Pop
    if cl is None:
3235 479636a3 Iustin Pop
      cl = GetClient()
3236 479636a3 Iustin Pop
    self.cl = cl
3237 479636a3 Iustin Pop
    self.verbose = verbose
3238 23b4b983 Iustin Pop
    self.jobs = []
3239 cff5fa7f Iustin Pop
    self.opts = opts
3240 919ca415 Iustin Pop
    self.feedback_fn = feedback_fn
3241 60452edf Michael Hanselmann
    self._counter = itertools.count()
3242 479636a3 Iustin Pop
3243 8d99a8bf Michael Hanselmann
  @staticmethod
3244 8d99a8bf Michael Hanselmann
  def _IfName(name, fmt):
3245 8d99a8bf Michael Hanselmann
    """Helper function for formatting name.
3246 8d99a8bf Michael Hanselmann

3247 8d99a8bf Michael Hanselmann
    """
3248 8d99a8bf Michael Hanselmann
    if name:
3249 8d99a8bf Michael Hanselmann
      return fmt % name
3250 8d99a8bf Michael Hanselmann
3251 8d99a8bf Michael Hanselmann
    return ""
3252 8d99a8bf Michael Hanselmann
3253 479636a3 Iustin Pop
  def QueueJob(self, name, *ops):
3254 23b4b983 Iustin Pop
    """Record a job for later submit.
3255 479636a3 Iustin Pop

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

3259 479636a3 Iustin Pop
    """
3260 cff5fa7f Iustin Pop
    SetGenericOpcodeOpts(ops, self.opts)
3261 60452edf Michael Hanselmann
    self.queue.append((self._counter.next(), name, ops))
3262 23b4b983 Iustin Pop
3263 8d99a8bf Michael Hanselmann
  def AddJobId(self, name, status, job_id):
3264 8d99a8bf Michael Hanselmann
    """Adds a job ID to the internal queue.
3265 8d99a8bf Michael Hanselmann

3266 8d99a8bf Michael Hanselmann
    """
3267 8d99a8bf Michael Hanselmann
    self.jobs.append((self._counter.next(), status, job_id, name))
3268 8d99a8bf Michael Hanselmann
3269 66ecc479 Guido Trotter
  def SubmitPending(self, each=False):
3270 23b4b983 Iustin Pop
    """Submit all pending jobs.
3271 23b4b983 Iustin Pop

3272 23b4b983 Iustin Pop
    """
3273 66ecc479 Guido Trotter
    if each:
3274 66ecc479 Guido Trotter
      results = []
3275 60452edf Michael Hanselmann
      for (_, _, ops) in self.queue:
3276 66ecc479 Guido Trotter
        # SubmitJob will remove the success status, but raise an exception if
3277 66ecc479 Guido Trotter
        # the submission fails, so we'll notice that anyway.
3278 519fafa1 Andrea Spadaccini
        results.append([True, self.cl.SubmitJob(ops)[0]])
3279 66ecc479 Guido Trotter
    else:
3280 60452edf Michael Hanselmann
      results = self.cl.SubmitManyJobs([ops for (_, _, ops) in self.queue])
3281 60452edf Michael Hanselmann
    for ((status, data), (idx, name, _)) in zip(results, self.queue):
3282 5299e61f Iustin Pop
      self.jobs.append((idx, status, data, name))
3283 5299e61f Iustin Pop
3284 5299e61f Iustin Pop
  def _ChooseJob(self):
3285 5299e61f Iustin Pop
    """Choose a non-waiting/queued job to poll next.
3286 5299e61f Iustin Pop

3287 5299e61f Iustin Pop
    """
3288 5299e61f Iustin Pop
    assert self.jobs, "_ChooseJob called with empty job list"
3289 5299e61f Iustin Pop
3290 11705e3d Iustin Pop
    result = self.cl.QueryJobs([i[2] for i in self.jobs[:_CHOOSE_BATCH]],
3291 11705e3d Iustin Pop
                               ["status"])
3292 5299e61f Iustin Pop
    assert result
3293 5299e61f Iustin Pop
3294 5299e61f Iustin Pop
    for job_data, status in zip(self.jobs, result):
3295 91c622a8 Iustin Pop
      if (isinstance(status, list) and status and
3296 91c622a8 Iustin Pop
          status[0] in (constants.JOB_STATUS_QUEUED,
3297 47099cd1 Michael Hanselmann
                        constants.JOB_STATUS_WAITING,
3298 91c622a8 Iustin Pop
                        constants.JOB_STATUS_CANCELING)):
3299 91c622a8 Iustin Pop
        # job is still present and waiting
3300 5299e61f Iustin Pop
        continue
3301 91c622a8 Iustin Pop
      # good candidate found (either running job or lost job)
3302 5299e61f Iustin Pop
      self.jobs.remove(job_data)
3303 5299e61f Iustin Pop
      return job_data
3304 5299e61f Iustin Pop
3305 5299e61f Iustin Pop
    # no job found
3306 5299e61f Iustin Pop
    return self.jobs.pop(0)
3307 479636a3 Iustin Pop
3308 479636a3 Iustin Pop
  def GetResults(self):
3309 479636a3 Iustin Pop
    """Wait for and return the results of all jobs.
3310 479636a3 Iustin Pop

3311 479636a3 Iustin Pop
    @rtype: list
3312 479636a3 Iustin Pop
    @return: list of tuples (success, job results), in the same order
3313 479636a3 Iustin Pop
        as the submitted jobs; if a job has failed, instead of the result
3314 479636a3 Iustin Pop
        there will be the error message
3315 479636a3 Iustin Pop

3316 479636a3 Iustin Pop
    """
3317 23b4b983 Iustin Pop
    if not self.jobs:
3318 23b4b983 Iustin Pop
      self.SubmitPending()
3319 479636a3 Iustin Pop
    results = []
3320 479636a3 Iustin Pop
    if self.verbose:
3321 5299e61f Iustin Pop
      ok_jobs = [row[2] for row in self.jobs if row[1]]
3322 23b4b983 Iustin Pop
      if ok_jobs:
3323 4474f112 Iustin Pop
        ToStdout("Submitted jobs %s", utils.CommaJoin(ok_jobs))
3324 5299e61f Iustin Pop
3325 5299e61f Iustin Pop
    # first, remove any non-submitted jobs
3326 cea881e5 Michael Hanselmann
    self.jobs, failures = compat.partition(self.jobs, lambda x: x[1])
3327 5299e61f Iustin Pop
    for idx, _, jid, name in failures:
3328 4474f112 Iustin Pop
      ToStderr("Failed to submit job%s: %s", self._IfName(name, " for %s"), jid)
3329 c63355f2 Iustin Pop
      results.append((idx, False, jid))
3330 5299e61f Iustin Pop
3331 5299e61f Iustin Pop
    while self.jobs:
3332 5299e61f Iustin Pop
      (idx, _, jid, name) = self._ChooseJob()
3333 4474f112 Iustin Pop
      ToStdout("Waiting for job %s%s ...", jid, self._IfName(name, " for %s"))
3334 479636a3 Iustin Pop
      try:
3335 919ca415 Iustin Pop
        job_result = PollJob(jid, cl=self.cl, feedback_fn=self.feedback_fn)
3336 479636a3 Iustin Pop
        success = True
3337 91c622a8 Iustin Pop
      except errors.JobLost, err:
3338 91c622a8 Iustin Pop
        _, job_result = FormatError(err)
3339 4474f112 Iustin Pop
        ToStderr("Job %s%s has been archived, cannot check its result",
3340 4474f112 Iustin Pop
                 jid, self._IfName(name, " for %s"))
3341 91c622a8 Iustin Pop
        success = False
3342 479636a3 Iustin Pop
      except (errors.GenericError, luxi.ProtocolError), err:
3343 479636a3 Iustin Pop
        _, job_result = FormatError(err)
3344 479636a3 Iustin Pop
        success = False
3345 479636a3 Iustin Pop
        # the error message will always be shown, verbose or not
3346 4474f112 Iustin Pop
        ToStderr("Job %s%s has failed: %s",
3347 4474f112 Iustin Pop
                 jid, self._IfName(name, " for %s"), job_result)
3348 479636a3 Iustin Pop
3349 5299e61f Iustin Pop
      results.append((idx, success, job_result))
3350 5299e61f Iustin Pop
3351 5299e61f Iustin Pop
    # sort based on the index, then drop it
3352 5299e61f Iustin Pop
    results.sort()
3353 5299e61f Iustin Pop
    results = [i[1:] for i in results]
3354 5299e61f Iustin Pop
3355 479636a3 Iustin Pop
    return results
3356 479636a3 Iustin Pop
3357 479636a3 Iustin Pop
  def WaitOrShow(self, wait):
3358 479636a3 Iustin Pop
    """Wait for job results or only print the job IDs.
3359 479636a3 Iustin Pop

3360 479636a3 Iustin Pop
    @type wait: boolean
3361 479636a3 Iustin Pop
    @param wait: whether to wait or not
3362 479636a3 Iustin Pop

3363 479636a3 Iustin Pop
    """
3364 479636a3 Iustin Pop
    if wait:
3365 479636a3 Iustin Pop
      return self.GetResults()
3366 479636a3 Iustin Pop
    else:
3367 23b4b983 Iustin Pop
      if not self.jobs:
3368 23b4b983 Iustin Pop
        self.SubmitPending()
3369 71834b2a Guido Trotter
      for _, status, result, name in self.jobs:
3370 23b4b983 Iustin Pop
        if status:
3371 4474f112 Iustin Pop
          ToStdout("%s: %s", result, name)
3372 23b4b983 Iustin Pop
        else:
3373 4474f112 Iustin Pop
          ToStderr("Failure for %s: %s", name, result)
3374 53a8a54d Iustin Pop
      return [row[1:3] for row in self.jobs]
3375 acd19189 René Nussbaumer
3376 acd19189 René Nussbaumer
3377 acd19189 René Nussbaumer
def FormatParameterDict(buf, param_dict, actual, level=1):
3378 acd19189 René Nussbaumer
  """Formats a parameter dictionary.
3379 acd19189 René Nussbaumer

3380 acd19189 René Nussbaumer
  @type buf: L{StringIO}
3381 acd19189 René Nussbaumer
  @param buf: the buffer into which to write
3382 acd19189 René Nussbaumer
  @type param_dict: dict
3383 acd19189 René Nussbaumer
  @param param_dict: the own parameters
3384 acd19189 René Nussbaumer
  @type actual: dict
3385 acd19189 René Nussbaumer
  @param actual: the current parameter set (including defaults)
3386 acd19189 René Nussbaumer
  @param level: Level of indent
3387 acd19189 René Nussbaumer

3388 acd19189 René Nussbaumer
  """
3389 acd19189 René Nussbaumer
  indent = "  " * level
3390 64da5a53 René Nussbaumer
3391 acd19189 René Nussbaumer
  for key in sorted(actual):
3392 64da5a53 René Nussbaumer
    data = actual[key]
3393 64da5a53 René Nussbaumer
    buf.write("%s- %s:" % (indent, key))
3394 64da5a53 René Nussbaumer
3395 64da5a53 René Nussbaumer
    if isinstance(data, dict) and data:
3396 64da5a53 René Nussbaumer
      buf.write("\n")
3397 64da5a53 René Nussbaumer
      FormatParameterDict(buf, param_dict.get(key, {}), data,
3398 64da5a53 René Nussbaumer
                          level=level + 1)
3399 64da5a53 René Nussbaumer
    else:
3400 64da5a53 René Nussbaumer
      val = param_dict.get(key, "default (%s)" % data)
3401 64da5a53 René Nussbaumer
      buf.write(" %s\n" % val)
3402 25bd815c René Nussbaumer
3403 25bd815c René Nussbaumer
3404 25bd815c René Nussbaumer
def ConfirmOperation(names, list_type, text, extra=""):
3405 25bd815c René Nussbaumer
  """Ask the user to confirm an operation on a list of list_type.
3406 25bd815c René Nussbaumer

3407 25bd815c René Nussbaumer
  This function is used to request confirmation for doing an operation
3408 25bd815c René Nussbaumer
  on a given list of list_type.
3409 25bd815c René Nussbaumer

3410 25bd815c René Nussbaumer
  @type names: list
3411 25bd815c René Nussbaumer
  @param names: the list of names that we display when
3412 25bd815c René Nussbaumer
      we ask for confirmation
3413 25bd815c René Nussbaumer
  @type list_type: str
3414 25bd815c René Nussbaumer
  @param list_type: Human readable name for elements in the list (e.g. nodes)
3415 25bd815c René Nussbaumer
  @type text: str
3416 25bd815c René Nussbaumer
  @param text: the operation that the user should confirm
3417 25bd815c René Nussbaumer
  @rtype: boolean
3418 25bd815c René Nussbaumer
  @return: True or False depending on user's confirmation.
3419 25bd815c René Nussbaumer

3420 25bd815c René Nussbaumer
  """
3421 25bd815c René Nussbaumer
  count = len(names)
3422 25bd815c René Nussbaumer
  msg = ("The %s will operate on %d %s.\n%s"
3423 25bd815c René Nussbaumer
         "Do you want to continue?" % (text, count, list_type, extra))
3424 25bd815c René Nussbaumer
  affected = (("\nAffected %s:\n" % list_type) +
3425 25bd815c René Nussbaumer
              "\n".join(["  %s" % name for name in names]))
3426 25bd815c René Nussbaumer
3427 25bd815c René Nussbaumer
  choices = [("y", True, "Yes, execute the %s" % text),
3428 25bd815c René Nussbaumer
             ("n", False, "No, abort the %s" % text)]
3429 25bd815c René Nussbaumer
3430 25bd815c René Nussbaumer
  if count > 20:
3431 25bd815c René Nussbaumer
    choices.insert(1, ("v", "v", "View the list of affected %s" % list_type))
3432 25bd815c René Nussbaumer
    question = msg
3433 25bd815c René Nussbaumer
  else:
3434 25bd815c René Nussbaumer
    question = msg + affected
3435 25bd815c René Nussbaumer
3436 25bd815c René Nussbaumer
  choice = AskUser(question, choices)
3437 25bd815c René Nussbaumer
  if choice == "v":
3438 25bd815c René Nussbaumer
    choices.pop(1)
3439 25bd815c René Nussbaumer
    choice = AskUser(msg + affected, choices)
3440 25bd815c René Nussbaumer
  return choice
3441 703fa9ab Iustin Pop
3442 703fa9ab Iustin Pop
3443 cd415612 René Nussbaumer
def _MaybeParseUnit(elements):
3444 cd415612 René Nussbaumer
  """Parses and returns an array of potential values with units.
3445 cd415612 René Nussbaumer

3446 cd415612 René Nussbaumer
  """
3447 ef40c537 René Nussbaumer
  parsed = {}
3448 ef40c537 René Nussbaumer
  for k, v in elements.items():
3449 ef40c537 René Nussbaumer
    if v == constants.VALUE_DEFAULT:
3450 ef40c537 René Nussbaumer
      parsed[k] = v
3451 cd415612 René Nussbaumer
    else:
3452 ef40c537 René Nussbaumer
      parsed[k] = utils.ParseUnit(v)
3453 cd415612 René Nussbaumer
  return parsed
3454 cd415612 René Nussbaumer
3455 cd415612 René Nussbaumer
3456 703fa9ab Iustin Pop
def CreateIPolicyFromOpts(ispecs_mem_size=None,
3457 703fa9ab Iustin Pop
                          ispecs_cpu_count=None,
3458 703fa9ab Iustin Pop
                          ispecs_disk_count=None,
3459 703fa9ab Iustin Pop
                          ispecs_disk_size=None,
3460 703fa9ab Iustin Pop
                          ispecs_nic_count=None,
3461 703fa9ab Iustin Pop
                          ipolicy_disk_templates=None,
3462 703fa9ab Iustin Pop
                          ipolicy_vcpu_ratio=None,
3463 ad5cc6bd René Nussbaumer
                          ipolicy_spindle_ratio=None,
3464 703fa9ab Iustin Pop
                          group_ipolicy=False,
3465 703fa9ab Iustin Pop
                          allowed_values=None,
3466 703fa9ab Iustin Pop
                          fill_all=False):
3467 703fa9ab Iustin Pop
  """Creation of instance policy based on command line options.
3468 703fa9ab Iustin Pop

3469 703fa9ab Iustin Pop
  @param fill_all: whether for cluster policies we should ensure that
3470 703fa9ab Iustin Pop
    all values are filled
3471 703fa9ab Iustin Pop

3472 703fa9ab Iustin Pop

3473 703fa9ab Iustin Pop
  """
3474 d67e0a94 Iustin Pop
  try:
3475 d67e0a94 Iustin Pop
    if ispecs_mem_size:
3476 cd415612 René Nussbaumer
      ispecs_mem_size = _MaybeParseUnit(ispecs_mem_size)
3477 d67e0a94 Iustin Pop
    if ispecs_disk_size:
3478 cd415612 René Nussbaumer
      ispecs_disk_size = _MaybeParseUnit(ispecs_disk_size)
3479 d67e0a94 Iustin Pop
  except (TypeError, ValueError, errors.UnitParseError), err:
3480 d67e0a94 Iustin Pop
    raise errors.OpPrereqError("Invalid disk (%s) or memory (%s) size"
3481 d67e0a94 Iustin Pop
                               " in policy: %s" %
3482 d67e0a94 Iustin Pop
                               (ispecs_disk_size, ispecs_mem_size, err),
3483 d67e0a94 Iustin Pop
                               errors.ECODE_INVAL)
3484 d67e0a94 Iustin Pop
3485 703fa9ab Iustin Pop
  # prepare ipolicy dict
3486 703fa9ab Iustin Pop
  ipolicy_transposed = {
3487 703fa9ab Iustin Pop
    constants.ISPEC_MEM_SIZE: ispecs_mem_size,
3488 703fa9ab Iustin Pop
    constants.ISPEC_CPU_COUNT: ispecs_cpu_count,
3489 703fa9ab Iustin Pop
    constants.ISPEC_DISK_COUNT: ispecs_disk_count,
3490 703fa9ab Iustin Pop
    constants.ISPEC_DISK_SIZE: ispecs_disk_size,
3491 703fa9ab Iustin Pop
    constants.ISPEC_NIC_COUNT: ispecs_nic_count,
3492 703fa9ab Iustin Pop
    }
3493 703fa9ab Iustin Pop
3494 703fa9ab Iustin Pop
  # first, check that the values given are correct
3495 703fa9ab Iustin Pop
  if group_ipolicy:
3496 703fa9ab Iustin Pop
    forced_type = TISPECS_GROUP_TYPES
3497 703fa9ab Iustin Pop
  else:
3498 703fa9ab Iustin Pop
    forced_type = TISPECS_CLUSTER_TYPES
3499 703fa9ab Iustin Pop
3500 703fa9ab Iustin Pop
  for specs in ipolicy_transposed.values():
3501 703fa9ab Iustin Pop
    utils.ForceDictType(specs, forced_type, allowed_values=allowed_values)
3502 703fa9ab Iustin Pop
3503 703fa9ab Iustin Pop
  # then transpose
3504 703fa9ab Iustin Pop
  ipolicy_out = objects.MakeEmptyIPolicy()
3505 703fa9ab Iustin Pop
  for name, specs in ipolicy_transposed.iteritems():
3506 703fa9ab Iustin Pop
    assert name in constants.ISPECS_PARAMETERS
3507 703fa9ab Iustin Pop
    for key, val in specs.items(): # {min: .. ,max: .., std: ..}
3508 703fa9ab Iustin Pop
      ipolicy_out[key][name] = val
3509 703fa9ab Iustin Pop
3510 703fa9ab Iustin Pop
  # no filldict for non-dicts
3511 703fa9ab Iustin Pop
  if not group_ipolicy and fill_all:
3512 703fa9ab Iustin Pop
    if ipolicy_disk_templates is None:
3513 703fa9ab Iustin Pop
      ipolicy_disk_templates = constants.DISK_TEMPLATES
3514 703fa9ab Iustin Pop
    if ipolicy_vcpu_ratio is None:
3515 703fa9ab Iustin Pop
      ipolicy_vcpu_ratio = \
3516 703fa9ab Iustin Pop
        constants.IPOLICY_DEFAULTS[constants.IPOLICY_VCPU_RATIO]
3517 ad5cc6bd René Nussbaumer
    if ipolicy_spindle_ratio is None:
3518 ad5cc6bd René Nussbaumer
      ipolicy_spindle_ratio = \
3519 ad5cc6bd René Nussbaumer
        constants.IPOLICY_DEFAULTS[constants.IPOLICY_SPINDLE_RATIO]
3520 703fa9ab Iustin Pop
  if ipolicy_disk_templates is not None:
3521 703fa9ab Iustin Pop
    ipolicy_out[constants.IPOLICY_DTS] = list(ipolicy_disk_templates)
3522 703fa9ab Iustin Pop
  if ipolicy_vcpu_ratio is not None:
3523 703fa9ab Iustin Pop
    ipolicy_out[constants.IPOLICY_VCPU_RATIO] = ipolicy_vcpu_ratio
3524 ad5cc6bd René Nussbaumer
  if ipolicy_spindle_ratio is not None:
3525 ad5cc6bd René Nussbaumer
    ipolicy_out[constants.IPOLICY_SPINDLE_RATIO] = ipolicy_spindle_ratio
3526 703fa9ab Iustin Pop
3527 703fa9ab Iustin Pop
  assert not (frozenset(ipolicy_out.keys()) - constants.IPOLICY_ALL_KEYS)
3528 703fa9ab Iustin Pop
3529 703fa9ab Iustin Pop
  return ipolicy_out