Statistics
| Branch: | Tag: | Revision:

root / lib / cli.py @ 1a2eb2dc

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

319 863d7f46 Michael Hanselmann
  Value can be any of the ones passed to the constructor.
320 863d7f46 Michael Hanselmann

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

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

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

344 863d7f46 Michael Hanselmann
  """
345 863d7f46 Michael Hanselmann
346 863d7f46 Michael Hanselmann
347 863d7f46 Michael Hanselmann
class ArgInstance(_Argument):
348 863d7f46 Michael Hanselmann
  """Instances argument.
349 863d7f46 Michael Hanselmann

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

356 863d7f46 Michael Hanselmann
  """
357 863d7f46 Michael Hanselmann
358 667dbd6b Adeodato Simo
359 667dbd6b Adeodato Simo
class ArgGroup(_Argument):
360 667dbd6b Adeodato Simo
  """Node group argument.
361 667dbd6b Adeodato Simo

362 667dbd6b Adeodato Simo
  """
363 667dbd6b Adeodato Simo
364 667dbd6b Adeodato Simo
365 863d7f46 Michael Hanselmann
class ArgJobId(_Argument):
366 863d7f46 Michael Hanselmann
  """Job ID argument.
367 863d7f46 Michael Hanselmann

368 863d7f46 Michael Hanselmann
  """
369 863d7f46 Michael Hanselmann
370 863d7f46 Michael Hanselmann
371 863d7f46 Michael Hanselmann
class ArgFile(_Argument):
372 863d7f46 Michael Hanselmann
  """File path argument.
373 863d7f46 Michael Hanselmann

374 863d7f46 Michael Hanselmann
  """
375 863d7f46 Michael Hanselmann
376 863d7f46 Michael Hanselmann
377 863d7f46 Michael Hanselmann
class ArgCommand(_Argument):
378 863d7f46 Michael Hanselmann
  """Command argument.
379 863d7f46 Michael Hanselmann

380 863d7f46 Michael Hanselmann
  """
381 863d7f46 Michael Hanselmann
382 863d7f46 Michael Hanselmann
383 83ec7961 Michael Hanselmann
class ArgHost(_Argument):
384 83ec7961 Michael Hanselmann
  """Host argument.
385 83ec7961 Michael Hanselmann

386 83ec7961 Michael Hanselmann
  """
387 83ec7961 Michael Hanselmann
388 83ec7961 Michael Hanselmann
389 f9faf9c3 René Nussbaumer
class ArgOs(_Argument):
390 f9faf9c3 René Nussbaumer
  """OS argument.
391 f9faf9c3 René Nussbaumer

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

409 846baef9 Iustin Pop
  Note that this function will modify its args parameter.
410 846baef9 Iustin Pop

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

433 810c50b7 Iustin Pop
  This function will extend the tags with the contents of the file
434 810c50b7 Iustin Pop
  passed in the 'tags_source' attribute of the opts parameter. A file
435 810c50b7 Iustin Pop
  named '-' will be replaced by stdin.
436 810c50b7 Iustin Pop

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

600 e7b61bb0 Iustin Pop
  This will store the parsed value as either True or False.
601 e7b61bb0 Iustin Pop

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

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

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

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

1347 552328b8 Michael Hanselmann
  """
1348 552328b8 Michael Hanselmann
  value = _PRIONAME_TO_VALUE[value]
1349 552328b8 Michael Hanselmann
1350 552328b8 Michael Hanselmann
  setattr(parser.values, option.dest, value)
1351 552328b8 Michael Hanselmann
1352 552328b8 Michael Hanselmann
1353 84a5b33c Michael Hanselmann
PRIORITY_OPT = cli_option("--priority", default=None, dest="priority",
1354 84a5b33c Michael Hanselmann
                          metavar="|".join(name for name, _ in _PRIORITY_NAMES),
1355 84a5b33c Michael Hanselmann
                          choices=_PRIONAME_TO_VALUE.keys(),
1356 552328b8 Michael Hanselmann
                          action="callback", type="choice",
1357 552328b8 Michael Hanselmann
                          callback=_PriorityOptionCb,
1358 aa06f8c6 Michael Hanselmann
                          help="Priority for opcode processing")
1359 84a5b33c Michael Hanselmann
1360 61a14bb3 Iustin Pop
HID_OS_OPT = cli_option("--hidden", dest="hidden",
1361 61a14bb3 Iustin Pop
                        type="bool", default=None, metavar=_YORNO,
1362 61a14bb3 Iustin Pop
                        help="Sets the hidden flag on the OS")
1363 61a14bb3 Iustin Pop
1364 61a14bb3 Iustin Pop
BLK_OS_OPT = cli_option("--blacklisted", dest="blacklisted",
1365 61a14bb3 Iustin Pop
                        type="bool", default=None, metavar=_YORNO,
1366 61a14bb3 Iustin Pop
                        help="Sets the blacklisted flag on the OS")
1367 61a14bb3 Iustin Pop
1368 b883637f René Nussbaumer
PREALLOC_WIPE_DISKS_OPT = cli_option("--prealloc-wipe-disks", default=None,
1369 b883637f René Nussbaumer
                                     type="bool", metavar=_YORNO,
1370 b883637f René Nussbaumer
                                     dest="prealloc_wipe_disks",
1371 b883637f René Nussbaumer
                                     help=("Wipe disks prior to instance"
1372 b883637f René Nussbaumer
                                           " creation"))
1373 b883637f René Nussbaumer
1374 a535cef7 René Nussbaumer
NODE_PARAMS_OPT = cli_option("--node-parameters", dest="ndparams",
1375 3c2b6a98 René Nussbaumer
                             type="keyval", default=None,
1376 a535cef7 René Nussbaumer
                             help="Node parameters")
1377 a535cef7 René Nussbaumer
1378 90e99856 Adeodato Simo
ALLOC_POLICY_OPT = cli_option("--alloc-policy", dest="alloc_policy",
1379 90e99856 Adeodato Simo
                              action="store", metavar="POLICY", default=None,
1380 90e99856 Adeodato Simo
                              help="Allocation policy for the node group")
1381 90e99856 Adeodato Simo
1382 d2881c71 René Nussbaumer
NODE_POWERED_OPT = cli_option("--node-powered", default=None,
1383 d2881c71 René Nussbaumer
                              type="bool", metavar=_YORNO,
1384 d2881c71 René Nussbaumer
                              dest="node_powered",
1385 d2881c71 René Nussbaumer
                              help="Specify if the SoR for node is powered")
1386 d2881c71 René Nussbaumer
1387 41543d8b René Nussbaumer
OOB_TIMEOUT_OPT = cli_option("--oob-timeout", dest="oob_timeout", type="int",
1388 5ae4945a Iustin Pop
                             default=constants.OOB_TIMEOUT,
1389 5ae4945a Iustin Pop
                             help="Maximum time to wait for out-of-band helper")
1390 41543d8b René Nussbaumer
1391 0c086a13 René Nussbaumer
POWER_DELAY_OPT = cli_option("--power-delay", dest="power_delay", type="float",
1392 0c086a13 René Nussbaumer
                             default=constants.OOB_POWER_DELAY,
1393 0c086a13 René Nussbaumer
                             help="Time in seconds to wait between power-ons")
1394 0c086a13 René Nussbaumer
1395 442587bf Michael Hanselmann
FORCE_FILTER_OPT = cli_option("-F", "--filter", dest="force_filter",
1396 442587bf Michael Hanselmann
                              action="store_true", default=False,
1397 442587bf Michael Hanselmann
                              help=("Whether command argument should be treated"
1398 442587bf Michael Hanselmann
                                    " as filter"))
1399 442587bf Michael Hanselmann
1400 885a0fc4 Iustin Pop
NO_REMEMBER_OPT = cli_option("--no-remember",
1401 885a0fc4 Iustin Pop
                             dest="no_remember",
1402 885a0fc4 Iustin Pop
                             action="store_true", default=False,
1403 885a0fc4 Iustin Pop
                             help="Perform but do not record the change"
1404 885a0fc4 Iustin Pop
                             " in the configuration")
1405 885a0fc4 Iustin Pop
1406 aafee533 Michael Hanselmann
PRIMARY_ONLY_OPT = cli_option("-p", "--primary-only",
1407 aafee533 Michael Hanselmann
                              default=False, action="store_true",
1408 aafee533 Michael Hanselmann
                              help="Evacuate primary instances only")
1409 aafee533 Michael Hanselmann
1410 aafee533 Michael Hanselmann
SECONDARY_ONLY_OPT = cli_option("-s", "--secondary-only",
1411 aafee533 Michael Hanselmann
                                default=False, action="store_true",
1412 aafee533 Michael Hanselmann
                                help="Evacuate secondary instances only"
1413 aafee533 Michael Hanselmann
                                     " (applies only to internally mirrored"
1414 aafee533 Michael Hanselmann
                                     " disk templates, e.g. %s)" %
1415 aafee533 Michael Hanselmann
                                     utils.CommaJoin(constants.DTS_INT_MIRROR))
1416 aafee533 Michael Hanselmann
1417 323f9095 Stephen Shirley
STARTUP_PAUSED_OPT = cli_option("--paused", dest="startup_paused",
1418 323f9095 Stephen Shirley
                                action="store_true", default=False,
1419 323f9095 Stephen Shirley
                                help="Pause instance at startup")
1420 323f9095 Stephen Shirley
1421 f6eb380d Michael Hanselmann
TO_GROUP_OPT = cli_option("--to", dest="to", metavar="<group>",
1422 f6eb380d Michael Hanselmann
                          help="Destination node group (name or uuid)",
1423 f6eb380d Michael Hanselmann
                          default=None, action="append",
1424 f6eb380d Michael Hanselmann
                          completion_suggest=OPT_COMPL_ONE_NODEGROUP)
1425 f6eb380d Michael Hanselmann
1426 93f2399e Andrea Spadaccini
IGNORE_ERRORS_OPT = cli_option("-I", "--ignore-errors", default=[],
1427 93f2399e Andrea Spadaccini
                               action="append", dest="ignore_errors",
1428 93f2399e Andrea Spadaccini
                               choices=list(constants.CV_ALL_ECODES_STRINGS),
1429 93f2399e Andrea Spadaccini
                               help="Error code to be ignored")
1430 93f2399e Andrea Spadaccini
1431 38f29a36 René Nussbaumer
DISK_STATE_OPT = cli_option("--disk-state", default=[], dest="disk_state",
1432 38f29a36 René Nussbaumer
                            action="append",
1433 a1cef552 Iustin Pop
                            help=("Specify disk state information in the"
1434 a1cef552 Iustin Pop
                                  " format"
1435 a1cef552 Iustin Pop
                                  " storage_type/identifier:option=value,...;"
1436 a1cef552 Iustin Pop
                                  " note this is unused for now"),
1437 38f29a36 René Nussbaumer
                            type="identkeyval")
1438 38f29a36 René Nussbaumer
1439 38f29a36 René Nussbaumer
HV_STATE_OPT = cli_option("--hypervisor-state", default=[], dest="hv_state",
1440 38f29a36 René Nussbaumer
                          action="append",
1441 38f29a36 René Nussbaumer
                          help=("Specify hypervisor state information in the"
1442 a1cef552 Iustin Pop
                                " format hypervisor:option=value,...;"
1443 a1cef552 Iustin Pop
                                " note this is unused for now"),
1444 38f29a36 René Nussbaumer
                          type="identkeyval")
1445 38f29a36 René Nussbaumer
1446 b6aaf437 René Nussbaumer
IGNORE_IPOLICY_OPT = cli_option("--ignore-ipolicy", dest="ignore_ipolicy",
1447 b6aaf437 René Nussbaumer
                                action="store_true", default=False,
1448 b6aaf437 René Nussbaumer
                                help="Ignore instance policy violations")
1449 b6aaf437 René Nussbaumer
1450 2c0af7da Guido Trotter
RUNTIME_MEM_OPT = cli_option("-m", "--runtime-memory", dest="runtime_mem",
1451 2c0af7da Guido Trotter
                             help="Sets the instance's runtime memory,"
1452 2c0af7da Guido Trotter
                             " ballooning it up or down to the new value",
1453 2c0af7da Guido Trotter
                             default=None, type="unit", metavar="<size>")
1454 61a14bb3 Iustin Pop
1455 ef8270dc Iustin Pop
ABSOLUTE_OPT = cli_option("--absolute", dest="absolute",
1456 ef8270dc Iustin Pop
                          action="store_true", default=False,
1457 ef8270dc Iustin Pop
                          help="Marks the grow as absolute instead of the"
1458 ef8270dc Iustin Pop
                          " (default) relative mode")
1459 ef8270dc Iustin Pop
1460 5786c087 Michael Hanselmann
#: Options provided by all commands
1461 5786c087 Michael Hanselmann
COMMON_OPTS = [DEBUG_OPT]
1462 5786c087 Michael Hanselmann
1463 eb28ecf6 Guido Trotter
# common options for creating instances. add and import then add their own
1464 eb28ecf6 Guido Trotter
# specific ones.
1465 eb28ecf6 Guido Trotter
COMMON_CREATE_OPTS = [
1466 eb28ecf6 Guido Trotter
  BACKEND_OPT,
1467 eb28ecf6 Guido Trotter
  DISK_OPT,
1468 eb28ecf6 Guido Trotter
  DISK_TEMPLATE_OPT,
1469 eb28ecf6 Guido Trotter
  FILESTORE_DIR_OPT,
1470 eb28ecf6 Guido Trotter
  FILESTORE_DRIVER_OPT,
1471 eb28ecf6 Guido Trotter
  HYPERVISOR_OPT,
1472 eb28ecf6 Guido Trotter
  IALLOCATOR_OPT,
1473 eb28ecf6 Guido Trotter
  NET_OPT,
1474 eb28ecf6 Guido Trotter
  NODE_PLACEMENT_OPT,
1475 eb28ecf6 Guido Trotter
  NOIPCHECK_OPT,
1476 eb28ecf6 Guido Trotter
  NONAMECHECK_OPT,
1477 eb28ecf6 Guido Trotter
  NONICS_OPT,
1478 eb28ecf6 Guido Trotter
  NWSYNC_OPT,
1479 eb28ecf6 Guido Trotter
  OSPARAMS_OPT,
1480 eb28ecf6 Guido Trotter
  OS_SIZE_OPT,
1481 eb28ecf6 Guido Trotter
  SUBMIT_OPT,
1482 0f8810df Michael Hanselmann
  TAG_ADD_OPT,
1483 eb28ecf6 Guido Trotter
  DRY_RUN_OPT,
1484 eb28ecf6 Guido Trotter
  PRIORITY_OPT,
1485 eb28ecf6 Guido Trotter
  ]
1486 eb28ecf6 Guido Trotter
1487 0ce212e5 Iustin Pop
# common instance policy options
1488 0ce212e5 Iustin Pop
INSTANCE_POLICY_OPTS = [
1489 0ce212e5 Iustin Pop
  SPECS_CPU_COUNT_OPT,
1490 0ce212e5 Iustin Pop
  SPECS_DISK_COUNT_OPT,
1491 0ce212e5 Iustin Pop
  SPECS_DISK_SIZE_OPT,
1492 0ce212e5 Iustin Pop
  SPECS_MEM_SIZE_OPT,
1493 0ce212e5 Iustin Pop
  SPECS_NIC_COUNT_OPT,
1494 d04c9d45 Iustin Pop
  IPOLICY_DISK_TEMPLATES,
1495 976b78ba Iustin Pop
  IPOLICY_VCPU_RATIO,
1496 ad5cc6bd René Nussbaumer
  IPOLICY_SPINDLE_RATIO,
1497 0ce212e5 Iustin Pop
  ]
1498 0ce212e5 Iustin Pop
1499 771734c9 Iustin Pop
1500 d971402f Michael Hanselmann
class _ShowUsage(Exception):
1501 d971402f Michael Hanselmann
  """Exception class for L{_ParseArgs}.
1502 d971402f Michael Hanselmann

1503 d971402f Michael Hanselmann
  """
1504 d971402f Michael Hanselmann
  def __init__(self, exit_error):
1505 d971402f Michael Hanselmann
    """Initializes instances of this class.
1506 d971402f Michael Hanselmann

1507 d971402f Michael Hanselmann
    @type exit_error: bool
1508 d971402f Michael Hanselmann
    @param exit_error: Whether to report failure on exit
1509 d971402f Michael Hanselmann

1510 d971402f Michael Hanselmann
    """
1511 d971402f Michael Hanselmann
    Exception.__init__(self)
1512 d971402f Michael Hanselmann
    self.exit_error = exit_error
1513 d971402f Michael Hanselmann
1514 d971402f Michael Hanselmann
1515 d971402f Michael Hanselmann
class _ShowVersion(Exception):
1516 d971402f Michael Hanselmann
  """Exception class for L{_ParseArgs}.
1517 d971402f Michael Hanselmann

1518 d971402f Michael Hanselmann
  """
1519 d971402f Michael Hanselmann
1520 d971402f Michael Hanselmann
1521 d971402f Michael Hanselmann
def _ParseArgs(binary, argv, commands, aliases, env_override):
1522 c41eea6e Iustin Pop
  """Parser for the command line arguments.
1523 a8083063 Iustin Pop

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

1527 d971402f Michael Hanselmann
  @param binary: Script name
1528 d971402f Michael Hanselmann
  @param argv: Command line arguments
1529 d971402f Michael Hanselmann
  @param commands: Dictionary containing command definitions
1530 d971402f Michael Hanselmann
  @param aliases: dictionary with command aliases {"alias": "target", ...}
1531 ef9fa5b9 René Nussbaumer
  @param env_override: list of env variables allowed for default args
1532 d971402f Michael Hanselmann
  @raise _ShowUsage: If usage description should be shown
1533 d971402f Michael Hanselmann
  @raise _ShowVersion: If version should be shown
1534 098c0958 Michael Hanselmann

1535 a8083063 Iustin Pop
  """
1536 ef9fa5b9 René Nussbaumer
  assert not (env_override - set(commands))
1537 d971402f Michael Hanselmann
  assert not (set(aliases.keys()) & set(commands.keys()))
1538 ef9fa5b9 René Nussbaumer
1539 d971402f Michael Hanselmann
  if len(argv) > 1:
1540 d971402f Michael Hanselmann
    cmd = argv[1]
1541 a8083063 Iustin Pop
  else:
1542 d971402f Michael Hanselmann
    # No option or command given
1543 d971402f Michael Hanselmann
    raise _ShowUsage(exit_error=True)
1544 a8083063 Iustin Pop
1545 d971402f Michael Hanselmann
  if cmd == "--version":
1546 d971402f Michael Hanselmann
    raise _ShowVersion()
1547 d971402f Michael Hanselmann
  elif cmd == "--help":
1548 d971402f Michael Hanselmann
    raise _ShowUsage(exit_error=False)
1549 d971402f Michael Hanselmann
  elif not (cmd in commands or cmd in aliases):
1550 d971402f Michael Hanselmann
    raise _ShowUsage(exit_error=True)
1551 de47cf8f Guido Trotter
1552 de47cf8f Guido Trotter
  # get command, unalias it, and look it up in commands
1553 de47cf8f Guido Trotter
  if cmd in aliases:
1554 de47cf8f Guido Trotter
    if aliases[cmd] not in commands:
1555 de47cf8f Guido Trotter
      raise errors.ProgrammerError("Alias '%s' maps to non-existing"
1556 de47cf8f Guido Trotter
                                   " command '%s'" % (cmd, aliases[cmd]))
1557 de47cf8f Guido Trotter
1558 de47cf8f Guido Trotter
    cmd = aliases[cmd]
1559 de47cf8f Guido Trotter
1560 ef9fa5b9 René Nussbaumer
  if cmd in env_override:
1561 ef9fa5b9 René Nussbaumer
    args_env_name = ("%s_%s" % (binary.replace("-", "_"), cmd)).upper()
1562 ef9fa5b9 René Nussbaumer
    env_args = os.environ.get(args_env_name)
1563 ef9fa5b9 René Nussbaumer
    if env_args:
1564 d971402f Michael Hanselmann
      argv = utils.InsertAtPos(argv, 2, shlex.split(env_args))
1565 ef9fa5b9 René Nussbaumer
1566 a8005e17 Michael Hanselmann
  func, args_def, parser_opts, usage, description = commands[cmd]
1567 bf5338b3 Michael Hanselmann
  parser = OptionParser(option_list=parser_opts + COMMON_OPTS,
1568 bf5338b3 Michael Hanselmann
                        description=description,
1569 bf5338b3 Michael Hanselmann
                        formatter=TitledHelpFormatter(),
1570 bf5338b3 Michael Hanselmann
                        usage="%%prog %s %s" % (cmd, usage))
1571 a8083063 Iustin Pop
  parser.disable_interspersed_args()
1572 d971402f Michael Hanselmann
  options, args = parser.parse_args(args=argv[2:])
1573 a8005e17 Michael Hanselmann
1574 a8005e17 Michael Hanselmann
  if not _CheckArguments(cmd, args_def, args):
1575 a8083063 Iustin Pop
    return None, None, None
1576 a8083063 Iustin Pop
1577 a8083063 Iustin Pop
  return func, options, args
1578 a8083063 Iustin Pop
1579 a8083063 Iustin Pop
1580 d971402f Michael Hanselmann
def _FormatUsage(binary, commands):
1581 d971402f Michael Hanselmann
  """Generates a nice description of all commands.
1582 d971402f Michael Hanselmann

1583 d971402f Michael Hanselmann
  @param binary: Script name
1584 d971402f Michael Hanselmann
  @param commands: Dictionary containing command definitions
1585 d971402f Michael Hanselmann

1586 d971402f Michael Hanselmann
  """
1587 d971402f Michael Hanselmann
  # compute the max line length for cmd + usage
1588 d971402f Michael Hanselmann
  mlen = min(60, max(map(len, commands)))
1589 d971402f Michael Hanselmann
1590 d971402f Michael Hanselmann
  yield "Usage: %s {command} [options...] [argument...]" % binary
1591 d971402f Michael Hanselmann
  yield "%s <command> --help to see details, or man %s" % (binary, binary)
1592 d971402f Michael Hanselmann
  yield ""
1593 d971402f Michael Hanselmann
  yield "Commands:"
1594 d971402f Michael Hanselmann
1595 d971402f Michael Hanselmann
  # and format a nice command list
1596 d971402f Michael Hanselmann
  for (cmd, (_, _, _, _, help_text)) in sorted(commands.items()):
1597 d971402f Michael Hanselmann
    help_lines = textwrap.wrap(help_text, 79 - 3 - mlen)
1598 d971402f Michael Hanselmann
    yield " %-*s - %s" % (mlen, cmd, help_lines.pop(0))
1599 d971402f Michael Hanselmann
    for line in help_lines:
1600 d971402f Michael Hanselmann
      yield " %-*s   %s" % (mlen, "", line)
1601 d971402f Michael Hanselmann
1602 d971402f Michael Hanselmann
  yield ""
1603 d971402f Michael Hanselmann
1604 d971402f Michael Hanselmann
1605 a8005e17 Michael Hanselmann
def _CheckArguments(cmd, args_def, args):
1606 a8005e17 Michael Hanselmann
  """Verifies the arguments using the argument definition.
1607 a8005e17 Michael Hanselmann

1608 a8005e17 Michael Hanselmann
  Algorithm:
1609 a8005e17 Michael Hanselmann

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

1612 a8005e17 Michael Hanselmann
    1. For each argument in definition
1613 a8005e17 Michael Hanselmann

1614 a8005e17 Michael Hanselmann
      1. Keep running count of minimum number of values (min_count)
1615 a8005e17 Michael Hanselmann
      1. Keep running count of maximum number of values (max_count)
1616 a8005e17 Michael Hanselmann
      1. If it has an unlimited number of values
1617 a8005e17 Michael Hanselmann

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

1620 a8005e17 Michael Hanselmann
    1. If last argument has limited number of values
1621 a8005e17 Michael Hanselmann

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

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

1626 a8005e17 Michael Hanselmann
  """
1627 a8005e17 Michael Hanselmann
  if args and not args_def:
1628 a8005e17 Michael Hanselmann
    ToStderr("Error: Command %s expects no arguments", cmd)
1629 a8005e17 Michael Hanselmann
    return False
1630 a8005e17 Michael Hanselmann
1631 a8005e17 Michael Hanselmann
  min_count = None
1632 a8005e17 Michael Hanselmann
  max_count = None
1633 a8005e17 Michael Hanselmann
  check_max = None
1634 a8005e17 Michael Hanselmann
1635 a8005e17 Michael Hanselmann
  last_idx = len(args_def) - 1
1636 a8005e17 Michael Hanselmann
1637 a8005e17 Michael Hanselmann
  for idx, arg in enumerate(args_def):
1638 a8005e17 Michael Hanselmann
    if min_count is None:
1639 a8005e17 Michael Hanselmann
      min_count = arg.min
1640 a8005e17 Michael Hanselmann
    elif arg.min is not None:
1641 a8005e17 Michael Hanselmann
      min_count += arg.min
1642 a8005e17 Michael Hanselmann
1643 a8005e17 Michael Hanselmann
    if max_count is None:
1644 a8005e17 Michael Hanselmann
      max_count = arg.max
1645 a8005e17 Michael Hanselmann
    elif arg.max is not None:
1646 a8005e17 Michael Hanselmann
      max_count += arg.max
1647 a8005e17 Michael Hanselmann
1648 a8005e17 Michael Hanselmann
    if idx == last_idx:
1649 a8005e17 Michael Hanselmann
      check_max = (arg.max is not None)
1650 a8005e17 Michael Hanselmann
1651 a8005e17 Michael Hanselmann
    elif arg.max is None:
1652 a8005e17 Michael Hanselmann
      raise errors.ProgrammerError("Only the last argument can have max=None")
1653 a8005e17 Michael Hanselmann
1654 a8005e17 Michael Hanselmann
  if check_max:
1655 a8005e17 Michael Hanselmann
    # Command with exact number of arguments
1656 a8005e17 Michael Hanselmann
    if (min_count is not None and max_count is not None and
1657 a8005e17 Michael Hanselmann
        min_count == max_count and len(args) != min_count):
1658 a8005e17 Michael Hanselmann
      ToStderr("Error: Command %s expects %d argument(s)", cmd, min_count)
1659 a8005e17 Michael Hanselmann
      return False
1660 a8005e17 Michael Hanselmann
1661 a8005e17 Michael Hanselmann
    # Command with limited number of arguments
1662 a8005e17 Michael Hanselmann
    if max_count is not None and len(args) > max_count:
1663 a8005e17 Michael Hanselmann
      ToStderr("Error: Command %s expects only %d argument(s)",
1664 a8005e17 Michael Hanselmann
               cmd, max_count)
1665 a8005e17 Michael Hanselmann
      return False
1666 a8005e17 Michael Hanselmann
1667 a8005e17 Michael Hanselmann
  # Command with some required arguments
1668 a8005e17 Michael Hanselmann
  if min_count is not None and len(args) < min_count:
1669 a8005e17 Michael Hanselmann
    ToStderr("Error: Command %s expects at least %d argument(s)",
1670 a8005e17 Michael Hanselmann
             cmd, min_count)
1671 a8005e17 Michael Hanselmann
    return False
1672 a8005e17 Michael Hanselmann
1673 a8005e17 Michael Hanselmann
  return True
1674 a8005e17 Michael Hanselmann
1675 a8005e17 Michael Hanselmann
1676 60d49723 Michael Hanselmann
def SplitNodeOption(value):
1677 60d49723 Michael Hanselmann
  """Splits the value of a --node option.
1678 60d49723 Michael Hanselmann

1679 60d49723 Michael Hanselmann
  """
1680 d0c8c01d Iustin Pop
  if value and ":" in value:
1681 d0c8c01d Iustin Pop
    return value.split(":", 1)
1682 60d49723 Michael Hanselmann
  else:
1683 60d49723 Michael Hanselmann
    return (value, None)
1684 60d49723 Michael Hanselmann
1685 60d49723 Michael Hanselmann
1686 07150497 Guido Trotter
def CalculateOSNames(os_name, os_variants):
1687 07150497 Guido Trotter
  """Calculates all the names an OS can be called, according to its variants.
1688 07150497 Guido Trotter

1689 07150497 Guido Trotter
  @type os_name: string
1690 07150497 Guido Trotter
  @param os_name: base name of the os
1691 07150497 Guido Trotter
  @type os_variants: list or None
1692 07150497 Guido Trotter
  @param os_variants: list of supported variants
1693 07150497 Guido Trotter
  @rtype: list
1694 07150497 Guido Trotter
  @return: list of valid names
1695 07150497 Guido Trotter

1696 07150497 Guido Trotter
  """
1697 07150497 Guido Trotter
  if os_variants:
1698 d0c8c01d Iustin Pop
    return ["%s+%s" % (os_name, v) for v in os_variants]
1699 07150497 Guido Trotter
  else:
1700 07150497 Guido Trotter
    return [os_name]
1701 07150497 Guido Trotter
1702 07150497 Guido Trotter
1703 a4ebd726 Michael Hanselmann
def ParseFields(selected, default):
1704 a4ebd726 Michael Hanselmann
  """Parses the values of "--field"-like options.
1705 a4ebd726 Michael Hanselmann

1706 a4ebd726 Michael Hanselmann
  @type selected: string or None
1707 a4ebd726 Michael Hanselmann
  @param selected: User-selected options
1708 a4ebd726 Michael Hanselmann
  @type default: list
1709 a4ebd726 Michael Hanselmann
  @param default: Default fields
1710 a4ebd726 Michael Hanselmann

1711 a4ebd726 Michael Hanselmann
  """
1712 a4ebd726 Michael Hanselmann
  if selected is None:
1713 a4ebd726 Michael Hanselmann
    return default
1714 a4ebd726 Michael Hanselmann
1715 a4ebd726 Michael Hanselmann
  if selected.startswith("+"):
1716 a4ebd726 Michael Hanselmann
    return default + selected[1:].split(",")
1717 a4ebd726 Michael Hanselmann
1718 a4ebd726 Michael Hanselmann
  return selected.split(",")
1719 a4ebd726 Michael Hanselmann
1720 a4ebd726 Michael Hanselmann
1721 e0e916fe Iustin Pop
UsesRPC = rpc.RunWithRPC
1722 4331f6cd Michael Hanselmann
1723 4331f6cd Michael Hanselmann
1724 47988778 Iustin Pop
def AskUser(text, choices=None):
1725 47988778 Iustin Pop
  """Ask the user a question.
1726 a8083063 Iustin Pop

1727 c41eea6e Iustin Pop
  @param text: the question to ask
1728 a8083063 Iustin Pop

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

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

1738 a8083063 Iustin Pop
  """
1739 47988778 Iustin Pop
  if choices is None:
1740 d0c8c01d Iustin Pop
    choices = [("y", True, "Perform the operation"),
1741 d0c8c01d Iustin Pop
               ("n", False, "Do not perform the operation")]
1742 47988778 Iustin Pop
  if not choices or not isinstance(choices, list):
1743 5bbd3f7f Michael Hanselmann
    raise errors.ProgrammerError("Invalid choices argument to AskUser")
1744 47988778 Iustin Pop
  for entry in choices:
1745 d0c8c01d Iustin Pop
    if not isinstance(entry, tuple) or len(entry) < 3 or entry[0] == "?":
1746 5bbd3f7f Michael Hanselmann
      raise errors.ProgrammerError("Invalid choices element to AskUser")
1747 47988778 Iustin Pop
1748 47988778 Iustin Pop
  answer = choices[-1][1]
1749 47988778 Iustin Pop
  new_text = []
1750 47988778 Iustin Pop
  for line in text.splitlines():
1751 47988778 Iustin Pop
    new_text.append(textwrap.fill(line, 70, replace_whitespace=False))
1752 47988778 Iustin Pop
  text = "\n".join(new_text)
1753 a8083063 Iustin Pop
  try:
1754 3023170f Iustin Pop
    f = file("/dev/tty", "a+")
1755 a8083063 Iustin Pop
  except IOError:
1756 47988778 Iustin Pop
    return answer
1757 a8083063 Iustin Pop
  try:
1758 47988778 Iustin Pop
    chars = [entry[0] for entry in choices]
1759 47988778 Iustin Pop
    chars[-1] = "[%s]" % chars[-1]
1760 d0c8c01d Iustin Pop
    chars.append("?")
1761 47988778 Iustin Pop
    maps = dict([(entry[0], entry[1]) for entry in choices])
1762 47988778 Iustin Pop
    while True:
1763 47988778 Iustin Pop
      f.write(text)
1764 d0c8c01d Iustin Pop
      f.write("\n")
1765 47988778 Iustin Pop
      f.write("/".join(chars))
1766 47988778 Iustin Pop
      f.write(": ")
1767 47988778 Iustin Pop
      line = f.readline(2).strip().lower()
1768 47988778 Iustin Pop
      if line in maps:
1769 47988778 Iustin Pop
        answer = maps[line]
1770 47988778 Iustin Pop
        break
1771 d0c8c01d Iustin Pop
      elif line == "?":
1772 47988778 Iustin Pop
        for entry in choices:
1773 47988778 Iustin Pop
          f.write(" %s - %s\n" % (entry[0], entry[2]))
1774 47988778 Iustin Pop
        f.write("\n")
1775 47988778 Iustin Pop
        continue
1776 a8083063 Iustin Pop
  finally:
1777 a8083063 Iustin Pop
    f.close()
1778 a8083063 Iustin Pop
  return answer
1779 a8083063 Iustin Pop
1780 a8083063 Iustin Pop
1781 e9d741b6 Iustin Pop
class JobSubmittedException(Exception):
1782 e9d741b6 Iustin Pop
  """Job was submitted, client should exit.
1783 e9d741b6 Iustin Pop

1784 e9d741b6 Iustin Pop
  This exception has one argument, the ID of the job that was
1785 e9d741b6 Iustin Pop
  submitted. The handler should print this ID.
1786 e9d741b6 Iustin Pop

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

1789 e9d741b6 Iustin Pop
  """
1790 e9d741b6 Iustin Pop
1791 e9d741b6 Iustin Pop
1792 0a1e74d9 Iustin Pop
def SendJob(ops, cl=None):
1793 0a1e74d9 Iustin Pop
  """Function to submit an opcode without waiting for the results.
1794 a8083063 Iustin Pop

1795 0a1e74d9 Iustin Pop
  @type ops: list
1796 0a1e74d9 Iustin Pop
  @param ops: list of opcodes
1797 0a1e74d9 Iustin Pop
  @type cl: luxi.Client
1798 0a1e74d9 Iustin Pop
  @param cl: the luxi client to use for communicating with the master;
1799 0a1e74d9 Iustin Pop
             if None, a new client will be created
1800 a8083063 Iustin Pop

1801 a8083063 Iustin Pop
  """
1802 e2212007 Iustin Pop
  if cl is None:
1803 b33e986b Iustin Pop
    cl = GetClient()
1804 685ee993 Iustin Pop
1805 0a1e74d9 Iustin Pop
  job_id = cl.SubmitJob(ops)
1806 0a1e74d9 Iustin Pop
1807 0a1e74d9 Iustin Pop
  return job_id
1808 0a1e74d9 Iustin Pop
1809 0a1e74d9 Iustin Pop
1810 4e338533 Michael Hanselmann
def GenericPollJob(job_id, cbs, report_cbs):
1811 4e338533 Michael Hanselmann
  """Generic job-polling function.
1812 0a1e74d9 Iustin Pop

1813 4e338533 Michael Hanselmann
  @type job_id: number
1814 4e338533 Michael Hanselmann
  @param job_id: Job ID
1815 4e338533 Michael Hanselmann
  @type cbs: Instance of L{JobPollCbBase}
1816 4e338533 Michael Hanselmann
  @param cbs: Data callbacks
1817 4e338533 Michael Hanselmann
  @type report_cbs: Instance of L{JobPollReportCbBase}
1818 4e338533 Michael Hanselmann
  @param report_cbs: Reporting callbacks
1819 0a1e74d9 Iustin Pop

1820 0a1e74d9 Iustin Pop
  """
1821 6c5a7090 Michael Hanselmann
  prev_job_info = None
1822 6c5a7090 Michael Hanselmann
  prev_logmsg_serial = None
1823 6c5a7090 Michael Hanselmann
1824 f4484122 Michael Hanselmann
  status = None
1825 f4484122 Michael Hanselmann
1826 685ee993 Iustin Pop
  while True:
1827 4e338533 Michael Hanselmann
    result = cbs.WaitForJobChangeOnce(job_id, ["status"], prev_job_info,
1828 4e338533 Michael Hanselmann
                                      prev_logmsg_serial)
1829 6c5a7090 Michael Hanselmann
    if not result:
1830 685ee993 Iustin Pop
      # job not found, go away!
1831 0bbe448c Michael Hanselmann
      raise errors.JobLost("Job with id %s lost" % job_id)
1832 4e338533 Michael Hanselmann
1833 4e338533 Michael Hanselmann
    if result == constants.JOB_NOTCHANGED:
1834 4e338533 Michael Hanselmann
      report_cbs.ReportNotChanged(job_id, status)
1835 f4484122 Michael Hanselmann
1836 f4484122 Michael Hanselmann
      # Wait again
1837 f4484122 Michael Hanselmann
      continue
1838 685ee993 Iustin Pop
1839 6c5a7090 Michael Hanselmann
    # Split result, a tuple of (field values, log entries)
1840 6c5a7090 Michael Hanselmann
    (job_info, log_entries) = result
1841 6c5a7090 Michael Hanselmann
    (status, ) = job_info
1842 6c5a7090 Michael Hanselmann
1843 6c5a7090 Michael Hanselmann
    if log_entries:
1844 6c5a7090 Michael Hanselmann
      for log_entry in log_entries:
1845 4e338533 Michael Hanselmann
        (serial, timestamp, log_type, message) = log_entry
1846 4e338533 Michael Hanselmann
        report_cbs.ReportLogMessage(job_id, serial, timestamp,
1847 4e338533 Michael Hanselmann
                                    log_type, message)
1848 6c5a7090 Michael Hanselmann
        prev_logmsg_serial = max(prev_logmsg_serial, serial)
1849 6c5a7090 Michael Hanselmann
1850 0bbe448c Michael Hanselmann
    # TODO: Handle canceled and archived jobs
1851 fbf0262f Michael Hanselmann
    elif status in (constants.JOB_STATUS_SUCCESS,
1852 fbf0262f Michael Hanselmann
                    constants.JOB_STATUS_ERROR,
1853 fbf0262f Michael Hanselmann
                    constants.JOB_STATUS_CANCELING,
1854 fbf0262f Michael Hanselmann
                    constants.JOB_STATUS_CANCELED):
1855 685ee993 Iustin Pop
      break
1856 6c5a7090 Michael Hanselmann
1857 6c5a7090 Michael Hanselmann
    prev_job_info = job_info
1858 685ee993 Iustin Pop
1859 4e338533 Michael Hanselmann
  jobs = cbs.QueryJobs([job_id], ["status", "opstatus", "opresult"])
1860 0bbe448c Michael Hanselmann
  if not jobs:
1861 0bbe448c Michael Hanselmann
    raise errors.JobLost("Job with id %s lost" % job_id)
1862 685ee993 Iustin Pop
1863 0e050889 Iustin Pop
  status, opstatus, result = jobs[0]
1864 4e338533 Michael Hanselmann
1865 0bbe448c Michael Hanselmann
  if status == constants.JOB_STATUS_SUCCESS:
1866 53c04d04 Iustin Pop
    return result
1867 4e338533 Michael Hanselmann
1868 4e338533 Michael Hanselmann
  if status in (constants.JOB_STATUS_CANCELING, constants.JOB_STATUS_CANCELED):
1869 fbf0262f Michael Hanselmann
    raise errors.OpExecError("Job was canceled")
1870 4e338533 Michael Hanselmann
1871 4e338533 Michael Hanselmann
  has_ok = False
1872 4e338533 Michael Hanselmann
  for idx, (status, msg) in enumerate(zip(opstatus, result)):
1873 4e338533 Michael Hanselmann
    if status == constants.OP_STATUS_SUCCESS:
1874 4e338533 Michael Hanselmann
      has_ok = True
1875 4e338533 Michael Hanselmann
    elif status == constants.OP_STATUS_ERROR:
1876 4e338533 Michael Hanselmann
      errors.MaybeRaise(msg)
1877 4e338533 Michael Hanselmann
1878 4e338533 Michael Hanselmann
      if has_ok:
1879 4e338533 Michael Hanselmann
        raise errors.OpExecError("partial failure (opcode %d): %s" %
1880 4e338533 Michael Hanselmann
                                 (idx, msg))
1881 4e338533 Michael Hanselmann
1882 4e338533 Michael Hanselmann
      raise errors.OpExecError(str(msg))
1883 4e338533 Michael Hanselmann
1884 4e338533 Michael Hanselmann
  # default failure mode
1885 4e338533 Michael Hanselmann
  raise errors.OpExecError(result)
1886 4e338533 Michael Hanselmann
1887 4e338533 Michael Hanselmann
1888 4e338533 Michael Hanselmann
class JobPollCbBase:
1889 4e338533 Michael Hanselmann
  """Base class for L{GenericPollJob} callbacks.
1890 4e338533 Michael Hanselmann

1891 4e338533 Michael Hanselmann
  """
1892 4e338533 Michael Hanselmann
  def __init__(self):
1893 4e338533 Michael Hanselmann
    """Initializes this class.
1894 4e338533 Michael Hanselmann

1895 4e338533 Michael Hanselmann
    """
1896 4e338533 Michael Hanselmann
1897 4e338533 Michael Hanselmann
  def WaitForJobChangeOnce(self, job_id, fields,
1898 4e338533 Michael Hanselmann
                           prev_job_info, prev_log_serial):
1899 4e338533 Michael Hanselmann
    """Waits for changes on a job.
1900 4e338533 Michael Hanselmann

1901 4e338533 Michael Hanselmann
    """
1902 4e338533 Michael Hanselmann
    raise NotImplementedError()
1903 4e338533 Michael Hanselmann
1904 4e338533 Michael Hanselmann
  def QueryJobs(self, job_ids, fields):
1905 4e338533 Michael Hanselmann
    """Returns the selected fields for the selected job IDs.
1906 4e338533 Michael Hanselmann

1907 4e338533 Michael Hanselmann
    @type job_ids: list of numbers
1908 4e338533 Michael Hanselmann
    @param job_ids: Job IDs
1909 4e338533 Michael Hanselmann
    @type fields: list of strings
1910 4e338533 Michael Hanselmann
    @param fields: Fields
1911 4e338533 Michael Hanselmann

1912 4e338533 Michael Hanselmann
    """
1913 4e338533 Michael Hanselmann
    raise NotImplementedError()
1914 4e338533 Michael Hanselmann
1915 4e338533 Michael Hanselmann
1916 4e338533 Michael Hanselmann
class JobPollReportCbBase:
1917 4e338533 Michael Hanselmann
  """Base class for L{GenericPollJob} reporting callbacks.
1918 4e338533 Michael Hanselmann

1919 4e338533 Michael Hanselmann
  """
1920 4e338533 Michael Hanselmann
  def __init__(self):
1921 4e338533 Michael Hanselmann
    """Initializes this class.
1922 4e338533 Michael Hanselmann

1923 4e338533 Michael Hanselmann
    """
1924 4e338533 Michael Hanselmann
1925 4e338533 Michael Hanselmann
  def ReportLogMessage(self, job_id, serial, timestamp, log_type, log_msg):
1926 4e338533 Michael Hanselmann
    """Handles a log message.
1927 4e338533 Michael Hanselmann

1928 4e338533 Michael Hanselmann
    """
1929 4e338533 Michael Hanselmann
    raise NotImplementedError()
1930 4e338533 Michael Hanselmann
1931 4e338533 Michael Hanselmann
  def ReportNotChanged(self, job_id, status):
1932 4e338533 Michael Hanselmann
    """Called for if a job hasn't changed in a while.
1933 4e338533 Michael Hanselmann

1934 4e338533 Michael Hanselmann
    @type job_id: number
1935 4e338533 Michael Hanselmann
    @param job_id: Job ID
1936 4e338533 Michael Hanselmann
    @type status: string or None
1937 4e338533 Michael Hanselmann
    @param status: Job status if available
1938 4e338533 Michael Hanselmann

1939 4e338533 Michael Hanselmann
    """
1940 4e338533 Michael Hanselmann
    raise NotImplementedError()
1941 4e338533 Michael Hanselmann
1942 4e338533 Michael Hanselmann
1943 4e338533 Michael Hanselmann
class _LuxiJobPollCb(JobPollCbBase):
1944 4e338533 Michael Hanselmann
  def __init__(self, cl):
1945 4e338533 Michael Hanselmann
    """Initializes this class.
1946 4e338533 Michael Hanselmann

1947 4e338533 Michael Hanselmann
    """
1948 4e338533 Michael Hanselmann
    JobPollCbBase.__init__(self)
1949 4e338533 Michael Hanselmann
    self.cl = cl
1950 4e338533 Michael Hanselmann
1951 4e338533 Michael Hanselmann
  def WaitForJobChangeOnce(self, job_id, fields,
1952 4e338533 Michael Hanselmann
                           prev_job_info, prev_log_serial):
1953 4e338533 Michael Hanselmann
    """Waits for changes on a job.
1954 4e338533 Michael Hanselmann

1955 4e338533 Michael Hanselmann
    """
1956 4e338533 Michael Hanselmann
    return self.cl.WaitForJobChangeOnce(job_id, fields,
1957 4e338533 Michael Hanselmann
                                        prev_job_info, prev_log_serial)
1958 4e338533 Michael Hanselmann
1959 4e338533 Michael Hanselmann
  def QueryJobs(self, job_ids, fields):
1960 4e338533 Michael Hanselmann
    """Returns the selected fields for the selected job IDs.
1961 4e338533 Michael Hanselmann

1962 4e338533 Michael Hanselmann
    """
1963 4e338533 Michael Hanselmann
    return self.cl.QueryJobs(job_ids, fields)
1964 4e338533 Michael Hanselmann
1965 4e338533 Michael Hanselmann
1966 4e338533 Michael Hanselmann
class FeedbackFnJobPollReportCb(JobPollReportCbBase):
1967 4e338533 Michael Hanselmann
  def __init__(self, feedback_fn):
1968 4e338533 Michael Hanselmann
    """Initializes this class.
1969 4e338533 Michael Hanselmann

1970 4e338533 Michael Hanselmann
    """
1971 4e338533 Michael Hanselmann
    JobPollReportCbBase.__init__(self)
1972 4e338533 Michael Hanselmann
1973 4e338533 Michael Hanselmann
    self.feedback_fn = feedback_fn
1974 4e338533 Michael Hanselmann
1975 4e338533 Michael Hanselmann
    assert callable(feedback_fn)
1976 4e338533 Michael Hanselmann
1977 4e338533 Michael Hanselmann
  def ReportLogMessage(self, job_id, serial, timestamp, log_type, log_msg):
1978 4e338533 Michael Hanselmann
    """Handles a log message.
1979 4e338533 Michael Hanselmann

1980 4e338533 Michael Hanselmann
    """
1981 4e338533 Michael Hanselmann
    self.feedback_fn((timestamp, log_type, log_msg))
1982 4e338533 Michael Hanselmann
1983 4e338533 Michael Hanselmann
  def ReportNotChanged(self, job_id, status):
1984 4e338533 Michael Hanselmann
    """Called if a job hasn't changed in a while.
1985 4e338533 Michael Hanselmann

1986 4e338533 Michael Hanselmann
    """
1987 4e338533 Michael Hanselmann
    # Ignore
1988 4e338533 Michael Hanselmann
1989 4e338533 Michael Hanselmann
1990 4e338533 Michael Hanselmann
class StdioJobPollReportCb(JobPollReportCbBase):
1991 4e338533 Michael Hanselmann
  def __init__(self):
1992 4e338533 Michael Hanselmann
    """Initializes this class.
1993 4e338533 Michael Hanselmann

1994 4e338533 Michael Hanselmann
    """
1995 4e338533 Michael Hanselmann
    JobPollReportCbBase.__init__(self)
1996 4e338533 Michael Hanselmann
1997 4e338533 Michael Hanselmann
    self.notified_queued = False
1998 4e338533 Michael Hanselmann
    self.notified_waitlock = False
1999 4e338533 Michael Hanselmann
2000 4e338533 Michael Hanselmann
  def ReportLogMessage(self, job_id, serial, timestamp, log_type, log_msg):
2001 4e338533 Michael Hanselmann
    """Handles a log message.
2002 4e338533 Michael Hanselmann

2003 4e338533 Michael Hanselmann
    """
2004 4e338533 Michael Hanselmann
    ToStdout("%s %s", time.ctime(utils.MergeTime(timestamp)),
2005 8a7f1c61 Michael Hanselmann
             FormatLogMessage(log_type, log_msg))
2006 4e338533 Michael Hanselmann
2007 4e338533 Michael Hanselmann
  def ReportNotChanged(self, job_id, status):
2008 4e338533 Michael Hanselmann
    """Called if a job hasn't changed in a while.
2009 4e338533 Michael Hanselmann

2010 4e338533 Michael Hanselmann
    """
2011 4e338533 Michael Hanselmann
    if status is None:
2012 4e338533 Michael Hanselmann
      return
2013 4e338533 Michael Hanselmann
2014 4e338533 Michael Hanselmann
    if status == constants.JOB_STATUS_QUEUED and not self.notified_queued:
2015 4e338533 Michael Hanselmann
      ToStderr("Job %s is waiting in queue", job_id)
2016 4e338533 Michael Hanselmann
      self.notified_queued = True
2017 4e338533 Michael Hanselmann
2018 47099cd1 Michael Hanselmann
    elif status == constants.JOB_STATUS_WAITING and not self.notified_waitlock:
2019 4e338533 Michael Hanselmann
      ToStderr("Job %s is trying to acquire all necessary locks", job_id)
2020 4e338533 Michael Hanselmann
      self.notified_waitlock = True
2021 4e338533 Michael Hanselmann
2022 4e338533 Michael Hanselmann
2023 8a7f1c61 Michael Hanselmann
def FormatLogMessage(log_type, log_msg):
2024 8a7f1c61 Michael Hanselmann
  """Formats a job message according to its type.
2025 8a7f1c61 Michael Hanselmann

2026 8a7f1c61 Michael Hanselmann
  """
2027 8a7f1c61 Michael Hanselmann
  if log_type != constants.ELOG_MESSAGE:
2028 8a7f1c61 Michael Hanselmann
    log_msg = str(log_msg)
2029 8a7f1c61 Michael Hanselmann
2030 8a7f1c61 Michael Hanselmann
  return utils.SafeEncode(log_msg)
2031 8a7f1c61 Michael Hanselmann
2032 8a7f1c61 Michael Hanselmann
2033 583163a6 Michael Hanselmann
def PollJob(job_id, cl=None, feedback_fn=None, reporter=None):
2034 4e338533 Michael Hanselmann
  """Function to poll for the result of a job.
2035 4e338533 Michael Hanselmann

2036 4e338533 Michael Hanselmann
  @type job_id: job identified
2037 4e338533 Michael Hanselmann
  @param job_id: the job to poll for results
2038 4e338533 Michael Hanselmann
  @type cl: luxi.Client
2039 4e338533 Michael Hanselmann
  @param cl: the luxi client to use for communicating with the master;
2040 4e338533 Michael Hanselmann
             if None, a new client will be created
2041 4e338533 Michael Hanselmann

2042 4e338533 Michael Hanselmann
  """
2043 4e338533 Michael Hanselmann
  if cl is None:
2044 4e338533 Michael Hanselmann
    cl = GetClient()
2045 4e338533 Michael Hanselmann
2046 583163a6 Michael Hanselmann
  if reporter is None:
2047 583163a6 Michael Hanselmann
    if feedback_fn:
2048 583163a6 Michael Hanselmann
      reporter = FeedbackFnJobPollReportCb(feedback_fn)
2049 583163a6 Michael Hanselmann
    else:
2050 583163a6 Michael Hanselmann
      reporter = StdioJobPollReportCb()
2051 583163a6 Michael Hanselmann
  elif feedback_fn:
2052 583163a6 Michael Hanselmann
    raise errors.ProgrammerError("Can't specify reporter and feedback function")
2053 4e338533 Michael Hanselmann
2054 4e338533 Michael Hanselmann
  return GenericPollJob(job_id, _LuxiJobPollCb(cl), reporter)
2055 ceab32dd Iustin Pop
2056 ceab32dd Iustin Pop
2057 583163a6 Michael Hanselmann
def SubmitOpCode(op, cl=None, feedback_fn=None, opts=None, reporter=None):
2058 0a1e74d9 Iustin Pop
  """Legacy function to submit an opcode.
2059 0a1e74d9 Iustin Pop

2060 0a1e74d9 Iustin Pop
  This is just a simple wrapper over the construction of the processor
2061 0a1e74d9 Iustin Pop
  instance. It should be extended to better handle feedback and
2062 0a1e74d9 Iustin Pop
  interaction functions.
2063 0a1e74d9 Iustin Pop

2064 0a1e74d9 Iustin Pop
  """
2065 0a1e74d9 Iustin Pop
  if cl is None:
2066 0a1e74d9 Iustin Pop
    cl = GetClient()
2067 0a1e74d9 Iustin Pop
2068 293ba2d8 Iustin Pop
  SetGenericOpcodeOpts([op], opts)
2069 293ba2d8 Iustin Pop
2070 5d297d8a Michael Hanselmann
  job_id = SendJob([op], cl=cl)
2071 0a1e74d9 Iustin Pop
2072 583163a6 Michael Hanselmann
  op_results = PollJob(job_id, cl=cl, feedback_fn=feedback_fn,
2073 583163a6 Michael Hanselmann
                       reporter=reporter)
2074 53c04d04 Iustin Pop
2075 53c04d04 Iustin Pop
  return op_results[0]
2076 0a1e74d9 Iustin Pop
2077 0a1e74d9 Iustin Pop
2078 94428652 Iustin Pop
def SubmitOrSend(op, opts, cl=None, feedback_fn=None):
2079 94428652 Iustin Pop
  """Wrapper around SubmitOpCode or SendJob.
2080 94428652 Iustin Pop

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

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

2089 94428652 Iustin Pop
  """
2090 94428652 Iustin Pop
  if opts and opts.submit_only:
2091 293ba2d8 Iustin Pop
    job = [op]
2092 293ba2d8 Iustin Pop
    SetGenericOpcodeOpts(job, opts)
2093 293ba2d8 Iustin Pop
    job_id = SendJob(job, cl=cl)
2094 e9d741b6 Iustin Pop
    raise JobSubmittedException(job_id)
2095 94428652 Iustin Pop
  else:
2096 293ba2d8 Iustin Pop
    return SubmitOpCode(op, cl=cl, feedback_fn=feedback_fn, opts=opts)
2097 293ba2d8 Iustin Pop
2098 293ba2d8 Iustin Pop
2099 293ba2d8 Iustin Pop
def SetGenericOpcodeOpts(opcode_list, options):
2100 293ba2d8 Iustin Pop
  """Processor for generic options.
2101 293ba2d8 Iustin Pop

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

2105 293ba2d8 Iustin Pop
  @param opcode_list: list of opcodes
2106 293ba2d8 Iustin Pop
  @param options: command line options or None
2107 293ba2d8 Iustin Pop
  @return: None (in-place modification)
2108 293ba2d8 Iustin Pop

2109 293ba2d8 Iustin Pop
  """
2110 293ba2d8 Iustin Pop
  if not options:
2111 293ba2d8 Iustin Pop
    return
2112 293ba2d8 Iustin Pop
  for op in opcode_list:
2113 aa06f8c6 Michael Hanselmann
    op.debug_level = options.debug
2114 a0a6ff34 Iustin Pop
    if hasattr(options, "dry_run"):
2115 a0a6ff34 Iustin Pop
      op.dry_run = options.dry_run
2116 aa06f8c6 Michael Hanselmann
    if getattr(options, "priority", None) is not None:
2117 552328b8 Michael Hanselmann
      op.priority = options.priority
2118 94428652 Iustin Pop
2119 94428652 Iustin Pop
2120 42ab9ac4 Iustin Pop
def GetClient(query=False):
2121 42ab9ac4 Iustin Pop
  """Connects to the a luxi socket and returns a client.
2122 42ab9ac4 Iustin Pop

2123 42ab9ac4 Iustin Pop
  @type query: boolean
2124 42ab9ac4 Iustin Pop
  @param query: this signifies that the client will only be
2125 42ab9ac4 Iustin Pop
      used for queries; if the build-time parameter
2126 42ab9ac4 Iustin Pop
      enable-split-queries is enabled, then the client will be
2127 42ab9ac4 Iustin Pop
      connected to the query socket instead of the masterd socket
2128 42ab9ac4 Iustin Pop

2129 42ab9ac4 Iustin Pop
  """
2130 42ab9ac4 Iustin Pop
  if query and constants.ENABLE_SPLIT_QUERY:
2131 ee4a14c0 Michael Hanselmann
    address = pathutils.QUERY_SOCKET
2132 42ab9ac4 Iustin Pop
  else:
2133 42ab9ac4 Iustin Pop
    address = None
2134 af30b2fd Michael Hanselmann
  # TODO: Cache object?
2135 b33e986b Iustin Pop
  try:
2136 42ab9ac4 Iustin Pop
    client = luxi.Client(address=address)
2137 b33e986b Iustin Pop
  except luxi.NoMasterError:
2138 d9a51679 Michael Hanselmann
    ss = ssconf.SimpleStore()
2139 d9a51679 Michael Hanselmann
2140 d9a51679 Michael Hanselmann
    # Try to read ssconf file
2141 d9a51679 Michael Hanselmann
    try:
2142 d9a51679 Michael Hanselmann
      ss.GetMasterNode()
2143 d9a51679 Michael Hanselmann
    except errors.ConfigurationError:
2144 d9a51679 Michael Hanselmann
      raise errors.OpPrereqError("Cluster not initialized or this machine is"
2145 2cfbc784 Iustin Pop
                                 " not part of a cluster",
2146 2cfbc784 Iustin Pop
                                 errors.ECODE_INVAL)
2147 d9a51679 Michael Hanselmann
2148 d9a51679 Michael Hanselmann
    master, myself = ssconf.GetMasterAndMyself(ss=ss)
2149 b33e986b Iustin Pop
    if master != myself:
2150 b33e986b Iustin Pop
      raise errors.OpPrereqError("This is not the master node, please connect"
2151 b33e986b Iustin Pop
                                 " to node '%s' and rerun the command" %
2152 2cfbc784 Iustin Pop
                                 master, errors.ECODE_INVAL)
2153 d9a51679 Michael Hanselmann
    raise
2154 b33e986b Iustin Pop
  return client
2155 af30b2fd Michael Hanselmann
2156 af30b2fd Michael Hanselmann
2157 73702ee7 Iustin Pop
def FormatError(err):
2158 73702ee7 Iustin Pop
  """Return a formatted error message for a given error.
2159 73702ee7 Iustin Pop

2160 73702ee7 Iustin Pop
  This function takes an exception instance and returns a tuple
2161 73702ee7 Iustin Pop
  consisting of two values: first, the recommended exit code, and
2162 73702ee7 Iustin Pop
  second, a string describing the error message (not
2163 73702ee7 Iustin Pop
  newline-terminated).
2164 73702ee7 Iustin Pop

2165 73702ee7 Iustin Pop
  """
2166 73702ee7 Iustin Pop
  retcode = 1
2167 73702ee7 Iustin Pop
  obuf = StringIO()
2168 e2e521d0 Iustin Pop
  msg = str(err)
2169 73702ee7 Iustin Pop
  if isinstance(err, errors.ConfigurationError):
2170 e2e521d0 Iustin Pop
    txt = "Corrupt configuration file: %s" % msg
2171 46fbdd04 Iustin Pop
    logging.error(txt)
2172 e2e521d0 Iustin Pop
    obuf.write(txt + "\n")
2173 73702ee7 Iustin Pop
    obuf.write("Aborting.")
2174 73702ee7 Iustin Pop
    retcode = 2
2175 73702ee7 Iustin Pop
  elif isinstance(err, errors.HooksAbort):
2176 73702ee7 Iustin Pop
    obuf.write("Failure: hooks execution failed:\n")
2177 73702ee7 Iustin Pop
    for node, script, out in err.args[0]:
2178 73702ee7 Iustin Pop
      if out:
2179 73702ee7 Iustin Pop
        obuf.write("  node: %s, script: %s, output: %s\n" %
2180 73702ee7 Iustin Pop
                   (node, script, out))
2181 73702ee7 Iustin Pop
      else:
2182 73702ee7 Iustin Pop
        obuf.write("  node: %s, script: %s (no output)\n" %
2183 73702ee7 Iustin Pop
                   (node, script))
2184 73702ee7 Iustin Pop
  elif isinstance(err, errors.HooksFailure):
2185 e2e521d0 Iustin Pop
    obuf.write("Failure: hooks general failure: %s" % msg)
2186 73702ee7 Iustin Pop
  elif isinstance(err, errors.ResolverError):
2187 b705c7a6 Manuel Franceschini
    this_host = netutils.Hostname.GetSysName()
2188 73702ee7 Iustin Pop
    if err.args[0] == this_host:
2189 73702ee7 Iustin Pop
      msg = "Failure: can't resolve my own hostname ('%s')"
2190 73702ee7 Iustin Pop
    else:
2191 73702ee7 Iustin Pop
      msg = "Failure: can't resolve hostname '%s'"
2192 73702ee7 Iustin Pop
    obuf.write(msg % err.args[0])
2193 73702ee7 Iustin Pop
  elif isinstance(err, errors.OpPrereqError):
2194 5c983ee5 Iustin Pop
    if len(err.args) == 2:
2195 5c983ee5 Iustin Pop
      obuf.write("Failure: prerequisites not met for this"
2196 5ae4945a Iustin Pop
                 " operation:\nerror type: %s, error details:\n%s" %
2197 5c983ee5 Iustin Pop
                 (err.args[1], err.args[0]))
2198 5c983ee5 Iustin Pop
    else:
2199 5c983ee5 Iustin Pop
      obuf.write("Failure: prerequisites not met for this"
2200 5c983ee5 Iustin Pop
                 " operation:\n%s" % msg)
2201 73702ee7 Iustin Pop
  elif isinstance(err, errors.OpExecError):
2202 e2e521d0 Iustin Pop
    obuf.write("Failure: command execution error:\n%s" % msg)
2203 73702ee7 Iustin Pop
  elif isinstance(err, errors.TagError):
2204 e2e521d0 Iustin Pop
    obuf.write("Failure: invalid tag(s) given:\n%s" % msg)
2205 686d7433 Iustin Pop
  elif isinstance(err, errors.JobQueueDrainError):
2206 686d7433 Iustin Pop
    obuf.write("Failure: the job queue is marked for drain and doesn't"
2207 686d7433 Iustin Pop
               " accept new requests\n")
2208 f87b405e Michael Hanselmann
  elif isinstance(err, errors.JobQueueFull):
2209 f87b405e Michael Hanselmann
    obuf.write("Failure: the job queue is full and doesn't accept new"
2210 f87b405e Michael Hanselmann
               " job submissions until old jobs are archived\n")
2211 a5728081 Guido Trotter
  elif isinstance(err, errors.TypeEnforcementError):
2212 a5728081 Guido Trotter
    obuf.write("Parameter Error: %s" % msg)
2213 c1ce76bb Iustin Pop
  elif isinstance(err, errors.ParameterError):
2214 c1ce76bb Iustin Pop
    obuf.write("Failure: unknown/wrong parameter name '%s'" % msg)
2215 03a8dbdc Iustin Pop
  elif isinstance(err, luxi.NoMasterError):
2216 03a8dbdc Iustin Pop
    obuf.write("Cannot communicate with the master daemon.\nIs it running"
2217 082c5adb Michael Hanselmann
               " and listening for connections?")
2218 03a8dbdc Iustin Pop
  elif isinstance(err, luxi.TimeoutError):
2219 cd4c86a8 Michael Hanselmann
    obuf.write("Timeout while talking to the master daemon. Jobs might have"
2220 cd4c86a8 Michael Hanselmann
               " been submitted and will continue to run even if the call"
2221 cd4c86a8 Michael Hanselmann
               " timed out. Useful commands in this situation are \"gnt-job"
2222 cd4c86a8 Michael Hanselmann
               " list\", \"gnt-job cancel\" and \"gnt-job watch\". Error:\n")
2223 cd4c86a8 Michael Hanselmann
    obuf.write(msg)
2224 5a1c22fe Iustin Pop
  elif isinstance(err, luxi.PermissionError):
2225 5a1c22fe Iustin Pop
    obuf.write("It seems you don't have permissions to connect to the"
2226 5a1c22fe Iustin Pop
               " master daemon.\nPlease retry as a different user.")
2227 03a8dbdc Iustin Pop
  elif isinstance(err, luxi.ProtocolError):
2228 03a8dbdc Iustin Pop
    obuf.write("Unhandled protocol error while talking to the master daemon:\n"
2229 03a8dbdc Iustin Pop
               "%s" % msg)
2230 91c622a8 Iustin Pop
  elif isinstance(err, errors.JobLost):
2231 91c622a8 Iustin Pop
    obuf.write("Error checking job status: %s" % msg)
2232 cb1e6c3c Michael Hanselmann
  elif isinstance(err, errors.QueryFilterParseError):
2233 cb1e6c3c Michael Hanselmann
    obuf.write("Error while parsing query filter: %s\n" % err.args[0])
2234 cb1e6c3c Michael Hanselmann
    obuf.write("\n".join(err.GetDetails()))
2235 797506fc Michael Hanselmann
  elif isinstance(err, errors.GenericError):
2236 797506fc Michael Hanselmann
    obuf.write("Unhandled Ganeti error: %s" % msg)
2237 e9d741b6 Iustin Pop
  elif isinstance(err, JobSubmittedException):
2238 e9d741b6 Iustin Pop
    obuf.write("JobID: %s\n" % err.args[0])
2239 e9d741b6 Iustin Pop
    retcode = 0
2240 73702ee7 Iustin Pop
  else:
2241 e2e521d0 Iustin Pop
    obuf.write("Unhandled exception: %s" % msg)
2242 d0c8c01d Iustin Pop
  return retcode, obuf.getvalue().rstrip("\n")
2243 73702ee7 Iustin Pop
2244 73702ee7 Iustin Pop
2245 ef9fa5b9 René Nussbaumer
def GenericMain(commands, override=None, aliases=None,
2246 ef9fa5b9 René Nussbaumer
                env_override=frozenset()):
2247 a8083063 Iustin Pop
  """Generic main function for all the gnt-* commands.
2248 a8083063 Iustin Pop

2249 ef9fa5b9 René Nussbaumer
  @param commands: a dictionary with a special structure, see the design doc
2250 ef9fa5b9 René Nussbaumer
                   for command line handling.
2251 ef9fa5b9 René Nussbaumer
  @param override: if not None, we expect a dictionary with keys that will
2252 ef9fa5b9 René Nussbaumer
                   override command line options; this can be used to pass
2253 ef9fa5b9 René Nussbaumer
                   options from the scripts to generic functions
2254 ef9fa5b9 René Nussbaumer
  @param aliases: dictionary with command aliases {'alias': 'target, ...}
2255 ef9fa5b9 René Nussbaumer
  @param env_override: list of environment names which are allowed to submit
2256 ef9fa5b9 René Nussbaumer
                       default args for commands
2257 a8083063 Iustin Pop

2258 a8083063 Iustin Pop
  """
2259 a8083063 Iustin Pop
  # save the program name and the entire command line for later logging
2260 a8083063 Iustin Pop
  if sys.argv:
2261 c1f19851 Michael Hanselmann
    binary = os.path.basename(sys.argv[0])
2262 c1f19851 Michael Hanselmann
    if not binary:
2263 c1f19851 Michael Hanselmann
      binary = sys.argv[0]
2264 c1f19851 Michael Hanselmann
2265 a8083063 Iustin Pop
    if len(sys.argv) >= 2:
2266 c1f19851 Michael Hanselmann
      logname = utils.ShellQuoteArgs([binary, sys.argv[1]])
2267 a8083063 Iustin Pop
    else:
2268 c1f19851 Michael Hanselmann
      logname = binary
2269 c1f19851 Michael Hanselmann
2270 c1f19851 Michael Hanselmann
    cmdline = utils.ShellQuoteArgs([binary] + sys.argv[1:])
2271 a8083063 Iustin Pop
  else:
2272 a8083063 Iustin Pop
    binary = "<unknown program>"
2273 c1f19851 Michael Hanselmann
    cmdline = "<unknown>"
2274 a8083063 Iustin Pop
2275 de47cf8f Guido Trotter
  if aliases is None:
2276 de47cf8f Guido Trotter
    aliases = {}
2277 de47cf8f Guido Trotter
2278 3126878d Guido Trotter
  try:
2279 d971402f Michael Hanselmann
    (func, options, args) = _ParseArgs(binary, sys.argv, commands, aliases,
2280 d971402f Michael Hanselmann
                                       env_override)
2281 d971402f Michael Hanselmann
  except _ShowVersion:
2282 d971402f Michael Hanselmann
    ToStdout("%s (ganeti %s) %s", binary, constants.VCS_VERSION,
2283 d971402f Michael Hanselmann
             constants.RELEASE_VERSION)
2284 d971402f Michael Hanselmann
    return constants.EXIT_SUCCESS
2285 d971402f Michael Hanselmann
  except _ShowUsage, err:
2286 d971402f Michael Hanselmann
    for line in _FormatUsage(binary, commands):
2287 d971402f Michael Hanselmann
      ToStdout(line)
2288 d971402f Michael Hanselmann
2289 d971402f Michael Hanselmann
    if err.exit_error:
2290 d971402f Michael Hanselmann
      return constants.EXIT_FAILURE
2291 d971402f Michael Hanselmann
    else:
2292 d971402f Michael Hanselmann
      return constants.EXIT_SUCCESS
2293 3126878d Guido Trotter
  except errors.ParameterError, err:
2294 3126878d Guido Trotter
    result, err_msg = FormatError(err)
2295 3126878d Guido Trotter
    ToStderr(err_msg)
2296 3126878d Guido Trotter
    return 1
2297 3126878d Guido Trotter
2298 a8083063 Iustin Pop
  if func is None: # parse error
2299 a8083063 Iustin Pop
    return 1
2300 a8083063 Iustin Pop
2301 334d1483 Iustin Pop
  if override is not None:
2302 334d1483 Iustin Pop
    for key, val in override.iteritems():
2303 334d1483 Iustin Pop
      setattr(options, key, val)
2304 334d1483 Iustin Pop
2305 ee4a14c0 Michael Hanselmann
  utils.SetupLogging(pathutils.LOG_COMMANDS, logname, debug=options.debug,
2306 cfcc79c6 Michael Hanselmann
                     stderr_logging=True)
2307 a8083063 Iustin Pop
2308 c1f19851 Michael Hanselmann
  logging.info("Command line: %s", cmdline)
2309 a8083063 Iustin Pop
2310 a8083063 Iustin Pop
  try:
2311 a4af651e Iustin Pop
    result = func(options, args)
2312 d8353c3a Iustin Pop
  except (errors.GenericError, luxi.ProtocolError,
2313 d8353c3a Iustin Pop
          JobSubmittedException), err:
2314 a4af651e Iustin Pop
    result, err_msg = FormatError(err)
2315 5bbd3f7f Michael Hanselmann
    logging.exception("Error during command processing")
2316 46fbdd04 Iustin Pop
    ToStderr(err_msg)
2317 8a53b55f Iustin Pop
  except KeyboardInterrupt:
2318 8a53b55f Iustin Pop
    result = constants.EXIT_FAILURE
2319 8a53b55f Iustin Pop
    ToStderr("Aborted. Note that if the operation created any jobs, they"
2320 8a53b55f Iustin Pop
             " might have been submitted and"
2321 8a53b55f Iustin Pop
             " will continue to run in the background.")
2322 225e2544 Iustin Pop
  except IOError, err:
2323 225e2544 Iustin Pop
    if err.errno == errno.EPIPE:
2324 225e2544 Iustin Pop
      # our terminal went away, we'll exit
2325 225e2544 Iustin Pop
      sys.exit(constants.EXIT_FAILURE)
2326 225e2544 Iustin Pop
    else:
2327 225e2544 Iustin Pop
      raise
2328 a8083063 Iustin Pop
2329 a8083063 Iustin Pop
  return result
2330 137161c9 Michael Hanselmann
2331 137161c9 Michael Hanselmann
2332 845c79d8 Michael Hanselmann
def ParseNicOption(optvalue):
2333 845c79d8 Michael Hanselmann
  """Parses the value of the --net option(s).
2334 845c79d8 Michael Hanselmann

2335 845c79d8 Michael Hanselmann
  """
2336 845c79d8 Michael Hanselmann
  try:
2337 845c79d8 Michael Hanselmann
    nic_max = max(int(nidx[0]) + 1 for nidx in optvalue)
2338 845c79d8 Michael Hanselmann
  except (TypeError, ValueError), err:
2339 2cfbc784 Iustin Pop
    raise errors.OpPrereqError("Invalid NIC index passed: %s" % str(err),
2340 2cfbc784 Iustin Pop
                               errors.ECODE_INVAL)
2341 845c79d8 Michael Hanselmann
2342 845c79d8 Michael Hanselmann
  nics = [{}] * nic_max
2343 845c79d8 Michael Hanselmann
  for nidx, ndict in optvalue:
2344 845c79d8 Michael Hanselmann
    nidx = int(nidx)
2345 845c79d8 Michael Hanselmann
2346 845c79d8 Michael Hanselmann
    if not isinstance(ndict, dict):
2347 845c79d8 Michael Hanselmann
      raise errors.OpPrereqError("Invalid nic/%d value: expected dict,"
2348 2cfbc784 Iustin Pop
                                 " got %s" % (nidx, ndict), errors.ECODE_INVAL)
2349 845c79d8 Michael Hanselmann
2350 845c79d8 Michael Hanselmann
    utils.ForceDictType(ndict, constants.INIC_PARAMS_TYPES)
2351 845c79d8 Michael Hanselmann
2352 845c79d8 Michael Hanselmann
    nics[nidx] = ndict
2353 845c79d8 Michael Hanselmann
2354 845c79d8 Michael Hanselmann
  return nics
2355 845c79d8 Michael Hanselmann
2356 845c79d8 Michael Hanselmann
2357 d77490c5 Iustin Pop
def GenericInstanceCreate(mode, opts, args):
2358 d77490c5 Iustin Pop
  """Add an instance to the cluster via either creation or import.
2359 d77490c5 Iustin Pop

2360 d77490c5 Iustin Pop
  @param mode: constants.INSTANCE_CREATE or constants.INSTANCE_IMPORT
2361 d77490c5 Iustin Pop
  @param opts: the command line options selected by the user
2362 d77490c5 Iustin Pop
  @type args: list
2363 d77490c5 Iustin Pop
  @param args: should contain only one element, the new instance name
2364 d77490c5 Iustin Pop
  @rtype: int
2365 d77490c5 Iustin Pop
  @return: the desired exit code
2366 d77490c5 Iustin Pop

2367 d77490c5 Iustin Pop
  """
2368 d77490c5 Iustin Pop
  instance = args[0]
2369 d77490c5 Iustin Pop
2370 d77490c5 Iustin Pop
  (pnode, snode) = SplitNodeOption(opts.node)
2371 d77490c5 Iustin Pop
2372 d77490c5 Iustin Pop
  hypervisor = None
2373 d77490c5 Iustin Pop
  hvparams = {}
2374 d77490c5 Iustin Pop
  if opts.hypervisor:
2375 d77490c5 Iustin Pop
    hypervisor, hvparams = opts.hypervisor
2376 d77490c5 Iustin Pop
2377 d77490c5 Iustin Pop
  if opts.nics:
2378 845c79d8 Michael Hanselmann
    nics = ParseNicOption(opts.nics)
2379 d77490c5 Iustin Pop
  elif opts.no_nics:
2380 d77490c5 Iustin Pop
    # no nics
2381 d77490c5 Iustin Pop
    nics = []
2382 0af0f641 Iustin Pop
  elif mode == constants.INSTANCE_CREATE:
2383 d77490c5 Iustin Pop
    # default of one nic, all auto
2384 d77490c5 Iustin Pop
    nics = [{}]
2385 0af0f641 Iustin Pop
  else:
2386 0af0f641 Iustin Pop
    # mode == import
2387 0af0f641 Iustin Pop
    nics = []
2388 d77490c5 Iustin Pop
2389 d77490c5 Iustin Pop
  if opts.disk_template == constants.DT_DISKLESS:
2390 d77490c5 Iustin Pop
    if opts.disks or opts.sd_size is not None:
2391 d77490c5 Iustin Pop
      raise errors.OpPrereqError("Diskless instance but disk"
2392 2cfbc784 Iustin Pop
                                 " information passed", errors.ECODE_INVAL)
2393 d77490c5 Iustin Pop
    disks = []
2394 d77490c5 Iustin Pop
  else:
2395 9b12ed0f Iustin Pop
    if (not opts.disks and not opts.sd_size
2396 9b12ed0f Iustin Pop
        and mode == constants.INSTANCE_CREATE):
2397 2cfbc784 Iustin Pop
      raise errors.OpPrereqError("No disk information specified",
2398 2cfbc784 Iustin Pop
                                 errors.ECODE_INVAL)
2399 d77490c5 Iustin Pop
    if opts.disks and opts.sd_size is not None:
2400 d77490c5 Iustin Pop
      raise errors.OpPrereqError("Please use either the '--disk' or"
2401 2cfbc784 Iustin Pop
                                 " '-s' option", errors.ECODE_INVAL)
2402 d77490c5 Iustin Pop
    if opts.sd_size is not None:
2403 ccfa86ba Michael Hanselmann
      opts.disks = [(0, {constants.IDISK_SIZE: opts.sd_size})]
2404 9b12ed0f Iustin Pop
2405 9b12ed0f Iustin Pop
    if opts.disks:
2406 9b12ed0f Iustin Pop
      try:
2407 9b12ed0f Iustin Pop
        disk_max = max(int(didx[0]) + 1 for didx in opts.disks)
2408 9b12ed0f Iustin Pop
      except ValueError, err:
2409 2cfbc784 Iustin Pop
        raise errors.OpPrereqError("Invalid disk index passed: %s" % str(err),
2410 2cfbc784 Iustin Pop
                                   errors.ECODE_INVAL)
2411 9b12ed0f Iustin Pop
      disks = [{}] * disk_max
2412 9b12ed0f Iustin Pop
    else:
2413 9b12ed0f Iustin Pop
      disks = []
2414 d77490c5 Iustin Pop
    for didx, ddict in opts.disks:
2415 d77490c5 Iustin Pop
      didx = int(didx)
2416 d77490c5 Iustin Pop
      if not isinstance(ddict, dict):
2417 d77490c5 Iustin Pop
        msg = "Invalid disk/%d value: expected dict, got %s" % (didx, ddict)
2418 2cfbc784 Iustin Pop
        raise errors.OpPrereqError(msg, errors.ECODE_INVAL)
2419 ccfa86ba Michael Hanselmann
      elif constants.IDISK_SIZE in ddict:
2420 ccfa86ba Michael Hanselmann
        if constants.IDISK_ADOPT in ddict:
2421 5029db65 Iustin Pop
          raise errors.OpPrereqError("Only one of 'size' and 'adopt' allowed"
2422 2cfbc784 Iustin Pop
                                     " (disk %d)" % didx, errors.ECODE_INVAL)
2423 5029db65 Iustin Pop
        try:
2424 ccfa86ba Michael Hanselmann
          ddict[constants.IDISK_SIZE] = \
2425 ccfa86ba Michael Hanselmann
            utils.ParseUnit(ddict[constants.IDISK_SIZE])
2426 5029db65 Iustin Pop
        except ValueError, err:
2427 5029db65 Iustin Pop
          raise errors.OpPrereqError("Invalid disk size for disk %d: %s" %
2428 2cfbc784 Iustin Pop
                                     (didx, err), errors.ECODE_INVAL)
2429 ccfa86ba Michael Hanselmann
      elif constants.IDISK_ADOPT in ddict:
2430 5029db65 Iustin Pop
        if mode == constants.INSTANCE_IMPORT:
2431 5029db65 Iustin Pop
          raise errors.OpPrereqError("Disk adoption not allowed for instance"
2432 2cfbc784 Iustin Pop
                                     " import", errors.ECODE_INVAL)
2433 ccfa86ba Michael Hanselmann
        ddict[constants.IDISK_SIZE] = 0
2434 5029db65 Iustin Pop
      else:
2435 5029db65 Iustin Pop
        raise errors.OpPrereqError("Missing size or adoption source for"
2436 2cfbc784 Iustin Pop
                                   " disk %d" % didx, errors.ECODE_INVAL)
2437 d77490c5 Iustin Pop
      disks[didx] = ddict
2438 d77490c5 Iustin Pop
2439 a57981c5 Apollon Oikonomopoulos
  if opts.tags is not None:
2440 0f8810df Michael Hanselmann
    tags = opts.tags.split(",")
2441 a57981c5 Apollon Oikonomopoulos
  else:
2442 a57981c5 Apollon Oikonomopoulos
    tags = []
2443 a57981c5 Apollon Oikonomopoulos
2444 b2e233a5 Guido Trotter
  utils.ForceDictType(opts.beparams, constants.BES_PARAMETER_COMPAT)
2445 d77490c5 Iustin Pop
  utils.ForceDictType(hvparams, constants.HVS_PARAMETER_TYPES)
2446 d77490c5 Iustin Pop
2447 d77490c5 Iustin Pop
  if mode == constants.INSTANCE_CREATE:
2448 d77490c5 Iustin Pop
    start = opts.start
2449 d77490c5 Iustin Pop
    os_type = opts.os
2450 1ee8e01a Guido Trotter
    force_variant = opts.force_variant
2451 d77490c5 Iustin Pop
    src_node = None
2452 d77490c5 Iustin Pop
    src_path = None
2453 25a8792c Iustin Pop
    no_install = opts.no_install
2454 e588764d Iustin Pop
    identify_defaults = False
2455 d77490c5 Iustin Pop
  elif mode == constants.INSTANCE_IMPORT:
2456 d77490c5 Iustin Pop
    start = False
2457 d77490c5 Iustin Pop
    os_type = None
2458 1ee8e01a Guido Trotter
    force_variant = False
2459 d77490c5 Iustin Pop
    src_node = opts.src_node
2460 d77490c5 Iustin Pop
    src_path = opts.src_dir
2461 25a8792c Iustin Pop
    no_install = None
2462 e588764d Iustin Pop
    identify_defaults = opts.identify_defaults
2463 d77490c5 Iustin Pop
  else:
2464 d77490c5 Iustin Pop
    raise errors.ProgrammerError("Invalid creation mode %s" % mode)
2465 d77490c5 Iustin Pop
2466 e1530b10 Iustin Pop
  op = opcodes.OpInstanceCreate(instance_name=instance,
2467 d77490c5 Iustin Pop
                                disks=disks,
2468 d77490c5 Iustin Pop
                                disk_template=opts.disk_template,
2469 d77490c5 Iustin Pop
                                nics=nics,
2470 d77490c5 Iustin Pop
                                pnode=pnode, snode=snode,
2471 d77490c5 Iustin Pop
                                ip_check=opts.ip_check,
2472 460d22be Iustin Pop
                                name_check=opts.name_check,
2473 d77490c5 Iustin Pop
                                wait_for_sync=opts.wait_for_sync,
2474 d77490c5 Iustin Pop
                                file_storage_dir=opts.file_storage_dir,
2475 d77490c5 Iustin Pop
                                file_driver=opts.file_driver,
2476 d77490c5 Iustin Pop
                                iallocator=opts.iallocator,
2477 d77490c5 Iustin Pop
                                hypervisor=hypervisor,
2478 d77490c5 Iustin Pop
                                hvparams=hvparams,
2479 d77490c5 Iustin Pop
                                beparams=opts.beparams,
2480 062a7100 Iustin Pop
                                osparams=opts.osparams,
2481 d77490c5 Iustin Pop
                                mode=mode,
2482 d77490c5 Iustin Pop
                                start=start,
2483 d77490c5 Iustin Pop
                                os_type=os_type,
2484 1ee8e01a Guido Trotter
                                force_variant=force_variant,
2485 d77490c5 Iustin Pop
                                src_node=src_node,
2486 25a8792c Iustin Pop
                                src_path=src_path,
2487 a57981c5 Apollon Oikonomopoulos
                                tags=tags,
2488 e588764d Iustin Pop
                                no_install=no_install,
2489 10889e0c René Nussbaumer
                                identify_defaults=identify_defaults,
2490 10889e0c René Nussbaumer
                                ignore_ipolicy=opts.ignore_ipolicy)
2491 d77490c5 Iustin Pop
2492 d77490c5 Iustin Pop
  SubmitOrSend(op, opts)
2493 d77490c5 Iustin Pop
  return 0
2494 d77490c5 Iustin Pop
2495 d77490c5 Iustin Pop
2496 7e49b6ce Michael Hanselmann
class _RunWhileClusterStoppedHelper:
2497 7e49b6ce Michael Hanselmann
  """Helper class for L{RunWhileClusterStopped} to simplify state management
2498 7e49b6ce Michael Hanselmann

2499 7e49b6ce Michael Hanselmann
  """
2500 7e49b6ce Michael Hanselmann
  def __init__(self, feedback_fn, cluster_name, master_node, online_nodes):
2501 7e49b6ce Michael Hanselmann
    """Initializes this class.
2502 7e49b6ce Michael Hanselmann

2503 7e49b6ce Michael Hanselmann
    @type feedback_fn: callable
2504 7e49b6ce Michael Hanselmann
    @param feedback_fn: Feedback function
2505 7e49b6ce Michael Hanselmann
    @type cluster_name: string
2506 7e49b6ce Michael Hanselmann
    @param cluster_name: Cluster name
2507 7e49b6ce Michael Hanselmann
    @type master_node: string
2508 7e49b6ce Michael Hanselmann
    @param master_node Master node name
2509 7e49b6ce Michael Hanselmann
    @type online_nodes: list
2510 7e49b6ce Michael Hanselmann
    @param online_nodes: List of names of online nodes
2511 7e49b6ce Michael Hanselmann

2512 7e49b6ce Michael Hanselmann
    """
2513 7e49b6ce Michael Hanselmann
    self.feedback_fn = feedback_fn
2514 7e49b6ce Michael Hanselmann
    self.cluster_name = cluster_name
2515 7e49b6ce Michael Hanselmann
    self.master_node = master_node
2516 7e49b6ce Michael Hanselmann
    self.online_nodes = online_nodes
2517 7e49b6ce Michael Hanselmann
2518 7e49b6ce Michael Hanselmann
    self.ssh = ssh.SshRunner(self.cluster_name)
2519 7e49b6ce Michael Hanselmann
2520 7e49b6ce Michael Hanselmann
    self.nonmaster_nodes = [name for name in online_nodes
2521 7e49b6ce Michael Hanselmann
                            if name != master_node]
2522 7e49b6ce Michael Hanselmann
2523 7e49b6ce Michael Hanselmann
    assert self.master_node not in self.nonmaster_nodes
2524 7e49b6ce Michael Hanselmann
2525 7e49b6ce Michael Hanselmann
  def _RunCmd(self, node_name, cmd):
2526 7e49b6ce Michael Hanselmann
    """Runs a command on the local or a remote machine.
2527 7e49b6ce Michael Hanselmann

2528 7e49b6ce Michael Hanselmann
    @type node_name: string
2529 7e49b6ce Michael Hanselmann
    @param node_name: Machine name
2530 7e49b6ce Michael Hanselmann
    @type cmd: list
2531 7e49b6ce Michael Hanselmann
    @param cmd: Command
2532 7e49b6ce Michael Hanselmann

2533 7e49b6ce Michael Hanselmann
    """
2534 7e49b6ce Michael Hanselmann
    if node_name is None or node_name == self.master_node:
2535 7e49b6ce Michael Hanselmann
      # No need to use SSH
2536 7e49b6ce Michael Hanselmann
      result = utils.RunCmd(cmd)
2537 7e49b6ce Michael Hanselmann
    else:
2538 052783ff Michael Hanselmann
      result = self.ssh.Run(node_name, constants.SSH_LOGIN_USER,
2539 052783ff Michael Hanselmann
                            utils.ShellQuoteArgs(cmd))
2540 7e49b6ce Michael Hanselmann
2541 7e49b6ce Michael Hanselmann
    if result.failed:
2542 7e49b6ce Michael Hanselmann
      errmsg = ["Failed to run command %s" % result.cmd]
2543 7e49b6ce Michael Hanselmann
      if node_name:
2544 7e49b6ce Michael Hanselmann
        errmsg.append("on node %s" % node_name)
2545 7e49b6ce Michael Hanselmann
      errmsg.append(": exitcode %s and error %s" %
2546 7e49b6ce Michael Hanselmann
                    (result.exit_code, result.output))
2547 7e49b6ce Michael Hanselmann
      raise errors.OpExecError(" ".join(errmsg))
2548 7e49b6ce Michael Hanselmann
2549 7e49b6ce Michael Hanselmann
  def Call(self, fn, *args):
2550 7e49b6ce Michael Hanselmann
    """Call function while all daemons are stopped.
2551 7e49b6ce Michael Hanselmann

2552 7e49b6ce Michael Hanselmann
    @type fn: callable
2553 7e49b6ce Michael Hanselmann
    @param fn: Function to be called
2554 7e49b6ce Michael Hanselmann

2555 7e49b6ce Michael Hanselmann
    """
2556 7e49b6ce Michael Hanselmann
    # Pause watcher by acquiring an exclusive lock on watcher state file
2557 7e49b6ce Michael Hanselmann
    self.feedback_fn("Blocking watcher")
2558 ee4a14c0 Michael Hanselmann
    watcher_block = utils.FileLock.Open(pathutils.WATCHER_LOCK_FILE)
2559 7e49b6ce Michael Hanselmann
    try:
2560 7e49b6ce Michael Hanselmann
      # TODO: Currently, this just blocks. There's no timeout.
2561 7e49b6ce Michael Hanselmann
      # TODO: Should it be a shared lock?
2562 7e49b6ce Michael Hanselmann
      watcher_block.Exclusive(blocking=True)
2563 7e49b6ce Michael Hanselmann
2564 7e49b6ce Michael Hanselmann
      # Stop master daemons, so that no new jobs can come in and all running
2565 7e49b6ce Michael Hanselmann
      # ones are finished
2566 7e49b6ce Michael Hanselmann
      self.feedback_fn("Stopping master daemons")
2567 ee4a14c0 Michael Hanselmann
      self._RunCmd(None, [pathutils.DAEMON_UTIL, "stop-master"])
2568 7e49b6ce Michael Hanselmann
      try:
2569 7e49b6ce Michael Hanselmann
        # Stop daemons on all nodes
2570 7e49b6ce Michael Hanselmann
        for node_name in self.online_nodes:
2571 7e49b6ce Michael Hanselmann
          self.feedback_fn("Stopping daemons on %s" % node_name)
2572 ee4a14c0 Michael Hanselmann
          self._RunCmd(node_name, [pathutils.DAEMON_UTIL, "stop-all"])
2573 7e49b6ce Michael Hanselmann
2574 7e49b6ce Michael Hanselmann
        # All daemons are shut down now
2575 7e49b6ce Michael Hanselmann
        try:
2576 7e49b6ce Michael Hanselmann
          return fn(self, *args)
2577 d512e84b Michael Hanselmann
        except Exception, err:
2578 d512e84b Michael Hanselmann
          _, errmsg = FormatError(err)
2579 7e49b6ce Michael Hanselmann
          logging.exception("Caught exception")
2580 d512e84b Michael Hanselmann
          self.feedback_fn(errmsg)
2581 7e49b6ce Michael Hanselmann
          raise
2582 7e49b6ce Michael Hanselmann
      finally:
2583 7e49b6ce Michael Hanselmann
        # Start cluster again, master node last
2584 7e49b6ce Michael Hanselmann
        for node_name in self.nonmaster_nodes + [self.master_node]:
2585 7e49b6ce Michael Hanselmann
          self.feedback_fn("Starting daemons on %s" % node_name)
2586 ee4a14c0 Michael Hanselmann
          self._RunCmd(node_name, [pathutils.DAEMON_UTIL, "start-all"])
2587 7e49b6ce Michael Hanselmann
    finally:
2588 7e49b6ce Michael Hanselmann
      # Resume watcher
2589 7e49b6ce Michael Hanselmann
      watcher_block.Close()
2590 7e49b6ce Michael Hanselmann
2591 7e49b6ce Michael Hanselmann
2592 7e49b6ce Michael Hanselmann
def RunWhileClusterStopped(feedback_fn, fn, *args):
2593 7e49b6ce Michael Hanselmann
  """Calls a function while all cluster daemons are stopped.
2594 7e49b6ce Michael Hanselmann

2595 7e49b6ce Michael Hanselmann
  @type feedback_fn: callable
2596 7e49b6ce Michael Hanselmann
  @param feedback_fn: Feedback function
2597 7e49b6ce Michael Hanselmann
  @type fn: callable
2598 7e49b6ce Michael Hanselmann
  @param fn: Function to be called when daemons are stopped
2599 7e49b6ce Michael Hanselmann

2600 7e49b6ce Michael Hanselmann
  """
2601 7e49b6ce Michael Hanselmann
  feedback_fn("Gathering cluster information")
2602 7e49b6ce Michael Hanselmann
2603 7e49b6ce Michael Hanselmann
  # This ensures we're running on the master daemon
2604 7e49b6ce Michael Hanselmann
  cl = GetClient()
2605 7e49b6ce Michael Hanselmann
2606 7e49b6ce Michael Hanselmann
  (cluster_name, master_node) = \
2607 7e49b6ce Michael Hanselmann
    cl.QueryConfigValues(["cluster_name", "master_node"])
2608 7e49b6ce Michael Hanselmann
2609 7e49b6ce Michael Hanselmann
  online_nodes = GetOnlineNodes([], cl=cl)
2610 7e49b6ce Michael Hanselmann
2611 7e49b6ce Michael Hanselmann
  # Don't keep a reference to the client. The master daemon will go away.
2612 7e49b6ce Michael Hanselmann
  del cl
2613 7e49b6ce Michael Hanselmann
2614 7e49b6ce Michael Hanselmann
  assert master_node in online_nodes
2615 7e49b6ce Michael Hanselmann
2616 7e49b6ce Michael Hanselmann
  return _RunWhileClusterStoppedHelper(feedback_fn, cluster_name, master_node,
2617 7e49b6ce Michael Hanselmann
                                       online_nodes).Call(fn, *args)
2618 7e49b6ce Michael Hanselmann
2619 7e49b6ce Michael Hanselmann
2620 16be8703 Iustin Pop
def GenerateTable(headers, fields, separator, data,
2621 9fbfbb7b Iustin Pop
                  numfields=None, unitfields=None,
2622 9fbfbb7b Iustin Pop
                  units=None):
2623 137161c9 Michael Hanselmann
  """Prints a table with headers and different fields.
2624 137161c9 Michael Hanselmann

2625 9fbfbb7b Iustin Pop
  @type headers: dict
2626 9fbfbb7b Iustin Pop
  @param headers: dictionary mapping field names to headers for
2627 9fbfbb7b Iustin Pop
      the table
2628 9fbfbb7b Iustin Pop
  @type fields: list
2629 9fbfbb7b Iustin Pop
  @param fields: the field names corresponding to each row in
2630 9fbfbb7b Iustin Pop
      the data field
2631 9fbfbb7b Iustin Pop
  @param separator: the separator to be used; if this is None,
2632 9fbfbb7b Iustin Pop
      the default 'smart' algorithm is used which computes optimal
2633 9fbfbb7b Iustin Pop
      field width, otherwise just the separator is used between
2634 9fbfbb7b Iustin Pop
      each field
2635 9fbfbb7b Iustin Pop
  @type data: list
2636 9fbfbb7b Iustin Pop
  @param data: a list of lists, each sublist being one row to be output
2637 9fbfbb7b Iustin Pop
  @type numfields: list
2638 9fbfbb7b Iustin Pop
  @param numfields: a list with the fields that hold numeric
2639 9fbfbb7b Iustin Pop
      values and thus should be right-aligned
2640 9fbfbb7b Iustin Pop
  @type unitfields: list
2641 9fbfbb7b Iustin Pop
  @param unitfields: a list with the fields that hold numeric
2642 9fbfbb7b Iustin Pop
      values that should be formatted with the units field
2643 9fbfbb7b Iustin Pop
  @type units: string or None
2644 9fbfbb7b Iustin Pop
  @param units: the units we should use for formatting, or None for
2645 9fbfbb7b Iustin Pop
      automatic choice (human-readable for non-separator usage, otherwise
2646 9fbfbb7b Iustin Pop
      megabytes); this is a one-letter string
2647 137161c9 Michael Hanselmann

2648 137161c9 Michael Hanselmann
  """
2649 9fbfbb7b Iustin Pop
  if units is None:
2650 9fbfbb7b Iustin Pop
    if separator:
2651 9fbfbb7b Iustin Pop
      units = "m"
2652 9fbfbb7b Iustin Pop
    else:
2653 9fbfbb7b Iustin Pop
      units = "h"
2654 9fbfbb7b Iustin Pop
2655 137161c9 Michael Hanselmann
  if numfields is None:
2656 137161c9 Michael Hanselmann
    numfields = []
2657 137161c9 Michael Hanselmann
  if unitfields is None:
2658 137161c9 Michael Hanselmann
    unitfields = []
2659 137161c9 Michael Hanselmann
2660 b459a848 Andrea Spadaccini
  numfields = utils.FieldSet(*numfields)   # pylint: disable=W0142
2661 b459a848 Andrea Spadaccini
  unitfields = utils.FieldSet(*unitfields) # pylint: disable=W0142
2662 00430f8e Iustin Pop
2663 137161c9 Michael Hanselmann
  format_fields = []
2664 137161c9 Michael Hanselmann
  for field in fields:
2665 01ca31ae Iustin Pop
    if headers and field not in headers:
2666 ea5a5b74 Guido Trotter
      # TODO: handle better unknown fields (either revert to old
2667 71c1af58 Iustin Pop
      # style of raising exception, or deal more intelligently with
2668 71c1af58 Iustin Pop
      # variable fields)
2669 71c1af58 Iustin Pop
      headers[field] = field
2670 137161c9 Michael Hanselmann
    if separator is not None:
2671 137161c9 Michael Hanselmann
      format_fields.append("%s")
2672 00430f8e Iustin Pop
    elif numfields.Matches(field):
2673 137161c9 Michael Hanselmann
      format_fields.append("%*s")
2674 137161c9 Michael Hanselmann
    else:
2675 137161c9 Michael Hanselmann
      format_fields.append("%-*s")
2676 137161c9 Michael Hanselmann
2677 137161c9 Michael Hanselmann
  if separator is None:
2678 137161c9 Michael Hanselmann
    mlens = [0 for name in fields]
2679 d0c8c01d Iustin Pop
    format_str = " ".join(format_fields)
2680 137161c9 Michael Hanselmann
  else:
2681 c04bc777 Iustin Pop
    format_str = separator.replace("%", "%%").join(format_fields)
2682 137161c9 Michael Hanselmann
2683 137161c9 Michael Hanselmann
  for row in data:
2684 dcbd6288 Guido Trotter
    if row is None:
2685 dcbd6288 Guido Trotter
      continue
2686 137161c9 Michael Hanselmann
    for idx, val in enumerate(row):
2687 00430f8e Iustin Pop
      if unitfields.Matches(fields[idx]):
2688 137161c9 Michael Hanselmann
        try:
2689 137161c9 Michael Hanselmann
          val = int(val)
2690 691744c4 Iustin Pop
        except (TypeError, ValueError):
2691 137161c9 Michael Hanselmann
          pass
2692 137161c9 Michael Hanselmann
        else:
2693 9fbfbb7b Iustin Pop
          val = row[idx] = utils.FormatUnit(val, units)
2694 01ca31ae Iustin Pop
      val = row[idx] = str(val)
2695 137161c9 Michael Hanselmann
      if separator is None:
2696 137161c9 Michael Hanselmann
        mlens[idx] = max(mlens[idx], len(val))
2697 137161c9 Michael Hanselmann
2698 16be8703 Iustin Pop
  result = []
2699 137161c9 Michael Hanselmann
  if headers:
2700 137161c9 Michael Hanselmann
    args = []
2701 137161c9 Michael Hanselmann
    for idx, name in enumerate(fields):
2702 137161c9 Michael Hanselmann
      hdr = headers[name]
2703 137161c9 Michael Hanselmann
      if separator is None:
2704 137161c9 Michael Hanselmann
        mlens[idx] = max(mlens[idx], len(hdr))
2705 137161c9 Michael Hanselmann
        args.append(mlens[idx])
2706 137161c9 Michael Hanselmann
      args.append(hdr)
2707 c04bc777 Iustin Pop
    result.append(format_str % tuple(args))
2708 137161c9 Michael Hanselmann
2709 ec39d63c Michael Hanselmann
  if separator is None:
2710 ec39d63c Michael Hanselmann
    assert len(mlens) == len(fields)
2711 ec39d63c Michael Hanselmann
2712 ec39d63c Michael Hanselmann
    if fields and not numfields.Matches(fields[-1]):
2713 ec39d63c Michael Hanselmann
      mlens[-1] = 0
2714 ec39d63c Michael Hanselmann
2715 137161c9 Michael Hanselmann
  for line in data:
2716 137161c9 Michael Hanselmann
    args = []
2717 dcbd6288 Guido Trotter
    if line is None:
2718 d0c8c01d Iustin Pop
      line = ["-" for _ in fields]
2719 f1501b3f Michael Hanselmann
    for idx in range(len(fields)):
2720 137161c9 Michael Hanselmann
      if separator is None:
2721 137161c9 Michael Hanselmann
        args.append(mlens[idx])
2722 137161c9 Michael Hanselmann
      args.append(line[idx])
2723 c04bc777 Iustin Pop
    result.append(format_str % tuple(args))
2724 16be8703 Iustin Pop
2725 16be8703 Iustin Pop
  return result
2726 3386e7a9 Iustin Pop
2727 3386e7a9 Iustin Pop
2728 ee3aedff Michael Hanselmann
def _FormatBool(value):
2729 ee3aedff Michael Hanselmann
  """Formats a boolean value as a string.
2730 ee3aedff Michael Hanselmann

2731 ee3aedff Michael Hanselmann
  """
2732 ee3aedff Michael Hanselmann
  if value:
2733 ee3aedff Michael Hanselmann
    return "Y"
2734 ee3aedff Michael Hanselmann
  return "N"
2735 ee3aedff Michael Hanselmann
2736 ee3aedff Michael Hanselmann
2737 ee3aedff Michael Hanselmann
#: Default formatting for query results; (callback, align right)
2738 ee3aedff Michael Hanselmann
_DEFAULT_FORMAT_QUERY = {
2739 ee3aedff Michael Hanselmann
  constants.QFT_TEXT: (str, False),
2740 ee3aedff Michael Hanselmann
  constants.QFT_BOOL: (_FormatBool, False),
2741 ee3aedff Michael Hanselmann
  constants.QFT_NUMBER: (str, True),
2742 ee3aedff Michael Hanselmann
  constants.QFT_TIMESTAMP: (utils.FormatTime, False),
2743 ee3aedff Michael Hanselmann
  constants.QFT_OTHER: (str, False),
2744 ee3aedff Michael Hanselmann
  constants.QFT_UNKNOWN: (str, False),
2745 ee3aedff Michael Hanselmann
  }
2746 ee3aedff Michael Hanselmann
2747 ee3aedff Michael Hanselmann
2748 ee3aedff Michael Hanselmann
def _GetColumnFormatter(fdef, override, unit):
2749 ee3aedff Michael Hanselmann
  """Returns formatting function for a field.
2750 ee3aedff Michael Hanselmann

2751 ee3aedff Michael Hanselmann
  @type fdef: L{objects.QueryFieldDefinition}
2752 ee3aedff Michael Hanselmann
  @type override: dict
2753 ee3aedff Michael Hanselmann
  @param override: Dictionary for overriding field formatting functions,
2754 ee3aedff Michael Hanselmann
    indexed by field name, contents like L{_DEFAULT_FORMAT_QUERY}
2755 ee3aedff Michael Hanselmann
  @type unit: string
2756 ee3aedff Michael Hanselmann
  @param unit: Unit used for formatting fields of type L{constants.QFT_UNIT}
2757 ee3aedff Michael Hanselmann
  @rtype: tuple; (callable, bool)
2758 ee3aedff Michael Hanselmann
  @return: Returns the function to format a value (takes one parameter) and a
2759 ee3aedff Michael Hanselmann
    boolean for aligning the value on the right-hand side
2760 ee3aedff Michael Hanselmann

2761 ee3aedff Michael Hanselmann
  """
2762 ee3aedff Michael Hanselmann
  fmt = override.get(fdef.name, None)
2763 ee3aedff Michael Hanselmann
  if fmt is not None:
2764 ee3aedff Michael Hanselmann
    return fmt
2765 ee3aedff Michael Hanselmann
2766 ee3aedff Michael Hanselmann
  assert constants.QFT_UNIT not in _DEFAULT_FORMAT_QUERY
2767 ee3aedff Michael Hanselmann
2768 ee3aedff Michael Hanselmann
  if fdef.kind == constants.QFT_UNIT:
2769 ee3aedff Michael Hanselmann
    # Can't keep this information in the static dictionary
2770 ee3aedff Michael Hanselmann
    return (lambda value: utils.FormatUnit(value, unit), True)
2771 ee3aedff Michael Hanselmann
2772 ee3aedff Michael Hanselmann
  fmt = _DEFAULT_FORMAT_QUERY.get(fdef.kind, None)
2773 ee3aedff Michael Hanselmann
  if fmt is not None:
2774 ee3aedff Michael Hanselmann
    return fmt
2775 ee3aedff Michael Hanselmann
2776 ee3aedff Michael Hanselmann
  raise NotImplementedError("Can't format column type '%s'" % fdef.kind)
2777 ee3aedff Michael Hanselmann
2778 ee3aedff Michael Hanselmann
2779 ee3aedff Michael Hanselmann
class _QueryColumnFormatter:
2780 ee3aedff Michael Hanselmann
  """Callable class for formatting fields of a query.
2781 ee3aedff Michael Hanselmann

2782 ee3aedff Michael Hanselmann
  """
2783 f0b1bafe Iustin Pop
  def __init__(self, fn, status_fn, verbose):
2784 ee3aedff Michael Hanselmann
    """Initializes this class.
2785 ee3aedff Michael Hanselmann

2786 ee3aedff Michael Hanselmann
    @type fn: callable
2787 ee3aedff Michael Hanselmann
    @param fn: Formatting function
2788 ee3aedff Michael Hanselmann
    @type status_fn: callable
2789 ee3aedff Michael Hanselmann
    @param status_fn: Function to report fields' status
2790 f0b1bafe Iustin Pop
    @type verbose: boolean
2791 f0b1bafe Iustin Pop
    @param verbose: whether to use verbose field descriptions or not
2792 ee3aedff Michael Hanselmann

2793 ee3aedff Michael Hanselmann
    """
2794 ee3aedff Michael Hanselmann
    self._fn = fn
2795 ee3aedff Michael Hanselmann
    self._status_fn = status_fn
2796 cbfa4f0f Michael Hanselmann
    self._verbose = verbose
2797 ee3aedff Michael Hanselmann
2798 ee3aedff Michael Hanselmann
  def __call__(self, data):
2799 ee3aedff Michael Hanselmann
    """Returns a field's string representation.
2800 ee3aedff Michael Hanselmann

2801 ee3aedff Michael Hanselmann
    """
2802 ee3aedff Michael Hanselmann
    (status, value) = data
2803 ee3aedff Michael Hanselmann
2804 ee3aedff Michael Hanselmann
    # Report status
2805 ee3aedff Michael Hanselmann
    self._status_fn(status)
2806 ee3aedff Michael Hanselmann
2807 cfb084ae René Nussbaumer
    if status == constants.RS_NORMAL:
2808 ee3aedff Michael Hanselmann
      return self._fn(value)
2809 ee3aedff Michael Hanselmann
2810 ee3aedff Michael Hanselmann
    assert value is None, \
2811 ee3aedff Michael Hanselmann
           "Found value %r for abnormal status %s" % (value, status)
2812 ee3aedff Michael Hanselmann
2813 f2c6673d Michael Hanselmann
    return FormatResultError(status, self._verbose)
2814 ee3aedff Michael Hanselmann
2815 ee3aedff Michael Hanselmann
2816 f2c6673d Michael Hanselmann
def FormatResultError(status, verbose):
2817 ae95e419 René Nussbaumer
  """Formats result status other than L{constants.RS_NORMAL}.
2818 ee3aedff Michael Hanselmann

2819 ae95e419 René Nussbaumer
  @param status: The result status
2820 f2c6673d Michael Hanselmann
  @type verbose: boolean
2821 f2c6673d Michael Hanselmann
  @param verbose: Whether to return the verbose text
2822 ae95e419 René Nussbaumer
  @return: Text of result status
2823 a6070ef7 Michael Hanselmann

2824 ae95e419 René Nussbaumer
  """
2825 ae95e419 René Nussbaumer
  assert status != constants.RS_NORMAL, \
2826 cbfa4f0f Michael Hanselmann
         "FormatResultError called with status equal to constants.RS_NORMAL"
2827 ae95e419 René Nussbaumer
  try:
2828 cbfa4f0f Michael Hanselmann
    (verbose_text, normal_text) = constants.RSS_DESCRIPTION[status]
2829 ae95e419 René Nussbaumer
  except KeyError:
2830 ee3aedff Michael Hanselmann
    raise NotImplementedError("Unknown status %s" % status)
2831 cbfa4f0f Michael Hanselmann
  else:
2832 cbfa4f0f Michael Hanselmann
    if verbose:
2833 cbfa4f0f Michael Hanselmann
      return verbose_text
2834 cbfa4f0f Michael Hanselmann
    return normal_text
2835 ee3aedff Michael Hanselmann
2836 ee3aedff Michael Hanselmann
2837 ee3aedff Michael Hanselmann
def FormatQueryResult(result, unit=None, format_override=None, separator=None,
2838 f0b1bafe Iustin Pop
                      header=False, verbose=False):
2839 ee3aedff Michael Hanselmann
  """Formats data in L{objects.QueryResponse}.
2840 ee3aedff Michael Hanselmann

2841 ee3aedff Michael Hanselmann
  @type result: L{objects.QueryResponse}
2842 ee3aedff Michael Hanselmann
  @param result: result of query operation
2843 ee3aedff Michael Hanselmann
  @type unit: string
2844 ee3aedff Michael Hanselmann
  @param unit: Unit used for formatting fields of type L{constants.QFT_UNIT},
2845 18009c1e Iustin Pop
    see L{utils.text.FormatUnit}
2846 ee3aedff Michael Hanselmann
  @type format_override: dict
2847 ee3aedff Michael Hanselmann
  @param format_override: Dictionary for overriding field formatting functions,
2848 ee3aedff Michael Hanselmann
    indexed by field name, contents like L{_DEFAULT_FORMAT_QUERY}
2849 ee3aedff Michael Hanselmann
  @type separator: string or None
2850 ee3aedff Michael Hanselmann
  @param separator: String used to separate fields
2851 ee3aedff Michael Hanselmann
  @type header: bool
2852 ee3aedff Michael Hanselmann
  @param header: Whether to output header row
2853 f0b1bafe Iustin Pop
  @type verbose: boolean
2854 f0b1bafe Iustin Pop
  @param verbose: whether to use verbose field descriptions or not
2855 ee3aedff Michael Hanselmann

2856 ee3aedff Michael Hanselmann
  """
2857 ee3aedff Michael Hanselmann
  if unit is None:
2858 ee3aedff Michael Hanselmann
    if separator:
2859 ee3aedff Michael Hanselmann
      unit = "m"
2860 ee3aedff Michael Hanselmann
    else:
2861 ee3aedff Michael Hanselmann
      unit = "h"
2862 ee3aedff Michael Hanselmann
2863 ee3aedff Michael Hanselmann
  if format_override is None:
2864 ee3aedff Michael Hanselmann
    format_override = {}
2865 ee3aedff Michael Hanselmann
2866 cfb084ae René Nussbaumer
  stats = dict.fromkeys(constants.RS_ALL, 0)
2867 ee3aedff Michael Hanselmann
2868 ee3aedff Michael Hanselmann
  def _RecordStatus(status):
2869 ee3aedff Michael Hanselmann
    if status in stats:
2870 ee3aedff Michael Hanselmann
      stats[status] += 1
2871 ee3aedff Michael Hanselmann
2872 ee3aedff Michael Hanselmann
  columns = []
2873 ee3aedff Michael Hanselmann
  for fdef in result.fields:
2874 ee3aedff Michael Hanselmann
    assert fdef.title and fdef.name
2875 ee3aedff Michael Hanselmann
    (fn, align_right) = _GetColumnFormatter(fdef, format_override, unit)
2876 ee3aedff Michael Hanselmann
    columns.append(TableColumn(fdef.title,
2877 f0b1bafe Iustin Pop
                               _QueryColumnFormatter(fn, _RecordStatus,
2878 f0b1bafe Iustin Pop
                                                     verbose),
2879 ee3aedff Michael Hanselmann
                               align_right))
2880 ee3aedff Michael Hanselmann
2881 ee3aedff Michael Hanselmann
  table = FormatTable(result.data, columns, header, separator)
2882 ee3aedff Michael Hanselmann
2883 ee3aedff Michael Hanselmann
  # Collect statistics
2884 cfb084ae René Nussbaumer
  assert len(stats) == len(constants.RS_ALL)
2885 ee3aedff Michael Hanselmann
  assert compat.all(count >= 0 for count in stats.values())
2886 ee3aedff Michael Hanselmann
2887 ee3aedff Michael Hanselmann
  # Determine overall status. If there was no data, unknown fields must be
2888 ee3aedff Michael Hanselmann
  # detected via the field definitions.
2889 cfb084ae René Nussbaumer
  if (stats[constants.RS_UNKNOWN] or
2890 ee3aedff Michael Hanselmann
      (not result.data and _GetUnknownFields(result.fields))):
2891 ee3aedff Michael Hanselmann
    status = QR_UNKNOWN
2892 ee3aedff Michael Hanselmann
  elif compat.any(count > 0 for key, count in stats.items()
2893 cfb084ae René Nussbaumer
                  if key != constants.RS_NORMAL):
2894 ee3aedff Michael Hanselmann
    status = QR_INCOMPLETE
2895 ee3aedff Michael Hanselmann
  else:
2896 ee3aedff Michael Hanselmann
    status = QR_NORMAL
2897 ee3aedff Michael Hanselmann
2898 ee3aedff Michael Hanselmann
  return (status, table)
2899 ee3aedff Michael Hanselmann
2900 ee3aedff Michael Hanselmann
2901 ee3aedff Michael Hanselmann
def _GetUnknownFields(fdefs):
2902 ee3aedff Michael Hanselmann
  """Returns list of unknown fields included in C{fdefs}.
2903 ee3aedff Michael Hanselmann

2904 ee3aedff Michael Hanselmann
  @type fdefs: list of L{objects.QueryFieldDefinition}
2905 ee3aedff Michael Hanselmann

2906 ee3aedff Michael Hanselmann
  """
2907 ee3aedff Michael Hanselmann
  return [fdef for fdef in fdefs
2908 ee3aedff Michael Hanselmann
          if fdef.kind == constants.QFT_UNKNOWN]
2909 ee3aedff Michael Hanselmann
2910 ee3aedff Michael Hanselmann
2911 ee3aedff Michael Hanselmann
def _WarnUnknownFields(fdefs):
2912 ee3aedff Michael Hanselmann
  """Prints a warning to stderr if a query included unknown fields.
2913 ee3aedff Michael Hanselmann

2914 ee3aedff Michael Hanselmann
  @type fdefs: list of L{objects.QueryFieldDefinition}
2915 ee3aedff Michael Hanselmann

2916 ee3aedff Michael Hanselmann
  """
2917 ee3aedff Michael Hanselmann
  unknown = _GetUnknownFields(fdefs)
2918 ee3aedff Michael Hanselmann
  if unknown:
2919 ee3aedff Michael Hanselmann
    ToStderr("Warning: Queried for unknown fields %s",
2920 ee3aedff Michael Hanselmann
             utils.CommaJoin(fdef.name for fdef in unknown))
2921 ee3aedff Michael Hanselmann
    return True
2922 ee3aedff Michael Hanselmann
2923 ee3aedff Michael Hanselmann
  return False
2924 ee3aedff Michael Hanselmann
2925 ee3aedff Michael Hanselmann
2926 ee3aedff Michael Hanselmann
def GenericList(resource, fields, names, unit, separator, header, cl=None,
2927 03ec545a Michael Hanselmann
                format_override=None, verbose=False, force_filter=False,
2928 6f287cf3 Iustin Pop
                namefield=None, qfilter=None, isnumeric=False):
2929 ee3aedff Michael Hanselmann
  """Generic implementation for listing all items of a resource.
2930 ee3aedff Michael Hanselmann

2931 abd66bf8 Michael Hanselmann
  @param resource: One of L{constants.QR_VIA_LUXI}
2932 ee3aedff Michael Hanselmann
  @type fields: list of strings
2933 ee3aedff Michael Hanselmann
  @param fields: List of fields to query for
2934 ee3aedff Michael Hanselmann
  @type names: list of strings
2935 ee3aedff Michael Hanselmann
  @param names: Names of items to query for
2936 ee3aedff Michael Hanselmann
  @type unit: string or None
2937 ee3aedff Michael Hanselmann
  @param unit: Unit used for formatting fields of type L{constants.QFT_UNIT} or
2938 ee3aedff Michael Hanselmann
    None for automatic choice (human-readable for non-separator usage,
2939 ee3aedff Michael Hanselmann
    otherwise megabytes); this is a one-letter string
2940 ee3aedff Michael Hanselmann
  @type separator: string or None
2941 ee3aedff Michael Hanselmann
  @param separator: String used to separate fields
2942 ee3aedff Michael Hanselmann
  @type header: bool
2943 ee3aedff Michael Hanselmann
  @param header: Whether to show header row
2944 2928de47 Michael Hanselmann
  @type force_filter: bool
2945 2928de47 Michael Hanselmann
  @param force_filter: Whether to always treat names as filter
2946 ee3aedff Michael Hanselmann
  @type format_override: dict
2947 ee3aedff Michael Hanselmann
  @param format_override: Dictionary for overriding field formatting functions,
2948 ee3aedff Michael Hanselmann
    indexed by field name, contents like L{_DEFAULT_FORMAT_QUERY}
2949 f0b1bafe Iustin Pop
  @type verbose: boolean
2950 f0b1bafe Iustin Pop
  @param verbose: whether to use verbose field descriptions or not
2951 03ec545a Michael Hanselmann
  @type namefield: string
2952 03ec545a Michael Hanselmann
  @param namefield: Name of field to use for simple filters (see
2953 03ec545a Michael Hanselmann
    L{qlang.MakeFilter} for details)
2954 f037e9d7 Michael Hanselmann
  @type qfilter: list or None
2955 f037e9d7 Michael Hanselmann
  @param qfilter: Query filter (in addition to names)
2956 6f287cf3 Iustin Pop
  @param isnumeric: bool
2957 6f287cf3 Iustin Pop
  @param isnumeric: Whether the namefield's type is numeric, and therefore
2958 6f287cf3 Iustin Pop
    any simple filters built by namefield should use integer values to
2959 6f287cf3 Iustin Pop
    reflect that
2960 ee3aedff Michael Hanselmann

2961 ee3aedff Michael Hanselmann
  """
2962 ee3aedff Michael Hanselmann
  if not names:
2963 ee3aedff Michael Hanselmann
    names = None
2964 ee3aedff Michael Hanselmann
2965 6f287cf3 Iustin Pop
  namefilter = qlang.MakeFilter(names, force_filter, namefield=namefield,
2966 6f287cf3 Iustin Pop
                                isnumeric=isnumeric)
2967 f037e9d7 Michael Hanselmann
2968 f037e9d7 Michael Hanselmann
  if qfilter is None:
2969 f037e9d7 Michael Hanselmann
    qfilter = namefilter
2970 f037e9d7 Michael Hanselmann
  elif namefilter is not None:
2971 f037e9d7 Michael Hanselmann
    qfilter = [qlang.OP_AND, namefilter, qfilter]
2972 2928de47 Michael Hanselmann
2973 727274dd Iustin Pop
  if cl is None:
2974 727274dd Iustin Pop
    cl = GetClient()
2975 727274dd Iustin Pop
2976 2e5c33db Iustin Pop
  response = cl.Query(resource, fields, qfilter)
2977 ee3aedff Michael Hanselmann
2978 ee3aedff Michael Hanselmann
  found_unknown = _WarnUnknownFields(response.fields)
2979 ee3aedff Michael Hanselmann
2980 ee3aedff Michael Hanselmann
  (status, data) = FormatQueryResult(response, unit=unit, separator=separator,
2981 ee3aedff Michael Hanselmann
                                     header=header,
2982 f0b1bafe Iustin Pop
                                     format_override=format_override,
2983 f0b1bafe Iustin Pop
                                     verbose=verbose)
2984 ee3aedff Michael Hanselmann
2985 ee3aedff Michael Hanselmann
  for line in data:
2986 ee3aedff Michael Hanselmann
    ToStdout(line)
2987 ee3aedff Michael Hanselmann
2988 ee3aedff Michael Hanselmann
  assert ((found_unknown and status == QR_UNKNOWN) or
2989 ee3aedff Michael Hanselmann
          (not found_unknown and status != QR_UNKNOWN))
2990 ee3aedff Michael Hanselmann
2991 ee3aedff Michael Hanselmann
  if status == QR_UNKNOWN:
2992 ee3aedff Michael Hanselmann
    return constants.EXIT_UNKNOWN_FIELD
2993 ee3aedff Michael Hanselmann
2994 ee3aedff Michael Hanselmann
  # TODO: Should the list command fail if not all data could be collected?
2995 ee3aedff Michael Hanselmann
  return constants.EXIT_SUCCESS
2996 ee3aedff Michael Hanselmann
2997 ee3aedff Michael Hanselmann
2998 ee3aedff Michael Hanselmann
def GenericListFields(resource, fields, separator, header, cl=None):
2999 ee3aedff Michael Hanselmann
  """Generic implementation for listing fields for a resource.
3000 ee3aedff Michael Hanselmann

3001 abd66bf8 Michael Hanselmann
  @param resource: One of L{constants.QR_VIA_LUXI}
3002 ee3aedff Michael Hanselmann
  @type fields: list of strings
3003 ee3aedff Michael Hanselmann
  @param fields: List of fields to query for
3004 ee3aedff Michael Hanselmann
  @type separator: string or None
3005 ee3aedff Michael Hanselmann
  @param separator: String used to separate fields
3006 ee3aedff Michael Hanselmann
  @type header: bool
3007 ee3aedff Michael Hanselmann
  @param header: Whether to show header row
3008 ee3aedff Michael Hanselmann

3009 ee3aedff Michael Hanselmann
  """
3010 ee3aedff Michael Hanselmann
  if cl is None:
3011 ee3aedff Michael Hanselmann
    cl = GetClient()
3012 ee3aedff Michael Hanselmann
3013 ee3aedff Michael Hanselmann
  if not fields:
3014 ee3aedff Michael Hanselmann
    fields = None
3015 ee3aedff Michael Hanselmann
3016 ee3aedff Michael Hanselmann
  response = cl.QueryFields(resource, fields)
3017 ee3aedff Michael Hanselmann
3018 ee3aedff Michael Hanselmann
  found_unknown = _WarnUnknownFields(response.fields)
3019 ee3aedff Michael Hanselmann
3020 ee3aedff Michael Hanselmann
  columns = [
3021 ee3aedff Michael Hanselmann
    TableColumn("Name", str, False),
3022 ee3aedff Michael Hanselmann
    TableColumn("Title", str, False),
3023 ea1440c1 Michael Hanselmann
    TableColumn("Description", str, False),
3024 ee3aedff Michael Hanselmann
    ]
3025 ee3aedff Michael Hanselmann
3026 ea1440c1 Michael Hanselmann
  rows = [[fdef.name, fdef.title, fdef.doc] for fdef in response.fields]
3027 ee3aedff Michael Hanselmann
3028 ee3aedff Michael Hanselmann
  for line in FormatTable(rows, columns, header, separator):
3029 ee3aedff Michael Hanselmann
    ToStdout(line)
3030 ee3aedff Michael Hanselmann
3031 ee3aedff Michael Hanselmann
  if found_unknown:
3032 ee3aedff Michael Hanselmann
    return constants.EXIT_UNKNOWN_FIELD
3033 ee3aedff Michael Hanselmann
3034 ee3aedff Michael Hanselmann
  return constants.EXIT_SUCCESS
3035 ee3aedff Michael Hanselmann
3036 ee3aedff Michael Hanselmann
3037 ee3aedff Michael Hanselmann
class TableColumn:
3038 ee3aedff Michael Hanselmann
  """Describes a column for L{FormatTable}.
3039 ee3aedff Michael Hanselmann

3040 ee3aedff Michael Hanselmann
  """
3041 ee3aedff Michael Hanselmann
  def __init__(self, title, fn, align_right):
3042 ee3aedff Michael Hanselmann
    """Initializes this class.
3043 ee3aedff Michael Hanselmann

3044 ee3aedff Michael Hanselmann
    @type title: string
3045 ee3aedff Michael Hanselmann
    @param title: Column title
3046 ee3aedff Michael Hanselmann
    @type fn: callable
3047 ee3aedff Michael Hanselmann
    @param fn: Formatting function
3048 ee3aedff Michael Hanselmann
    @type align_right: bool
3049 ee3aedff Michael Hanselmann
    @param align_right: Whether to align values on the right-hand side
3050 ee3aedff Michael Hanselmann

3051 ee3aedff Michael Hanselmann
    """
3052 ee3aedff Michael Hanselmann
    self.title = title
3053 ee3aedff Michael Hanselmann
    self.format = fn
3054 ee3aedff Michael Hanselmann
    self.align_right = align_right
3055 ee3aedff Michael Hanselmann
3056 ee3aedff Michael Hanselmann
3057 ee3aedff Michael Hanselmann
def _GetColFormatString(width, align_right):
3058 ee3aedff Michael Hanselmann
  """Returns the format string for a field.
3059 ee3aedff Michael Hanselmann

3060 ee3aedff Michael Hanselmann
  """
3061 ee3aedff Michael Hanselmann
  if align_right:
3062 ee3aedff Michael Hanselmann
    sign = ""
3063 ee3aedff Michael Hanselmann
  else:
3064 ee3aedff Michael Hanselmann
    sign = "-"
3065 ee3aedff Michael Hanselmann
3066 ee3aedff Michael Hanselmann
  return "%%%s%ss" % (sign, width)
3067 ee3aedff Michael Hanselmann
3068 ee3aedff Michael Hanselmann
3069 ee3aedff Michael Hanselmann
def FormatTable(rows, columns, header, separator):
3070 ee3aedff Michael Hanselmann
  """Formats data as a table.
3071 ee3aedff Michael Hanselmann

3072 ee3aedff Michael Hanselmann
  @type rows: list of lists
3073 ee3aedff Michael Hanselmann
  @param rows: Row data, one list per row
3074 ee3aedff Michael Hanselmann
  @type columns: list of L{TableColumn}
3075 ee3aedff Michael Hanselmann
  @param columns: Column descriptions
3076 ee3aedff Michael Hanselmann
  @type header: bool
3077 ee3aedff Michael Hanselmann
  @param header: Whether to show header row
3078 ee3aedff Michael Hanselmann
  @type separator: string or None
3079 ee3aedff Michael Hanselmann
  @param separator: String used to separate columns
3080 ee3aedff Michael Hanselmann

3081 ee3aedff Michael Hanselmann
  """
3082 ee3aedff Michael Hanselmann
  if header:
3083 ee3aedff Michael Hanselmann
    data = [[col.title for col in columns]]
3084 ee3aedff Michael Hanselmann
    colwidth = [len(col.title) for col in columns]
3085 ee3aedff Michael Hanselmann
  else:
3086 ee3aedff Michael Hanselmann
    data = []
3087 ee3aedff Michael Hanselmann
    colwidth = [0 for _ in columns]
3088 ee3aedff Michael Hanselmann
3089 ee3aedff Michael Hanselmann
  # Format row data
3090 ee3aedff Michael Hanselmann
  for row in rows:
3091 ee3aedff Michael Hanselmann
    assert len(row) == len(columns)
3092 ee3aedff Michael Hanselmann
3093 ee3aedff Michael Hanselmann
    formatted = [col.format(value) for value, col in zip(row, columns)]
3094 ee3aedff Michael Hanselmann
3095 ee3aedff Michael Hanselmann
    if separator is None:
3096 ee3aedff Michael Hanselmann
      # Update column widths
3097 ee3aedff Michael Hanselmann
      for idx, (oldwidth, value) in enumerate(zip(colwidth, formatted)):
3098 ee3aedff Michael Hanselmann
        # Modifying a list's items while iterating is fine
3099 ee3aedff Michael Hanselmann
        colwidth[idx] = max(oldwidth, len(value))
3100 ee3aedff Michael Hanselmann
3101 ee3aedff Michael Hanselmann
    data.append(formatted)
3102 ee3aedff Michael Hanselmann
3103 ee3aedff Michael Hanselmann
  if separator is not None:
3104 ee3aedff Michael Hanselmann
    # Return early if a separator is used
3105 ee3aedff Michael Hanselmann
    return [separator.join(row) for row in data]
3106 ee3aedff Michael Hanselmann
3107 ee3aedff Michael Hanselmann
  if columns and not columns[-1].align_right:
3108 ee3aedff Michael Hanselmann
    # Avoid unnecessary spaces at end of line
3109 ee3aedff Michael Hanselmann
    colwidth[-1] = 0
3110 ee3aedff Michael Hanselmann
3111 ee3aedff Michael Hanselmann
  # Build format string
3112 ee3aedff Michael Hanselmann
  fmt = " ".join([_GetColFormatString(width, col.align_right)
3113 ee3aedff Michael Hanselmann
                  for col, width in zip(columns, colwidth)])
3114 ee3aedff Michael Hanselmann
3115 ee3aedff Michael Hanselmann
  return [fmt % tuple(row) for row in data]
3116 ee3aedff Michael Hanselmann
3117 ee3aedff Michael Hanselmann
3118 3386e7a9 Iustin Pop
def FormatTimestamp(ts):
3119 3386e7a9 Iustin Pop
  """Formats a given timestamp.
3120 3386e7a9 Iustin Pop

3121 3386e7a9 Iustin Pop
  @type ts: timestamp
3122 3386e7a9 Iustin Pop
  @param ts: a timeval-type timestamp, a tuple of seconds and microseconds
3123 3386e7a9 Iustin Pop

3124 3386e7a9 Iustin Pop
  @rtype: string
3125 5fcc718f Iustin Pop
  @return: a string with the formatted timestamp
3126 3386e7a9 Iustin Pop

3127 3386e7a9 Iustin Pop
  """
3128 e687ec01 Michael Hanselmann
  if not isinstance(ts, (tuple, list)) or len(ts) != 2:
3129 d0c8c01d Iustin Pop
    return "?"
3130 26a72a48 Michael Hanselmann
3131 26a72a48 Michael Hanselmann
  (sec, usecs) = ts
3132 26a72a48 Michael Hanselmann
  return utils.FormatTime(sec, usecs=usecs)
3133 2241e2b9 Iustin Pop
3134 2241e2b9 Iustin Pop
3135 2241e2b9 Iustin Pop
def ParseTimespec(value):
3136 2241e2b9 Iustin Pop
  """Parse a time specification.
3137 2241e2b9 Iustin Pop

3138 2241e2b9 Iustin Pop
  The following suffixed will be recognized:
3139 2241e2b9 Iustin Pop

3140 2241e2b9 Iustin Pop
    - s: seconds
3141 2241e2b9 Iustin Pop
    - m: minutes
3142 2241e2b9 Iustin Pop
    - h: hours
3143 2241e2b9 Iustin Pop
    - d: day
3144 2241e2b9 Iustin Pop
    - w: weeks
3145 2241e2b9 Iustin Pop

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

3148 2241e2b9 Iustin Pop
  """
3149 2241e2b9 Iustin Pop
  value = str(value)
3150 2241e2b9 Iustin Pop
  if not value:
3151 2cfbc784 Iustin Pop
    raise errors.OpPrereqError("Empty time specification passed",
3152 2cfbc784 Iustin Pop
                               errors.ECODE_INVAL)
3153 2241e2b9 Iustin Pop
  suffix_map = {
3154 d0c8c01d Iustin Pop
    "s": 1,
3155 d0c8c01d Iustin Pop
    "m": 60,
3156 d0c8c01d Iustin Pop
    "h": 3600,
3157 d0c8c01d Iustin Pop
    "d": 86400,
3158 d0c8c01d Iustin Pop
    "w": 604800,
3159 2241e2b9 Iustin Pop
    }
3160 2241e2b9 Iustin Pop
  if value[-1] not in suffix_map:
3161 2241e2b9 Iustin Pop
    try:
3162 2241e2b9 Iustin Pop
      value = int(value)
3163 691744c4 Iustin Pop
    except (TypeError, ValueError):
3164 2cfbc784 Iustin Pop
      raise errors.OpPrereqError("Invalid time specification '%s'" % value,
3165 2cfbc784 Iustin Pop
                                 errors.ECODE_INVAL)
3166 2241e2b9 Iustin Pop
  else:
3167 2241e2b9 Iustin Pop
    multiplier = suffix_map[value[-1]]
3168 2241e2b9 Iustin Pop
    value = value[:-1]
3169 2241e2b9 Iustin Pop
    if not value: # no data left after stripping the suffix
3170 2241e2b9 Iustin Pop
      raise errors.OpPrereqError("Invalid time specification (only"
3171 2cfbc784 Iustin Pop
                                 " suffix passed)", errors.ECODE_INVAL)
3172 2241e2b9 Iustin Pop
    try:
3173 2241e2b9 Iustin Pop
      value = int(value) * multiplier
3174 691744c4 Iustin Pop
    except (TypeError, ValueError):
3175 2cfbc784 Iustin Pop
      raise errors.OpPrereqError("Invalid time specification '%s'" % value,
3176 2cfbc784 Iustin Pop
                                 errors.ECODE_INVAL)
3177 2241e2b9 Iustin Pop
  return value
3178 46fbdd04 Iustin Pop
3179 46fbdd04 Iustin Pop
3180 e9e26bb3 Iustin Pop
def GetOnlineNodes(nodes, cl=None, nowarn=False, secondary_ips=False,
3181 05484a24 Michael Hanselmann
                   filter_master=False, nodegroup=None):
3182 4040a784 Iustin Pop
  """Returns the names of online nodes.
3183 4040a784 Iustin Pop

3184 4040a784 Iustin Pop
  This function will also log a warning on stderr with the names of
3185 4040a784 Iustin Pop
  the online nodes.
3186 4040a784 Iustin Pop

3187 4040a784 Iustin Pop
  @param nodes: if not empty, use only this subset of nodes (minus the
3188 4040a784 Iustin Pop
      offline ones)
3189 4040a784 Iustin Pop
  @param cl: if not None, luxi client to use
3190 4040a784 Iustin Pop
  @type nowarn: boolean
3191 4040a784 Iustin Pop
  @param nowarn: by default, this function will output a note with the
3192 4040a784 Iustin Pop
      offline nodes that are skipped; if this parameter is True the
3193 4040a784 Iustin Pop
      note is not displayed
3194 e9e26bb3 Iustin Pop
  @type secondary_ips: boolean
3195 e9e26bb3 Iustin Pop
  @param secondary_ips: if True, return the secondary IPs instead of the
3196 e9e26bb3 Iustin Pop
      names, useful for doing network traffic over the replication interface
3197 e9e26bb3 Iustin Pop
      (if any)
3198 e9e26bb3 Iustin Pop
  @type filter_master: boolean
3199 e9e26bb3 Iustin Pop
  @param filter_master: if True, do not return the master node in the list
3200 e9e26bb3 Iustin Pop
      (useful in coordination with secondary_ips where we cannot check our
3201 e9e26bb3 Iustin Pop
      node name against the list)
3202 05484a24 Michael Hanselmann
  @type nodegroup: string
3203 05484a24 Michael Hanselmann
  @param nodegroup: If set, only return nodes in this node group
3204 4040a784 Iustin Pop

3205 4040a784 Iustin Pop
  """
3206 4040a784 Iustin Pop
  if cl is None:
3207 4040a784 Iustin Pop
    cl = GetClient()
3208 4040a784 Iustin Pop
3209 2e5c33db Iustin Pop
  qfilter = []
3210 05484a24 Michael Hanselmann
3211 05484a24 Michael Hanselmann
  if nodes:
3212 2e5c33db Iustin Pop
    qfilter.append(qlang.MakeSimpleFilter("name", nodes))
3213 05484a24 Michael Hanselmann
3214 05484a24 Michael Hanselmann
  if nodegroup is not None:
3215 2e5c33db Iustin Pop
    qfilter.append([qlang.OP_OR, [qlang.OP_EQUAL, "group", nodegroup],
3216 05484a24 Michael Hanselmann
                                 [qlang.OP_EQUAL, "group.uuid", nodegroup]])
3217 e9e26bb3 Iustin Pop
3218 e9e26bb3 Iustin Pop
  if filter_master:
3219 2e5c33db Iustin Pop
    qfilter.append([qlang.OP_NOT, [qlang.OP_TRUE, "master"]])
3220 05484a24 Michael Hanselmann
3221 2e5c33db Iustin Pop
  if qfilter:
3222 2e5c33db Iustin Pop
    if len(qfilter) > 1:
3223 2e5c33db Iustin Pop
      final_filter = [qlang.OP_AND] + qfilter
3224 05484a24 Michael Hanselmann
    else:
3225 2e5c33db Iustin Pop
      assert len(qfilter) == 1
3226 2e5c33db Iustin Pop
      final_filter = qfilter[0]
3227 e9e26bb3 Iustin Pop
  else:
3228 05484a24 Michael Hanselmann
    final_filter = None
3229 05484a24 Michael Hanselmann
3230 05484a24 Michael Hanselmann
  result = cl.Query(constants.QR_NODE, ["name", "offline", "sip"], final_filter)
3231 05484a24 Michael Hanselmann
3232 05484a24 Michael Hanselmann
  def _IsOffline(row):
3233 05484a24 Michael Hanselmann
    (_, (_, offline), _) = row
3234 05484a24 Michael Hanselmann
    return offline
3235 05484a24 Michael Hanselmann
3236 05484a24 Michael Hanselmann
  def _GetName(row):
3237 05484a24 Michael Hanselmann
    ((_, name), _, _) = row
3238 05484a24 Michael Hanselmann
    return name
3239 05484a24 Michael Hanselmann
3240 05484a24 Michael Hanselmann
  def _GetSip(row):
3241 05484a24 Michael Hanselmann
    (_, _, (_, sip)) = row
3242 05484a24 Michael Hanselmann
    return sip
3243 05484a24 Michael Hanselmann
3244 05484a24 Michael Hanselmann
  (offline, online) = compat.partition(result.data, _IsOffline)
3245 e9e26bb3 Iustin Pop
3246 4040a784 Iustin Pop
  if offline and not nowarn:
3247 05484a24 Michael Hanselmann
    ToStderr("Note: skipping offline node(s): %s" %
3248 05484a24 Michael Hanselmann
             utils.CommaJoin(map(_GetName, offline)))
3249 05484a24 Michael Hanselmann
3250 05484a24 Michael Hanselmann
  if secondary_ips:
3251 05484a24 Michael Hanselmann
    fn = _GetSip
3252 05484a24 Michael Hanselmann
  else:
3253 05484a24 Michael Hanselmann
    fn = _GetName
3254 05484a24 Michael Hanselmann
3255 05484a24 Michael Hanselmann
  return map(fn, online)
3256 4040a784 Iustin Pop
3257 4040a784 Iustin Pop
3258 46fbdd04 Iustin Pop
def _ToStream(stream, txt, *args):
3259 46fbdd04 Iustin Pop
  """Write a message to a stream, bypassing the logging system
3260 46fbdd04 Iustin Pop

3261 46fbdd04 Iustin Pop
  @type stream: file object
3262 46fbdd04 Iustin Pop
  @param stream: the file to which we should write
3263 46fbdd04 Iustin Pop
  @type txt: str
3264 46fbdd04 Iustin Pop
  @param txt: the message
3265 46fbdd04 Iustin Pop

3266 46fbdd04 Iustin Pop
  """
3267 225e2544 Iustin Pop
  try:
3268 225e2544 Iustin Pop
    if args:
3269 225e2544 Iustin Pop
      args = tuple(args)
3270 225e2544 Iustin Pop
      stream.write(txt % args)
3271 225e2544 Iustin Pop
    else:
3272 225e2544 Iustin Pop
      stream.write(txt)
3273 d0c8c01d Iustin Pop
    stream.write("\n")
3274 225e2544 Iustin Pop
    stream.flush()
3275 225e2544 Iustin Pop
  except IOError, err:
3276 225e2544 Iustin Pop
    if err.errno == errno.EPIPE:
3277 225e2544 Iustin Pop
      # our terminal went away, we'll exit
3278 225e2544 Iustin Pop
      sys.exit(constants.EXIT_FAILURE)
3279 225e2544 Iustin Pop
    else:
3280 225e2544 Iustin Pop
      raise
3281 46fbdd04 Iustin Pop
3282 46fbdd04 Iustin Pop
3283 46fbdd04 Iustin Pop
def ToStdout(txt, *args):
3284 46fbdd04 Iustin Pop
  """Write a message to stdout only, bypassing the logging system
3285 46fbdd04 Iustin Pop

3286 46fbdd04 Iustin Pop
  This is just a wrapper over _ToStream.
3287 46fbdd04 Iustin Pop

3288 46fbdd04 Iustin Pop
  @type txt: str
3289 46fbdd04 Iustin Pop
  @param txt: the message
3290 46fbdd04 Iustin Pop

3291 46fbdd04 Iustin Pop
  """
3292 46fbdd04 Iustin Pop
  _ToStream(sys.stdout, txt, *args)
3293 46fbdd04 Iustin Pop
3294 46fbdd04 Iustin Pop
3295 46fbdd04 Iustin Pop
def ToStderr(txt, *args):
3296 46fbdd04 Iustin Pop
  """Write a message to stderr only, bypassing the logging system
3297 46fbdd04 Iustin Pop

3298 46fbdd04 Iustin Pop
  This is just a wrapper over _ToStream.
3299 46fbdd04 Iustin Pop

3300 46fbdd04 Iustin Pop
  @type txt: str
3301 46fbdd04 Iustin Pop
  @param txt: the message
3302 46fbdd04 Iustin Pop

3303 46fbdd04 Iustin Pop
  """
3304 46fbdd04 Iustin Pop
  _ToStream(sys.stderr, txt, *args)
3305 479636a3 Iustin Pop
3306 479636a3 Iustin Pop
3307 479636a3 Iustin Pop
class JobExecutor(object):
3308 479636a3 Iustin Pop
  """Class which manages the submission and execution of multiple jobs.
3309 479636a3 Iustin Pop

3310 479636a3 Iustin Pop
  Note that instances of this class should not be reused between
3311 479636a3 Iustin Pop
  GetResults() calls.
3312 479636a3 Iustin Pop

3313 479636a3 Iustin Pop
  """
3314 919ca415 Iustin Pop
  def __init__(self, cl=None, verbose=True, opts=None, feedback_fn=None):
3315 479636a3 Iustin Pop
    self.queue = []
3316 479636a3 Iustin Pop
    if cl is None:
3317 479636a3 Iustin Pop
      cl = GetClient()
3318 479636a3 Iustin Pop
    self.cl = cl
3319 479636a3 Iustin Pop
    self.verbose = verbose
3320 23b4b983 Iustin Pop
    self.jobs = []
3321 cff5fa7f Iustin Pop
    self.opts = opts
3322 919ca415 Iustin Pop
    self.feedback_fn = feedback_fn
3323 60452edf Michael Hanselmann
    self._counter = itertools.count()
3324 479636a3 Iustin Pop
3325 8d99a8bf Michael Hanselmann
  @staticmethod
3326 8d99a8bf Michael Hanselmann
  def _IfName(name, fmt):
3327 8d99a8bf Michael Hanselmann
    """Helper function for formatting name.
3328 8d99a8bf Michael Hanselmann

3329 8d99a8bf Michael Hanselmann
    """
3330 8d99a8bf Michael Hanselmann
    if name:
3331 8d99a8bf Michael Hanselmann
      return fmt % name
3332 8d99a8bf Michael Hanselmann
3333 8d99a8bf Michael Hanselmann
    return ""
3334 8d99a8bf Michael Hanselmann
3335 479636a3 Iustin Pop
  def QueueJob(self, name, *ops):
3336 23b4b983 Iustin Pop
    """Record a job for later submit.
3337 479636a3 Iustin Pop

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

3341 479636a3 Iustin Pop
    """
3342 cff5fa7f Iustin Pop
    SetGenericOpcodeOpts(ops, self.opts)
3343 60452edf Michael Hanselmann
    self.queue.append((self._counter.next(), name, ops))
3344 23b4b983 Iustin Pop
3345 8d99a8bf Michael Hanselmann
  def AddJobId(self, name, status, job_id):
3346 8d99a8bf Michael Hanselmann
    """Adds a job ID to the internal queue.
3347 8d99a8bf Michael Hanselmann

3348 8d99a8bf Michael Hanselmann
    """
3349 8d99a8bf Michael Hanselmann
    self.jobs.append((self._counter.next(), status, job_id, name))
3350 8d99a8bf Michael Hanselmann
3351 66ecc479 Guido Trotter
  def SubmitPending(self, each=False):
3352 23b4b983 Iustin Pop
    """Submit all pending jobs.
3353 23b4b983 Iustin Pop

3354 23b4b983 Iustin Pop
    """
3355 66ecc479 Guido Trotter
    if each:
3356 66ecc479 Guido Trotter
      results = []
3357 60452edf Michael Hanselmann
      for (_, _, ops) in self.queue:
3358 66ecc479 Guido Trotter
        # SubmitJob will remove the success status, but raise an exception if
3359 66ecc479 Guido Trotter
        # the submission fails, so we'll notice that anyway.
3360 519fafa1 Andrea Spadaccini
        results.append([True, self.cl.SubmitJob(ops)[0]])
3361 66ecc479 Guido Trotter
    else:
3362 60452edf Michael Hanselmann
      results = self.cl.SubmitManyJobs([ops for (_, _, ops) in self.queue])
3363 60452edf Michael Hanselmann
    for ((status, data), (idx, name, _)) in zip(results, self.queue):
3364 5299e61f Iustin Pop
      self.jobs.append((idx, status, data, name))
3365 5299e61f Iustin Pop
3366 5299e61f Iustin Pop
  def _ChooseJob(self):
3367 5299e61f Iustin Pop
    """Choose a non-waiting/queued job to poll next.
3368 5299e61f Iustin Pop

3369 5299e61f Iustin Pop
    """
3370 5299e61f Iustin Pop
    assert self.jobs, "_ChooseJob called with empty job list"
3371 5299e61f Iustin Pop
3372 11705e3d Iustin Pop
    result = self.cl.QueryJobs([i[2] for i in self.jobs[:_CHOOSE_BATCH]],
3373 11705e3d Iustin Pop
                               ["status"])
3374 5299e61f Iustin Pop
    assert result
3375 5299e61f Iustin Pop
3376 5299e61f Iustin Pop
    for job_data, status in zip(self.jobs, result):
3377 91c622a8 Iustin Pop
      if (isinstance(status, list) and status and
3378 91c622a8 Iustin Pop
          status[0] in (constants.JOB_STATUS_QUEUED,
3379 47099cd1 Michael Hanselmann
                        constants.JOB_STATUS_WAITING,
3380 91c622a8 Iustin Pop
                        constants.JOB_STATUS_CANCELING)):
3381 91c622a8 Iustin Pop
        # job is still present and waiting
3382 5299e61f Iustin Pop
        continue
3383 91c622a8 Iustin Pop
      # good candidate found (either running job or lost job)
3384 5299e61f Iustin Pop
      self.jobs.remove(job_data)
3385 5299e61f Iustin Pop
      return job_data
3386 5299e61f Iustin Pop
3387 5299e61f Iustin Pop
    # no job found
3388 5299e61f Iustin Pop
    return self.jobs.pop(0)
3389 479636a3 Iustin Pop
3390 479636a3 Iustin Pop
  def GetResults(self):
3391 479636a3 Iustin Pop
    """Wait for and return the results of all jobs.
3392 479636a3 Iustin Pop

3393 479636a3 Iustin Pop
    @rtype: list
3394 479636a3 Iustin Pop
    @return: list of tuples (success, job results), in the same order
3395 479636a3 Iustin Pop
        as the submitted jobs; if a job has failed, instead of the result
3396 479636a3 Iustin Pop
        there will be the error message
3397 479636a3 Iustin Pop

3398 479636a3 Iustin Pop
    """
3399 23b4b983 Iustin Pop
    if not self.jobs:
3400 23b4b983 Iustin Pop
      self.SubmitPending()
3401 479636a3 Iustin Pop
    results = []
3402 479636a3 Iustin Pop
    if self.verbose:
3403 5299e61f Iustin Pop
      ok_jobs = [row[2] for row in self.jobs if row[1]]
3404 23b4b983 Iustin Pop
      if ok_jobs:
3405 4474f112 Iustin Pop
        ToStdout("Submitted jobs %s", utils.CommaJoin(ok_jobs))
3406 5299e61f Iustin Pop
3407 5299e61f Iustin Pop
    # first, remove any non-submitted jobs
3408 cea881e5 Michael Hanselmann
    self.jobs, failures = compat.partition(self.jobs, lambda x: x[1])
3409 5299e61f Iustin Pop
    for idx, _, jid, name in failures:
3410 4474f112 Iustin Pop
      ToStderr("Failed to submit job%s: %s", self._IfName(name, " for %s"), jid)
3411 c63355f2 Iustin Pop
      results.append((idx, False, jid))
3412 5299e61f Iustin Pop
3413 5299e61f Iustin Pop
    while self.jobs:
3414 5299e61f Iustin Pop
      (idx, _, jid, name) = self._ChooseJob()
3415 4474f112 Iustin Pop
      ToStdout("Waiting for job %s%s ...", jid, self._IfName(name, " for %s"))
3416 479636a3 Iustin Pop
      try:
3417 919ca415 Iustin Pop
        job_result = PollJob(jid, cl=self.cl, feedback_fn=self.feedback_fn)
3418 479636a3 Iustin Pop
        success = True
3419 91c622a8 Iustin Pop
      except errors.JobLost, err:
3420 91c622a8 Iustin Pop
        _, job_result = FormatError(err)
3421 4474f112 Iustin Pop
        ToStderr("Job %s%s has been archived, cannot check its result",
3422 4474f112 Iustin Pop
                 jid, self._IfName(name, " for %s"))
3423 91c622a8 Iustin Pop
        success = False
3424 479636a3 Iustin Pop
      except (errors.GenericError, luxi.ProtocolError), err:
3425 479636a3 Iustin Pop
        _, job_result = FormatError(err)
3426 479636a3 Iustin Pop
        success = False
3427 479636a3 Iustin Pop
        # the error message will always be shown, verbose or not
3428 4474f112 Iustin Pop
        ToStderr("Job %s%s has failed: %s",
3429 4474f112 Iustin Pop
                 jid, self._IfName(name, " for %s"), job_result)
3430 479636a3 Iustin Pop
3431 5299e61f Iustin Pop
      results.append((idx, success, job_result))
3432 5299e61f Iustin Pop
3433 5299e61f Iustin Pop
    # sort based on the index, then drop it
3434 5299e61f Iustin Pop
    results.sort()
3435 5299e61f Iustin Pop
    results = [i[1:] for i in results]
3436 5299e61f Iustin Pop
3437 479636a3 Iustin Pop
    return results
3438 479636a3 Iustin Pop
3439 479636a3 Iustin Pop
  def WaitOrShow(self, wait):
3440 479636a3 Iustin Pop
    """Wait for job results or only print the job IDs.
3441 479636a3 Iustin Pop

3442 479636a3 Iustin Pop
    @type wait: boolean
3443 479636a3 Iustin Pop
    @param wait: whether to wait or not
3444 479636a3 Iustin Pop

3445 479636a3 Iustin Pop
    """
3446 479636a3 Iustin Pop
    if wait:
3447 479636a3 Iustin Pop
      return self.GetResults()
3448 479636a3 Iustin Pop
    else:
3449 23b4b983 Iustin Pop
      if not self.jobs:
3450 23b4b983 Iustin Pop
        self.SubmitPending()
3451 71834b2a Guido Trotter
      for _, status, result, name in self.jobs:
3452 23b4b983 Iustin Pop
        if status:
3453 4474f112 Iustin Pop
          ToStdout("%s: %s", result, name)
3454 23b4b983 Iustin Pop
        else:
3455 4474f112 Iustin Pop
          ToStderr("Failure for %s: %s", name, result)
3456 53a8a54d Iustin Pop
      return [row[1:3] for row in self.jobs]
3457 acd19189 René Nussbaumer
3458 acd19189 René Nussbaumer
3459 acd19189 René Nussbaumer
def FormatParameterDict(buf, param_dict, actual, level=1):
3460 acd19189 René Nussbaumer
  """Formats a parameter dictionary.
3461 acd19189 René Nussbaumer

3462 acd19189 René Nussbaumer
  @type buf: L{StringIO}
3463 acd19189 René Nussbaumer
  @param buf: the buffer into which to write
3464 acd19189 René Nussbaumer
  @type param_dict: dict
3465 acd19189 René Nussbaumer
  @param param_dict: the own parameters
3466 acd19189 René Nussbaumer
  @type actual: dict
3467 acd19189 René Nussbaumer
  @param actual: the current parameter set (including defaults)
3468 acd19189 René Nussbaumer
  @param level: Level of indent
3469 acd19189 René Nussbaumer

3470 acd19189 René Nussbaumer
  """
3471 acd19189 René Nussbaumer
  indent = "  " * level
3472 64da5a53 René Nussbaumer
3473 acd19189 René Nussbaumer
  for key in sorted(actual):
3474 64da5a53 René Nussbaumer
    data = actual[key]
3475 64da5a53 René Nussbaumer
    buf.write("%s- %s:" % (indent, key))
3476 64da5a53 René Nussbaumer
3477 64da5a53 René Nussbaumer
    if isinstance(data, dict) and data:
3478 64da5a53 René Nussbaumer
      buf.write("\n")
3479 64da5a53 René Nussbaumer
      FormatParameterDict(buf, param_dict.get(key, {}), data,
3480 64da5a53 René Nussbaumer
                          level=level + 1)
3481 64da5a53 René Nussbaumer
    else:
3482 64da5a53 René Nussbaumer
      val = param_dict.get(key, "default (%s)" % data)
3483 64da5a53 René Nussbaumer
      buf.write(" %s\n" % val)
3484 25bd815c René Nussbaumer
3485 25bd815c René Nussbaumer
3486 25bd815c René Nussbaumer
def ConfirmOperation(names, list_type, text, extra=""):
3487 25bd815c René Nussbaumer
  """Ask the user to confirm an operation on a list of list_type.
3488 25bd815c René Nussbaumer

3489 25bd815c René Nussbaumer
  This function is used to request confirmation for doing an operation
3490 25bd815c René Nussbaumer
  on a given list of list_type.
3491 25bd815c René Nussbaumer

3492 25bd815c René Nussbaumer
  @type names: list
3493 25bd815c René Nussbaumer
  @param names: the list of names that we display when
3494 25bd815c René Nussbaumer
      we ask for confirmation
3495 25bd815c René Nussbaumer
  @type list_type: str
3496 25bd815c René Nussbaumer
  @param list_type: Human readable name for elements in the list (e.g. nodes)
3497 25bd815c René Nussbaumer
  @type text: str
3498 25bd815c René Nussbaumer
  @param text: the operation that the user should confirm
3499 25bd815c René Nussbaumer
  @rtype: boolean
3500 25bd815c René Nussbaumer
  @return: True or False depending on user's confirmation.
3501 25bd815c René Nussbaumer

3502 25bd815c René Nussbaumer
  """
3503 25bd815c René Nussbaumer
  count = len(names)
3504 25bd815c René Nussbaumer
  msg = ("The %s will operate on %d %s.\n%s"
3505 25bd815c René Nussbaumer
         "Do you want to continue?" % (text, count, list_type, extra))
3506 25bd815c René Nussbaumer
  affected = (("\nAffected %s:\n" % list_type) +
3507 25bd815c René Nussbaumer
              "\n".join(["  %s" % name for name in names]))
3508 25bd815c René Nussbaumer
3509 25bd815c René Nussbaumer
  choices = [("y", True, "Yes, execute the %s" % text),
3510 25bd815c René Nussbaumer
             ("n", False, "No, abort the %s" % text)]
3511 25bd815c René Nussbaumer
3512 25bd815c René Nussbaumer
  if count > 20:
3513 25bd815c René Nussbaumer
    choices.insert(1, ("v", "v", "View the list of affected %s" % list_type))
3514 25bd815c René Nussbaumer
    question = msg
3515 25bd815c René Nussbaumer
  else:
3516 25bd815c René Nussbaumer
    question = msg + affected
3517 25bd815c René Nussbaumer
3518 25bd815c René Nussbaumer
  choice = AskUser(question, choices)
3519 25bd815c René Nussbaumer
  if choice == "v":
3520 25bd815c René Nussbaumer
    choices.pop(1)
3521 25bd815c René Nussbaumer
    choice = AskUser(msg + affected, choices)
3522 25bd815c René Nussbaumer
  return choice
3523 703fa9ab Iustin Pop
3524 703fa9ab Iustin Pop
3525 cd415612 René Nussbaumer
def _MaybeParseUnit(elements):
3526 cd415612 René Nussbaumer
  """Parses and returns an array of potential values with units.
3527 cd415612 René Nussbaumer

3528 cd415612 René Nussbaumer
  """
3529 ef40c537 René Nussbaumer
  parsed = {}
3530 ef40c537 René Nussbaumer
  for k, v in elements.items():
3531 ef40c537 René Nussbaumer
    if v == constants.VALUE_DEFAULT:
3532 ef40c537 René Nussbaumer
      parsed[k] = v
3533 cd415612 René Nussbaumer
    else:
3534 ef40c537 René Nussbaumer
      parsed[k] = utils.ParseUnit(v)
3535 cd415612 René Nussbaumer
  return parsed
3536 cd415612 René Nussbaumer
3537 cd415612 René Nussbaumer
3538 703fa9ab Iustin Pop
def CreateIPolicyFromOpts(ispecs_mem_size=None,
3539 703fa9ab Iustin Pop
                          ispecs_cpu_count=None,
3540 703fa9ab Iustin Pop
                          ispecs_disk_count=None,
3541 703fa9ab Iustin Pop
                          ispecs_disk_size=None,
3542 703fa9ab Iustin Pop
                          ispecs_nic_count=None,
3543 703fa9ab Iustin Pop
                          ipolicy_disk_templates=None,
3544 703fa9ab Iustin Pop
                          ipolicy_vcpu_ratio=None,
3545 ad5cc6bd René Nussbaumer
                          ipolicy_spindle_ratio=None,
3546 703fa9ab Iustin Pop
                          group_ipolicy=False,
3547 703fa9ab Iustin Pop
                          allowed_values=None,
3548 703fa9ab Iustin Pop
                          fill_all=False):
3549 703fa9ab Iustin Pop
  """Creation of instance policy based on command line options.
3550 703fa9ab Iustin Pop

3551 703fa9ab Iustin Pop
  @param fill_all: whether for cluster policies we should ensure that
3552 703fa9ab Iustin Pop
    all values are filled
3553 703fa9ab Iustin Pop

3554 703fa9ab Iustin Pop

3555 703fa9ab Iustin Pop
  """
3556 d67e0a94 Iustin Pop
  try:
3557 d67e0a94 Iustin Pop
    if ispecs_mem_size:
3558 cd415612 René Nussbaumer
      ispecs_mem_size = _MaybeParseUnit(ispecs_mem_size)
3559 d67e0a94 Iustin Pop
    if ispecs_disk_size:
3560 cd415612 René Nussbaumer
      ispecs_disk_size = _MaybeParseUnit(ispecs_disk_size)
3561 d67e0a94 Iustin Pop
  except (TypeError, ValueError, errors.UnitParseError), err:
3562 d67e0a94 Iustin Pop
    raise errors.OpPrereqError("Invalid disk (%s) or memory (%s) size"
3563 d67e0a94 Iustin Pop
                               " in policy: %s" %
3564 d67e0a94 Iustin Pop
                               (ispecs_disk_size, ispecs_mem_size, err),
3565 d67e0a94 Iustin Pop
                               errors.ECODE_INVAL)
3566 d67e0a94 Iustin Pop
3567 703fa9ab Iustin Pop
  # prepare ipolicy dict
3568 703fa9ab Iustin Pop
  ipolicy_transposed = {
3569 703fa9ab Iustin Pop
    constants.ISPEC_MEM_SIZE: ispecs_mem_size,
3570 703fa9ab Iustin Pop
    constants.ISPEC_CPU_COUNT: ispecs_cpu_count,
3571 703fa9ab Iustin Pop
    constants.ISPEC_DISK_COUNT: ispecs_disk_count,
3572 703fa9ab Iustin Pop
    constants.ISPEC_DISK_SIZE: ispecs_disk_size,
3573 703fa9ab Iustin Pop
    constants.ISPEC_NIC_COUNT: ispecs_nic_count,
3574 703fa9ab Iustin Pop
    }
3575 703fa9ab Iustin Pop
3576 703fa9ab Iustin Pop
  # first, check that the values given are correct
3577 703fa9ab Iustin Pop
  if group_ipolicy:
3578 703fa9ab Iustin Pop
    forced_type = TISPECS_GROUP_TYPES
3579 703fa9ab Iustin Pop
  else:
3580 703fa9ab Iustin Pop
    forced_type = TISPECS_CLUSTER_TYPES
3581 703fa9ab Iustin Pop
3582 703fa9ab Iustin Pop
  for specs in ipolicy_transposed.values():
3583 703fa9ab Iustin Pop
    utils.ForceDictType(specs, forced_type, allowed_values=allowed_values)
3584 703fa9ab Iustin Pop
3585 703fa9ab Iustin Pop
  # then transpose
3586 703fa9ab Iustin Pop
  ipolicy_out = objects.MakeEmptyIPolicy()
3587 703fa9ab Iustin Pop
  for name, specs in ipolicy_transposed.iteritems():
3588 703fa9ab Iustin Pop
    assert name in constants.ISPECS_PARAMETERS
3589 703fa9ab Iustin Pop
    for key, val in specs.items(): # {min: .. ,max: .., std: ..}
3590 703fa9ab Iustin Pop
      ipolicy_out[key][name] = val
3591 703fa9ab Iustin Pop
3592 703fa9ab Iustin Pop
  # no filldict for non-dicts
3593 703fa9ab Iustin Pop
  if not group_ipolicy and fill_all:
3594 703fa9ab Iustin Pop
    if ipolicy_disk_templates is None:
3595 703fa9ab Iustin Pop
      ipolicy_disk_templates = constants.DISK_TEMPLATES
3596 703fa9ab Iustin Pop
    if ipolicy_vcpu_ratio is None:
3597 703fa9ab Iustin Pop
      ipolicy_vcpu_ratio = \
3598 703fa9ab Iustin Pop
        constants.IPOLICY_DEFAULTS[constants.IPOLICY_VCPU_RATIO]
3599 ad5cc6bd René Nussbaumer
    if ipolicy_spindle_ratio is None:
3600 ad5cc6bd René Nussbaumer
      ipolicy_spindle_ratio = \
3601 ad5cc6bd René Nussbaumer
        constants.IPOLICY_DEFAULTS[constants.IPOLICY_SPINDLE_RATIO]
3602 703fa9ab Iustin Pop
  if ipolicy_disk_templates is not None:
3603 703fa9ab Iustin Pop
    ipolicy_out[constants.IPOLICY_DTS] = list(ipolicy_disk_templates)
3604 703fa9ab Iustin Pop
  if ipolicy_vcpu_ratio is not None:
3605 703fa9ab Iustin Pop
    ipolicy_out[constants.IPOLICY_VCPU_RATIO] = ipolicy_vcpu_ratio
3606 ad5cc6bd René Nussbaumer
  if ipolicy_spindle_ratio is not None:
3607 ad5cc6bd René Nussbaumer
    ipolicy_out[constants.IPOLICY_SPINDLE_RATIO] = ipolicy_spindle_ratio
3608 703fa9ab Iustin Pop
3609 703fa9ab Iustin Pop
  assert not (frozenset(ipolicy_out.keys()) - constants.IPOLICY_ALL_KEYS)
3610 703fa9ab Iustin Pop
3611 703fa9ab Iustin Pop
  return ipolicy_out