Statistics
| Branch: | Tag: | Revision:

root / lib / cli.py @ 7f5edc60

History | View | Annotate | Download (121.8 kB)

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

345 863d7f46 Michael Hanselmann
  Value can be any of the ones passed to the constructor.
346 863d7f46 Michael Hanselmann

347 863d7f46 Michael Hanselmann
  """
348 b459a848 Andrea Spadaccini
  # pylint: disable=W0622
349 863d7f46 Michael Hanselmann
  def __init__(self, min=0, max=None, choices=None):
350 863d7f46 Michael Hanselmann
    _Argument.__init__(self, min=min, max=max)
351 863d7f46 Michael Hanselmann
    self.choices = choices
352 863d7f46 Michael Hanselmann
353 863d7f46 Michael Hanselmann
  def __repr__(self):
354 863d7f46 Michael Hanselmann
    return ("<%s min=%s max=%s choices=%r>" %
355 863d7f46 Michael Hanselmann
            (self.__class__.__name__, self.min, self.max, self.choices))
356 863d7f46 Michael Hanselmann
357 863d7f46 Michael Hanselmann
358 863d7f46 Michael Hanselmann
class ArgChoice(ArgSuggest):
359 863d7f46 Michael Hanselmann
  """Choice argument.
360 863d7f46 Michael Hanselmann

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

364 863d7f46 Michael Hanselmann
  """
365 863d7f46 Michael Hanselmann
366 863d7f46 Michael Hanselmann
367 863d7f46 Michael Hanselmann
class ArgUnknown(_Argument):
368 863d7f46 Michael Hanselmann
  """Unknown argument to program (e.g. determined at runtime).
369 863d7f46 Michael Hanselmann

370 863d7f46 Michael Hanselmann
  """
371 863d7f46 Michael Hanselmann
372 863d7f46 Michael Hanselmann
373 863d7f46 Michael Hanselmann
class ArgInstance(_Argument):
374 863d7f46 Michael Hanselmann
  """Instances argument.
375 863d7f46 Michael Hanselmann

376 863d7f46 Michael Hanselmann
  """
377 863d7f46 Michael Hanselmann
378 863d7f46 Michael Hanselmann
379 863d7f46 Michael Hanselmann
class ArgNode(_Argument):
380 863d7f46 Michael Hanselmann
  """Node argument.
381 863d7f46 Michael Hanselmann

382 863d7f46 Michael Hanselmann
  """
383 863d7f46 Michael Hanselmann
384 667dbd6b Adeodato Simo
385 9c784fb3 Dimitris Aragiorgis
class ArgNetwork(_Argument):
386 9c784fb3 Dimitris Aragiorgis
  """Network argument.
387 9c784fb3 Dimitris Aragiorgis

388 9c784fb3 Dimitris Aragiorgis
  """
389 9c784fb3 Dimitris Aragiorgis
390 3c286190 Dimitris Aragiorgis
391 667dbd6b Adeodato Simo
class ArgGroup(_Argument):
392 667dbd6b Adeodato Simo
  """Node group argument.
393 667dbd6b Adeodato Simo

394 667dbd6b Adeodato Simo
  """
395 667dbd6b Adeodato Simo
396 667dbd6b Adeodato Simo
397 863d7f46 Michael Hanselmann
class ArgJobId(_Argument):
398 863d7f46 Michael Hanselmann
  """Job ID argument.
399 863d7f46 Michael Hanselmann

400 863d7f46 Michael Hanselmann
  """
401 863d7f46 Michael Hanselmann
402 863d7f46 Michael Hanselmann
403 863d7f46 Michael Hanselmann
class ArgFile(_Argument):
404 863d7f46 Michael Hanselmann
  """File path argument.
405 863d7f46 Michael Hanselmann

406 863d7f46 Michael Hanselmann
  """
407 863d7f46 Michael Hanselmann
408 863d7f46 Michael Hanselmann
409 863d7f46 Michael Hanselmann
class ArgCommand(_Argument):
410 863d7f46 Michael Hanselmann
  """Command argument.
411 863d7f46 Michael Hanselmann

412 863d7f46 Michael Hanselmann
  """
413 863d7f46 Michael Hanselmann
414 863d7f46 Michael Hanselmann
415 83ec7961 Michael Hanselmann
class ArgHost(_Argument):
416 83ec7961 Michael Hanselmann
  """Host argument.
417 83ec7961 Michael Hanselmann

418 83ec7961 Michael Hanselmann
  """
419 83ec7961 Michael Hanselmann
420 83ec7961 Michael Hanselmann
421 f9faf9c3 René Nussbaumer
class ArgOs(_Argument):
422 f9faf9c3 René Nussbaumer
  """OS argument.
423 f9faf9c3 René Nussbaumer

424 f9faf9c3 René Nussbaumer
  """
425 f9faf9c3 René Nussbaumer
426 f9faf9c3 René Nussbaumer
427 b954f097 Constantinos Venetsanopoulos
class ArgExtStorage(_Argument):
428 b954f097 Constantinos Venetsanopoulos
  """ExtStorage argument.
429 b954f097 Constantinos Venetsanopoulos

430 b954f097 Constantinos Venetsanopoulos
  """
431 b954f097 Constantinos Venetsanopoulos
432 b954f097 Constantinos Venetsanopoulos
433 4a265c08 Michael Hanselmann
ARGS_NONE = []
434 4a265c08 Michael Hanselmann
ARGS_MANY_INSTANCES = [ArgInstance()]
435 9c784fb3 Dimitris Aragiorgis
ARGS_MANY_NETWORKS = [ArgNetwork()]
436 4a265c08 Michael Hanselmann
ARGS_MANY_NODES = [ArgNode()]
437 667dbd6b Adeodato Simo
ARGS_MANY_GROUPS = [ArgGroup()]
438 4a265c08 Michael Hanselmann
ARGS_ONE_INSTANCE = [ArgInstance(min=1, max=1)]
439 9c784fb3 Dimitris Aragiorgis
ARGS_ONE_NETWORK = [ArgNetwork(min=1, max=1)]
440 4a265c08 Michael Hanselmann
ARGS_ONE_NODE = [ArgNode(min=1, max=1)]
441 dadf6b7d Michael Hanselmann
# TODO
442 dadf6b7d Michael Hanselmann
ARGS_ONE_GROUP = [ArgGroup(min=1, max=1)]
443 f9faf9c3 René Nussbaumer
ARGS_ONE_OS = [ArgOs(min=1, max=1)]
444 4a265c08 Michael Hanselmann
445 4a265c08 Michael Hanselmann
446 846baef9 Iustin Pop
def _ExtractTagsObject(opts, args):
447 846baef9 Iustin Pop
  """Extract the tag type object.
448 846baef9 Iustin Pop

449 846baef9 Iustin Pop
  Note that this function will modify its args parameter.
450 846baef9 Iustin Pop

451 846baef9 Iustin Pop
  """
452 846baef9 Iustin Pop
  if not hasattr(opts, "tag_type"):
453 846baef9 Iustin Pop
    raise errors.ProgrammerError("tag_type not passed to _ExtractTagsObject")
454 846baef9 Iustin Pop
  kind = opts.tag_type
455 846baef9 Iustin Pop
  if kind == constants.TAG_CLUSTER:
456 bcd35e09 Dato Simó
    retval = kind, None
457 819cbfe5 Michael Hanselmann
  elif kind in (constants.TAG_NODEGROUP,
458 819cbfe5 Michael Hanselmann
                constants.TAG_NODE,
459 8140e24f Dimitris Aragiorgis
                constants.TAG_NETWORK,
460 819cbfe5 Michael Hanselmann
                constants.TAG_INSTANCE):
461 846baef9 Iustin Pop
    if not args:
462 2cfbc784 Iustin Pop
      raise errors.OpPrereqError("no arguments passed to the command",
463 2cfbc784 Iustin Pop
                                 errors.ECODE_INVAL)
464 846baef9 Iustin Pop
    name = args.pop(0)
465 846baef9 Iustin Pop
    retval = kind, name
466 846baef9 Iustin Pop
  else:
467 846baef9 Iustin Pop
    raise errors.ProgrammerError("Unhandled tag type '%s'" % kind)
468 846baef9 Iustin Pop
  return retval
469 846baef9 Iustin Pop
470 846baef9 Iustin Pop
471 810c50b7 Iustin Pop
def _ExtendTags(opts, args):
472 810c50b7 Iustin Pop
  """Extend the args if a source file has been given.
473 810c50b7 Iustin Pop

474 810c50b7 Iustin Pop
  This function will extend the tags with the contents of the file
475 810c50b7 Iustin Pop
  passed in the 'tags_source' attribute of the opts parameter. A file
476 810c50b7 Iustin Pop
  named '-' will be replaced by stdin.
477 810c50b7 Iustin Pop

478 810c50b7 Iustin Pop
  """
479 810c50b7 Iustin Pop
  fname = opts.tags_source
480 810c50b7 Iustin Pop
  if fname is None:
481 810c50b7 Iustin Pop
    return
482 810c50b7 Iustin Pop
  if fname == "-":
483 810c50b7 Iustin Pop
    new_fh = sys.stdin
484 810c50b7 Iustin Pop
  else:
485 810c50b7 Iustin Pop
    new_fh = open(fname, "r")
486 810c50b7 Iustin Pop
  new_data = []
487 810c50b7 Iustin Pop
  try:
488 810c50b7 Iustin Pop
    # we don't use the nice 'new_data = [line.strip() for line in fh]'
489 810c50b7 Iustin Pop
    # because of python bug 1633941
490 810c50b7 Iustin Pop
    while True:
491 810c50b7 Iustin Pop
      line = new_fh.readline()
492 810c50b7 Iustin Pop
      if not line:
493 810c50b7 Iustin Pop
        break
494 810c50b7 Iustin Pop
      new_data.append(line.strip())
495 810c50b7 Iustin Pop
  finally:
496 810c50b7 Iustin Pop
    new_fh.close()
497 810c50b7 Iustin Pop
  args.extend(new_data)
498 810c50b7 Iustin Pop
499 810c50b7 Iustin Pop
500 846baef9 Iustin Pop
def ListTags(opts, args):
501 846baef9 Iustin Pop
  """List the tags on a given object.
502 846baef9 Iustin Pop

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

508 846baef9 Iustin Pop
  """
509 846baef9 Iustin Pop
  kind, name = _ExtractTagsObject(opts, args)
510 f2374060 Iustin Pop
  cl = GetClient(query=True)
511 7699c3af Iustin Pop
  result = cl.QueryTags(kind, name)
512 846baef9 Iustin Pop
  result = list(result)
513 846baef9 Iustin Pop
  result.sort()
514 846baef9 Iustin Pop
  for tag in result:
515 03298ebe Michael Hanselmann
    ToStdout(tag)
516 846baef9 Iustin Pop
517 846baef9 Iustin Pop
518 846baef9 Iustin Pop
def AddTags(opts, args):
519 846baef9 Iustin Pop
  """Add tags on a given object.
520 846baef9 Iustin Pop

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

526 846baef9 Iustin Pop
  """
527 846baef9 Iustin Pop
  kind, name = _ExtractTagsObject(opts, args)
528 810c50b7 Iustin Pop
  _ExtendTags(opts, args)
529 846baef9 Iustin Pop
  if not args:
530 2cfbc784 Iustin Pop
    raise errors.OpPrereqError("No tags to be added", errors.ECODE_INVAL)
531 d1602edc Iustin Pop
  op = opcodes.OpTagsSet(kind=kind, name=name, tags=args)
532 6bc3ed14 Michael Hanselmann
  SubmitOrSend(op, opts)
533 846baef9 Iustin Pop
534 846baef9 Iustin Pop
535 846baef9 Iustin Pop
def RemoveTags(opts, args):
536 846baef9 Iustin Pop
  """Remove tags from a given object.
537 846baef9 Iustin Pop

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

543 846baef9 Iustin Pop
  """
544 846baef9 Iustin Pop
  kind, name = _ExtractTagsObject(opts, args)
545 810c50b7 Iustin Pop
  _ExtendTags(opts, args)
546 846baef9 Iustin Pop
  if not args:
547 2cfbc784 Iustin Pop
    raise errors.OpPrereqError("No tags to be removed", errors.ECODE_INVAL)
548 3f0ab95f Iustin Pop
  op = opcodes.OpTagsDel(kind=kind, name=name, tags=args)
549 6bc3ed14 Michael Hanselmann
  SubmitOrSend(op, opts)
550 846baef9 Iustin Pop
551 a8083063 Iustin Pop
552 b459a848 Andrea Spadaccini
def check_unit(option, opt, value): # pylint: disable=W0613
553 65fe4693 Iustin Pop
  """OptParsers custom converter for units.
554 65fe4693 Iustin Pop

555 65fe4693 Iustin Pop
  """
556 a8083063 Iustin Pop
  try:
557 a8083063 Iustin Pop
    return utils.ParseUnit(value)
558 a8083063 Iustin Pop
  except errors.UnitParseError, err:
559 3ecf6786 Iustin Pop
    raise OptionValueError("option %s: %s" % (opt, err))
560 a8083063 Iustin Pop
561 a8083063 Iustin Pop
562 a8469393 Iustin Pop
def _SplitKeyVal(opt, data):
563 a8469393 Iustin Pop
  """Convert a KeyVal string into a dict.
564 a8469393 Iustin Pop

565 a8469393 Iustin Pop
  This function will convert a key=val[,...] string into a dict. Empty
566 a8469393 Iustin Pop
  values will be converted specially: keys which have the prefix 'no_'
567 a8469393 Iustin Pop
  will have the value=False and the prefix stripped, the others will
568 a8469393 Iustin Pop
  have value=True.
569 a8469393 Iustin Pop

570 a8469393 Iustin Pop
  @type opt: string
571 a8469393 Iustin Pop
  @param opt: a string holding the option name for which we process the
572 a8469393 Iustin Pop
      data, used in building error messages
573 a8469393 Iustin Pop
  @type data: string
574 a8469393 Iustin Pop
  @param data: a string of the format key=val,key=val,...
575 a8469393 Iustin Pop
  @rtype: dict
576 a8469393 Iustin Pop
  @return: {key=val, key=val}
577 a8469393 Iustin Pop
  @raises errors.ParameterError: if there are duplicate keys
578 a8469393 Iustin Pop

579 a8469393 Iustin Pop
  """
580 a8469393 Iustin Pop
  kv_dict = {}
581 4f31882e Guido Trotter
  if data:
582 1b3a7656 Iustin Pop
    for elem in utils.UnescapeAndSplit(data, sep=","):
583 4f31882e Guido Trotter
      if "=" in elem:
584 4f31882e Guido Trotter
        key, val = elem.split("=", 1)
585 a8469393 Iustin Pop
      else:
586 4f31882e Guido Trotter
        if elem.startswith(NO_PREFIX):
587 4f31882e Guido Trotter
          key, val = elem[len(NO_PREFIX):], False
588 4f31882e Guido Trotter
        elif elem.startswith(UN_PREFIX):
589 4f31882e Guido Trotter
          key, val = elem[len(UN_PREFIX):], None
590 4f31882e Guido Trotter
        else:
591 4f31882e Guido Trotter
          key, val = elem, True
592 4f31882e Guido Trotter
      if key in kv_dict:
593 4f31882e Guido Trotter
        raise errors.ParameterError("Duplicate key '%s' in option %s" %
594 4f31882e Guido Trotter
                                    (key, opt))
595 4f31882e Guido Trotter
      kv_dict[key] = val
596 a8469393 Iustin Pop
  return kv_dict
597 a8469393 Iustin Pop
598 a8469393 Iustin Pop
599 b459a848 Andrea Spadaccini
def check_ident_key_val(option, opt, value):  # pylint: disable=W0613
600 552c8dff Michael Hanselmann
  """Custom parser for ident:key=val,key=val options.
601 552c8dff Michael Hanselmann

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

605 a8469393 Iustin Pop
  """
606 a8469393 Iustin Pop
  if ":" not in value:
607 d0c8c01d Iustin Pop
    ident, rest = value, ""
608 a8469393 Iustin Pop
  else:
609 a8469393 Iustin Pop
    ident, rest = value.split(":", 1)
610 8b46606c Guido Trotter
611 8b46606c Guido Trotter
  if ident.startswith(NO_PREFIX):
612 8b46606c Guido Trotter
    if rest:
613 8b46606c Guido Trotter
      msg = "Cannot pass options when removing parameter groups: %s" % value
614 8b46606c Guido Trotter
      raise errors.ParameterError(msg)
615 8b46606c Guido Trotter
    retval = (ident[len(NO_PREFIX):], False)
616 956631b6 Michael Hanselmann
  elif (ident.startswith(UN_PREFIX) and
617 956631b6 Michael Hanselmann
        (len(ident) <= len(UN_PREFIX) or
618 956631b6 Michael Hanselmann
         not ident[len(UN_PREFIX)][0].isdigit())):
619 8b46606c Guido Trotter
    if rest:
620 8b46606c Guido Trotter
      msg = "Cannot pass options when removing parameter groups: %s" % value
621 8b46606c Guido Trotter
      raise errors.ParameterError(msg)
622 8b46606c Guido Trotter
    retval = (ident[len(UN_PREFIX):], None)
623 8b46606c Guido Trotter
  else:
624 a8469393 Iustin Pop
    kv_dict = _SplitKeyVal(opt, rest)
625 a8469393 Iustin Pop
    retval = (ident, kv_dict)
626 a8469393 Iustin Pop
  return retval
627 a8469393 Iustin Pop
628 a8469393 Iustin Pop
629 b459a848 Andrea Spadaccini
def check_key_val(option, opt, value):  # pylint: disable=W0613
630 552c8dff Michael Hanselmann
  """Custom parser class for key=val,key=val options.
631 552c8dff Michael Hanselmann

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

634 a8469393 Iustin Pop
  """
635 a8469393 Iustin Pop
  return _SplitKeyVal(opt, value)
636 a8469393 Iustin Pop
637 a8469393 Iustin Pop
638 b459a848 Andrea Spadaccini
def check_bool(option, opt, value): # pylint: disable=W0613
639 e7b61bb0 Iustin Pop
  """Custom parser for yes/no options.
640 e7b61bb0 Iustin Pop

641 e7b61bb0 Iustin Pop
  This will store the parsed value as either True or False.
642 e7b61bb0 Iustin Pop

643 e7b61bb0 Iustin Pop
  """
644 e7b61bb0 Iustin Pop
  value = value.lower()
645 e7b61bb0 Iustin Pop
  if value == constants.VALUE_FALSE or value == "no":
646 e7b61bb0 Iustin Pop
    return False
647 e7b61bb0 Iustin Pop
  elif value == constants.VALUE_TRUE or value == "yes":
648 e7b61bb0 Iustin Pop
    return True
649 e7b61bb0 Iustin Pop
  else:
650 e7b61bb0 Iustin Pop
    raise errors.ParameterError("Invalid boolean value '%s'" % value)
651 e7b61bb0 Iustin Pop
652 e7b61bb0 Iustin Pop
653 499eb088 Iustin Pop
def check_list(option, opt, value): # pylint: disable=W0613
654 499eb088 Iustin Pop
  """Custom parser for comma-separated lists.
655 499eb088 Iustin Pop

656 499eb088 Iustin Pop
  """
657 499eb088 Iustin Pop
  # we have to make this explicit check since "".split(",") is [""],
658 499eb088 Iustin Pop
  # not an empty list :(
659 499eb088 Iustin Pop
  if not value:
660 499eb088 Iustin Pop
    return []
661 499eb088 Iustin Pop
  else:
662 499eb088 Iustin Pop
    return utils.UnescapeAndSplit(value)
663 499eb088 Iustin Pop
664 499eb088 Iustin Pop
665 cd415612 René Nussbaumer
def check_maybefloat(option, opt, value): # pylint: disable=W0613
666 cd415612 René Nussbaumer
  """Custom parser for float numbers which might be also defaults.
667 cd415612 René Nussbaumer

668 cd415612 René Nussbaumer
  """
669 cd415612 René Nussbaumer
  value = value.lower()
670 cd415612 René Nussbaumer
671 cd415612 René Nussbaumer
  if value == constants.VALUE_DEFAULT:
672 cd415612 René Nussbaumer
    return value
673 cd415612 René Nussbaumer
  else:
674 cd415612 René Nussbaumer
    return float(value)
675 cd415612 René Nussbaumer
676 cd415612 René Nussbaumer
677 63d44c55 Michael Hanselmann
# completion_suggestion is normally a list. Using numeric values not evaluating
678 63d44c55 Michael Hanselmann
# to False for dynamic completion.
679 63d44c55 Michael Hanselmann
(OPT_COMPL_MANY_NODES,
680 63d44c55 Michael Hanselmann
 OPT_COMPL_ONE_NODE,
681 63d44c55 Michael Hanselmann
 OPT_COMPL_ONE_INSTANCE,
682 63d44c55 Michael Hanselmann
 OPT_COMPL_ONE_OS,
683 b954f097 Constantinos Venetsanopoulos
 OPT_COMPL_ONE_EXTSTORAGE,
684 2d3ed64b Michael Hanselmann
 OPT_COMPL_ONE_IALLOCATOR,
685 9c784fb3 Dimitris Aragiorgis
 OPT_COMPL_ONE_NETWORK,
686 36e247e1 Guido Trotter
 OPT_COMPL_INST_ADD_NODES,
687 b954f097 Constantinos Venetsanopoulos
 OPT_COMPL_ONE_NODEGROUP) = range(100, 109)
688 63d44c55 Michael Hanselmann
689 b8028dcf Michael Hanselmann
OPT_COMPL_ALL = compat.UniqueFrozenset([
690 63d44c55 Michael Hanselmann
  OPT_COMPL_MANY_NODES,
691 63d44c55 Michael Hanselmann
  OPT_COMPL_ONE_NODE,
692 63d44c55 Michael Hanselmann
  OPT_COMPL_ONE_INSTANCE,
693 63d44c55 Michael Hanselmann
  OPT_COMPL_ONE_OS,
694 b954f097 Constantinos Venetsanopoulos
  OPT_COMPL_ONE_EXTSTORAGE,
695 63d44c55 Michael Hanselmann
  OPT_COMPL_ONE_IALLOCATOR,
696 9c784fb3 Dimitris Aragiorgis
  OPT_COMPL_ONE_NETWORK,
697 2d3ed64b Michael Hanselmann
  OPT_COMPL_INST_ADD_NODES,
698 36e247e1 Guido Trotter
  OPT_COMPL_ONE_NODEGROUP,
699 63d44c55 Michael Hanselmann
  ])
700 63d44c55 Michael Hanselmann
701 63d44c55 Michael Hanselmann
702 552c8dff Michael Hanselmann
class CliOption(Option):
703 552c8dff Michael Hanselmann
  """Custom option class for optparse.
704 a8469393 Iustin Pop

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

1397 552328b8 Michael Hanselmann
  """
1398 552328b8 Michael Hanselmann
  value = _PRIONAME_TO_VALUE[value]
1399 552328b8 Michael Hanselmann
1400 552328b8 Michael Hanselmann
  setattr(parser.values, option.dest, value)
1401 552328b8 Michael Hanselmann
1402 552328b8 Michael Hanselmann
1403 84a5b33c Michael Hanselmann
PRIORITY_OPT = cli_option("--priority", default=None, dest="priority",
1404 84a5b33c Michael Hanselmann
                          metavar="|".join(name for name, _ in _PRIORITY_NAMES),
1405 84a5b33c Michael Hanselmann
                          choices=_PRIONAME_TO_VALUE.keys(),
1406 552328b8 Michael Hanselmann
                          action="callback", type="choice",
1407 552328b8 Michael Hanselmann
                          callback=_PriorityOptionCb,
1408 aa06f8c6 Michael Hanselmann
                          help="Priority for opcode processing")
1409 84a5b33c Michael Hanselmann
1410 61a14bb3 Iustin Pop
HID_OS_OPT = cli_option("--hidden", dest="hidden",
1411 61a14bb3 Iustin Pop
                        type="bool", default=None, metavar=_YORNO,
1412 61a14bb3 Iustin Pop
                        help="Sets the hidden flag on the OS")
1413 61a14bb3 Iustin Pop
1414 61a14bb3 Iustin Pop
BLK_OS_OPT = cli_option("--blacklisted", dest="blacklisted",
1415 61a14bb3 Iustin Pop
                        type="bool", default=None, metavar=_YORNO,
1416 61a14bb3 Iustin Pop
                        help="Sets the blacklisted flag on the OS")
1417 61a14bb3 Iustin Pop
1418 b883637f René Nussbaumer
PREALLOC_WIPE_DISKS_OPT = cli_option("--prealloc-wipe-disks", default=None,
1419 b883637f René Nussbaumer
                                     type="bool", metavar=_YORNO,
1420 b883637f René Nussbaumer
                                     dest="prealloc_wipe_disks",
1421 b883637f René Nussbaumer
                                     help=("Wipe disks prior to instance"
1422 b883637f René Nussbaumer
                                           " creation"))
1423 b883637f René Nussbaumer
1424 a535cef7 René Nussbaumer
NODE_PARAMS_OPT = cli_option("--node-parameters", dest="ndparams",
1425 3c2b6a98 René Nussbaumer
                             type="keyval", default=None,
1426 a535cef7 René Nussbaumer
                             help="Node parameters")
1427 a535cef7 René Nussbaumer
1428 90e99856 Adeodato Simo
ALLOC_POLICY_OPT = cli_option("--alloc-policy", dest="alloc_policy",
1429 90e99856 Adeodato Simo
                              action="store", metavar="POLICY", default=None,
1430 90e99856 Adeodato Simo
                              help="Allocation policy for the node group")
1431 90e99856 Adeodato Simo
1432 d2881c71 René Nussbaumer
NODE_POWERED_OPT = cli_option("--node-powered", default=None,
1433 d2881c71 René Nussbaumer
                              type="bool", metavar=_YORNO,
1434 d2881c71 René Nussbaumer
                              dest="node_powered",
1435 d2881c71 René Nussbaumer
                              help="Specify if the SoR for node is powered")
1436 d2881c71 René Nussbaumer
1437 41543d8b René Nussbaumer
OOB_TIMEOUT_OPT = cli_option("--oob-timeout", dest="oob_timeout", type="int",
1438 5ae4945a Iustin Pop
                             default=constants.OOB_TIMEOUT,
1439 5ae4945a Iustin Pop
                             help="Maximum time to wait for out-of-band helper")
1440 41543d8b René Nussbaumer
1441 0c086a13 René Nussbaumer
POWER_DELAY_OPT = cli_option("--power-delay", dest="power_delay", type="float",
1442 0c086a13 René Nussbaumer
                             default=constants.OOB_POWER_DELAY,
1443 0c086a13 René Nussbaumer
                             help="Time in seconds to wait between power-ons")
1444 0c086a13 René Nussbaumer
1445 442587bf Michael Hanselmann
FORCE_FILTER_OPT = cli_option("-F", "--filter", dest="force_filter",
1446 442587bf Michael Hanselmann
                              action="store_true", default=False,
1447 442587bf Michael Hanselmann
                              help=("Whether command argument should be treated"
1448 442587bf Michael Hanselmann
                                    " as filter"))
1449 442587bf Michael Hanselmann
1450 885a0fc4 Iustin Pop
NO_REMEMBER_OPT = cli_option("--no-remember",
1451 885a0fc4 Iustin Pop
                             dest="no_remember",
1452 885a0fc4 Iustin Pop
                             action="store_true", default=False,
1453 885a0fc4 Iustin Pop
                             help="Perform but do not record the change"
1454 885a0fc4 Iustin Pop
                             " in the configuration")
1455 885a0fc4 Iustin Pop
1456 aafee533 Michael Hanselmann
PRIMARY_ONLY_OPT = cli_option("-p", "--primary-only",
1457 aafee533 Michael Hanselmann
                              default=False, action="store_true",
1458 aafee533 Michael Hanselmann
                              help="Evacuate primary instances only")
1459 aafee533 Michael Hanselmann
1460 aafee533 Michael Hanselmann
SECONDARY_ONLY_OPT = cli_option("-s", "--secondary-only",
1461 aafee533 Michael Hanselmann
                                default=False, action="store_true",
1462 aafee533 Michael Hanselmann
                                help="Evacuate secondary instances only"
1463 aafee533 Michael Hanselmann
                                     " (applies only to internally mirrored"
1464 aafee533 Michael Hanselmann
                                     " disk templates, e.g. %s)" %
1465 aafee533 Michael Hanselmann
                                     utils.CommaJoin(constants.DTS_INT_MIRROR))
1466 aafee533 Michael Hanselmann
1467 323f9095 Stephen Shirley
STARTUP_PAUSED_OPT = cli_option("--paused", dest="startup_paused",
1468 323f9095 Stephen Shirley
                                action="store_true", default=False,
1469 323f9095 Stephen Shirley
                                help="Pause instance at startup")
1470 323f9095 Stephen Shirley
1471 f6eb380d Michael Hanselmann
TO_GROUP_OPT = cli_option("--to", dest="to", metavar="<group>",
1472 f6eb380d Michael Hanselmann
                          help="Destination node group (name or uuid)",
1473 f6eb380d Michael Hanselmann
                          default=None, action="append",
1474 f6eb380d Michael Hanselmann
                          completion_suggest=OPT_COMPL_ONE_NODEGROUP)
1475 f6eb380d Michael Hanselmann
1476 93f2399e Andrea Spadaccini
IGNORE_ERRORS_OPT = cli_option("-I", "--ignore-errors", default=[],
1477 93f2399e Andrea Spadaccini
                               action="append", dest="ignore_errors",
1478 93f2399e Andrea Spadaccini
                               choices=list(constants.CV_ALL_ECODES_STRINGS),
1479 93f2399e Andrea Spadaccini
                               help="Error code to be ignored")
1480 93f2399e Andrea Spadaccini
1481 38f29a36 René Nussbaumer
DISK_STATE_OPT = cli_option("--disk-state", default=[], dest="disk_state",
1482 38f29a36 René Nussbaumer
                            action="append",
1483 a1cef552 Iustin Pop
                            help=("Specify disk state information in the"
1484 a1cef552 Iustin Pop
                                  " format"
1485 a1cef552 Iustin Pop
                                  " storage_type/identifier:option=value,...;"
1486 a1cef552 Iustin Pop
                                  " note this is unused for now"),
1487 38f29a36 René Nussbaumer
                            type="identkeyval")
1488 38f29a36 René Nussbaumer
1489 38f29a36 René Nussbaumer
HV_STATE_OPT = cli_option("--hypervisor-state", default=[], dest="hv_state",
1490 38f29a36 René Nussbaumer
                          action="append",
1491 38f29a36 René Nussbaumer
                          help=("Specify hypervisor state information in the"
1492 a1cef552 Iustin Pop
                                " format hypervisor:option=value,...;"
1493 a1cef552 Iustin Pop
                                " note this is unused for now"),
1494 38f29a36 René Nussbaumer
                          type="identkeyval")
1495 38f29a36 René Nussbaumer
1496 b6aaf437 René Nussbaumer
IGNORE_IPOLICY_OPT = cli_option("--ignore-ipolicy", dest="ignore_ipolicy",
1497 b6aaf437 René Nussbaumer
                                action="store_true", default=False,
1498 b6aaf437 René Nussbaumer
                                help="Ignore instance policy violations")
1499 b6aaf437 René Nussbaumer
1500 2c0af7da Guido Trotter
RUNTIME_MEM_OPT = cli_option("-m", "--runtime-memory", dest="runtime_mem",
1501 2c0af7da Guido Trotter
                             help="Sets the instance's runtime memory,"
1502 2c0af7da Guido Trotter
                             " ballooning it up or down to the new value",
1503 2c0af7da Guido Trotter
                             default=None, type="unit", metavar="<size>")
1504 61a14bb3 Iustin Pop
1505 ef8270dc Iustin Pop
ABSOLUTE_OPT = cli_option("--absolute", dest="absolute",
1506 ef8270dc Iustin Pop
                          action="store_true", default=False,
1507 ef8270dc Iustin Pop
                          help="Marks the grow as absolute instead of the"
1508 ef8270dc Iustin Pop
                          " (default) relative mode")
1509 ef8270dc Iustin Pop
1510 9c784fb3 Dimitris Aragiorgis
NETWORK_OPT = cli_option("--network",
1511 9c784fb3 Dimitris Aragiorgis
                         action="store", default=None, dest="network",
1512 9c784fb3 Dimitris Aragiorgis
                         help="IP network in CIDR notation")
1513 9c784fb3 Dimitris Aragiorgis
1514 9c784fb3 Dimitris Aragiorgis
GATEWAY_OPT = cli_option("--gateway",
1515 9c784fb3 Dimitris Aragiorgis
                         action="store", default=None, dest="gateway",
1516 9c784fb3 Dimitris Aragiorgis
                         help="IP address of the router (gateway)")
1517 9c784fb3 Dimitris Aragiorgis
1518 9c784fb3 Dimitris Aragiorgis
ADD_RESERVED_IPS_OPT = cli_option("--add-reserved-ips",
1519 9c784fb3 Dimitris Aragiorgis
                                  action="store", default=None,
1520 9c784fb3 Dimitris Aragiorgis
                                  dest="add_reserved_ips",
1521 9c784fb3 Dimitris Aragiorgis
                                  help="Comma-separated list of"
1522 9c784fb3 Dimitris Aragiorgis
                                  " reserved IPs to add")
1523 9c784fb3 Dimitris Aragiorgis
1524 9c784fb3 Dimitris Aragiorgis
REMOVE_RESERVED_IPS_OPT = cli_option("--remove-reserved-ips",
1525 9c784fb3 Dimitris Aragiorgis
                                     action="store", default=None,
1526 9c784fb3 Dimitris Aragiorgis
                                     dest="remove_reserved_ips",
1527 9c784fb3 Dimitris Aragiorgis
                                     help="Comma-delimited list of"
1528 9c784fb3 Dimitris Aragiorgis
                                     " reserved IPs to remove")
1529 9c784fb3 Dimitris Aragiorgis
1530 9c784fb3 Dimitris Aragiorgis
NETWORK_TYPE_OPT = cli_option("--network-type",
1531 9c784fb3 Dimitris Aragiorgis
                              action="store", default=None, dest="network_type",
1532 9c784fb3 Dimitris Aragiorgis
                              help="Network type: private, public, None")
1533 9c784fb3 Dimitris Aragiorgis
1534 9c784fb3 Dimitris Aragiorgis
NETWORK6_OPT = cli_option("--network6",
1535 9c784fb3 Dimitris Aragiorgis
                          action="store", default=None, dest="network6",
1536 9c784fb3 Dimitris Aragiorgis
                          help="IP network in CIDR notation")
1537 9c784fb3 Dimitris Aragiorgis
1538 9c784fb3 Dimitris Aragiorgis
GATEWAY6_OPT = cli_option("--gateway6",
1539 9c784fb3 Dimitris Aragiorgis
                          action="store", default=None, dest="gateway6",
1540 9c784fb3 Dimitris Aragiorgis
                          help="IP6 address of the router (gateway)")
1541 9c784fb3 Dimitris Aragiorgis
1542 9c784fb3 Dimitris Aragiorgis
NOCONFLICTSCHECK_OPT = cli_option("--no-conflicts-check",
1543 9c784fb3 Dimitris Aragiorgis
                                  dest="conflicts_check",
1544 9c784fb3 Dimitris Aragiorgis
                                  default=True,
1545 9c784fb3 Dimitris Aragiorgis
                                  action="store_false",
1546 9c784fb3 Dimitris Aragiorgis
                                  help="Don't check for conflicting IPs")
1547 9c784fb3 Dimitris Aragiorgis
1548 5786c087 Michael Hanselmann
#: Options provided by all commands
1549 5786c087 Michael Hanselmann
COMMON_OPTS = [DEBUG_OPT]
1550 5786c087 Michael Hanselmann
1551 eb28ecf6 Guido Trotter
# common options for creating instances. add and import then add their own
1552 eb28ecf6 Guido Trotter
# specific ones.
1553 eb28ecf6 Guido Trotter
COMMON_CREATE_OPTS = [
1554 eb28ecf6 Guido Trotter
  BACKEND_OPT,
1555 eb28ecf6 Guido Trotter
  DISK_OPT,
1556 eb28ecf6 Guido Trotter
  DISK_TEMPLATE_OPT,
1557 eb28ecf6 Guido Trotter
  FILESTORE_DIR_OPT,
1558 eb28ecf6 Guido Trotter
  FILESTORE_DRIVER_OPT,
1559 eb28ecf6 Guido Trotter
  HYPERVISOR_OPT,
1560 eb28ecf6 Guido Trotter
  IALLOCATOR_OPT,
1561 eb28ecf6 Guido Trotter
  NET_OPT,
1562 eb28ecf6 Guido Trotter
  NODE_PLACEMENT_OPT,
1563 eb28ecf6 Guido Trotter
  NOIPCHECK_OPT,
1564 9c784fb3 Dimitris Aragiorgis
  NOCONFLICTSCHECK_OPT,
1565 eb28ecf6 Guido Trotter
  NONAMECHECK_OPT,
1566 eb28ecf6 Guido Trotter
  NONICS_OPT,
1567 eb28ecf6 Guido Trotter
  NWSYNC_OPT,
1568 eb28ecf6 Guido Trotter
  OSPARAMS_OPT,
1569 eb28ecf6 Guido Trotter
  OS_SIZE_OPT,
1570 eb28ecf6 Guido Trotter
  SUBMIT_OPT,
1571 0f8810df Michael Hanselmann
  TAG_ADD_OPT,
1572 eb28ecf6 Guido Trotter
  DRY_RUN_OPT,
1573 eb28ecf6 Guido Trotter
  PRIORITY_OPT,
1574 eb28ecf6 Guido Trotter
  ]
1575 eb28ecf6 Guido Trotter
1576 0ce212e5 Iustin Pop
# common instance policy options
1577 0ce212e5 Iustin Pop
INSTANCE_POLICY_OPTS = [
1578 0ce212e5 Iustin Pop
  SPECS_CPU_COUNT_OPT,
1579 0ce212e5 Iustin Pop
  SPECS_DISK_COUNT_OPT,
1580 0ce212e5 Iustin Pop
  SPECS_DISK_SIZE_OPT,
1581 0ce212e5 Iustin Pop
  SPECS_MEM_SIZE_OPT,
1582 0ce212e5 Iustin Pop
  SPECS_NIC_COUNT_OPT,
1583 d04c9d45 Iustin Pop
  IPOLICY_DISK_TEMPLATES,
1584 976b78ba Iustin Pop
  IPOLICY_VCPU_RATIO,
1585 ad5cc6bd René Nussbaumer
  IPOLICY_SPINDLE_RATIO,
1586 0ce212e5 Iustin Pop
  ]
1587 0ce212e5 Iustin Pop
1588 771734c9 Iustin Pop
1589 d971402f Michael Hanselmann
class _ShowUsage(Exception):
1590 d971402f Michael Hanselmann
  """Exception class for L{_ParseArgs}.
1591 d971402f Michael Hanselmann

1592 d971402f Michael Hanselmann
  """
1593 d971402f Michael Hanselmann
  def __init__(self, exit_error):
1594 d971402f Michael Hanselmann
    """Initializes instances of this class.
1595 d971402f Michael Hanselmann

1596 d971402f Michael Hanselmann
    @type exit_error: bool
1597 d971402f Michael Hanselmann
    @param exit_error: Whether to report failure on exit
1598 d971402f Michael Hanselmann

1599 d971402f Michael Hanselmann
    """
1600 d971402f Michael Hanselmann
    Exception.__init__(self)
1601 d971402f Michael Hanselmann
    self.exit_error = exit_error
1602 d971402f Michael Hanselmann
1603 d971402f Michael Hanselmann
1604 d971402f Michael Hanselmann
class _ShowVersion(Exception):
1605 d971402f Michael Hanselmann
  """Exception class for L{_ParseArgs}.
1606 d971402f Michael Hanselmann

1607 d971402f Michael Hanselmann
  """
1608 d971402f Michael Hanselmann
1609 d971402f Michael Hanselmann
1610 d971402f Michael Hanselmann
def _ParseArgs(binary, argv, commands, aliases, env_override):
1611 c41eea6e Iustin Pop
  """Parser for the command line arguments.
1612 a8083063 Iustin Pop

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

1616 d971402f Michael Hanselmann
  @param binary: Script name
1617 d971402f Michael Hanselmann
  @param argv: Command line arguments
1618 d971402f Michael Hanselmann
  @param commands: Dictionary containing command definitions
1619 d971402f Michael Hanselmann
  @param aliases: dictionary with command aliases {"alias": "target", ...}
1620 ef9fa5b9 René Nussbaumer
  @param env_override: list of env variables allowed for default args
1621 d971402f Michael Hanselmann
  @raise _ShowUsage: If usage description should be shown
1622 d971402f Michael Hanselmann
  @raise _ShowVersion: If version should be shown
1623 098c0958 Michael Hanselmann

1624 a8083063 Iustin Pop
  """
1625 ef9fa5b9 René Nussbaumer
  assert not (env_override - set(commands))
1626 d971402f Michael Hanselmann
  assert not (set(aliases.keys()) & set(commands.keys()))
1627 ef9fa5b9 René Nussbaumer
1628 d971402f Michael Hanselmann
  if len(argv) > 1:
1629 d971402f Michael Hanselmann
    cmd = argv[1]
1630 a8083063 Iustin Pop
  else:
1631 d971402f Michael Hanselmann
    # No option or command given
1632 d971402f Michael Hanselmann
    raise _ShowUsage(exit_error=True)
1633 a8083063 Iustin Pop
1634 d971402f Michael Hanselmann
  if cmd == "--version":
1635 d971402f Michael Hanselmann
    raise _ShowVersion()
1636 d971402f Michael Hanselmann
  elif cmd == "--help":
1637 d971402f Michael Hanselmann
    raise _ShowUsage(exit_error=False)
1638 d971402f Michael Hanselmann
  elif not (cmd in commands or cmd in aliases):
1639 d971402f Michael Hanselmann
    raise _ShowUsage(exit_error=True)
1640 de47cf8f Guido Trotter
1641 de47cf8f Guido Trotter
  # get command, unalias it, and look it up in commands
1642 de47cf8f Guido Trotter
  if cmd in aliases:
1643 de47cf8f Guido Trotter
    if aliases[cmd] not in commands:
1644 de47cf8f Guido Trotter
      raise errors.ProgrammerError("Alias '%s' maps to non-existing"
1645 de47cf8f Guido Trotter
                                   " command '%s'" % (cmd, aliases[cmd]))
1646 de47cf8f Guido Trotter
1647 de47cf8f Guido Trotter
    cmd = aliases[cmd]
1648 de47cf8f Guido Trotter
1649 ef9fa5b9 René Nussbaumer
  if cmd in env_override:
1650 ef9fa5b9 René Nussbaumer
    args_env_name = ("%s_%s" % (binary.replace("-", "_"), cmd)).upper()
1651 ef9fa5b9 René Nussbaumer
    env_args = os.environ.get(args_env_name)
1652 ef9fa5b9 René Nussbaumer
    if env_args:
1653 d971402f Michael Hanselmann
      argv = utils.InsertAtPos(argv, 2, shlex.split(env_args))
1654 ef9fa5b9 René Nussbaumer
1655 a8005e17 Michael Hanselmann
  func, args_def, parser_opts, usage, description = commands[cmd]
1656 bf5338b3 Michael Hanselmann
  parser = OptionParser(option_list=parser_opts + COMMON_OPTS,
1657 bf5338b3 Michael Hanselmann
                        description=description,
1658 bf5338b3 Michael Hanselmann
                        formatter=TitledHelpFormatter(),
1659 bf5338b3 Michael Hanselmann
                        usage="%%prog %s %s" % (cmd, usage))
1660 a8083063 Iustin Pop
  parser.disable_interspersed_args()
1661 d971402f Michael Hanselmann
  options, args = parser.parse_args(args=argv[2:])
1662 a8005e17 Michael Hanselmann
1663 a8005e17 Michael Hanselmann
  if not _CheckArguments(cmd, args_def, args):
1664 a8083063 Iustin Pop
    return None, None, None
1665 a8083063 Iustin Pop
1666 a8083063 Iustin Pop
  return func, options, args
1667 a8083063 Iustin Pop
1668 a8083063 Iustin Pop
1669 d971402f Michael Hanselmann
def _FormatUsage(binary, commands):
1670 d971402f Michael Hanselmann
  """Generates a nice description of all commands.
1671 d971402f Michael Hanselmann

1672 d971402f Michael Hanselmann
  @param binary: Script name
1673 d971402f Michael Hanselmann
  @param commands: Dictionary containing command definitions
1674 d971402f Michael Hanselmann

1675 d971402f Michael Hanselmann
  """
1676 d971402f Michael Hanselmann
  # compute the max line length for cmd + usage
1677 d971402f Michael Hanselmann
  mlen = min(60, max(map(len, commands)))
1678 d971402f Michael Hanselmann
1679 d971402f Michael Hanselmann
  yield "Usage: %s {command} [options...] [argument...]" % binary
1680 d971402f Michael Hanselmann
  yield "%s <command> --help to see details, or man %s" % (binary, binary)
1681 d971402f Michael Hanselmann
  yield ""
1682 d971402f Michael Hanselmann
  yield "Commands:"
1683 d971402f Michael Hanselmann
1684 d971402f Michael Hanselmann
  # and format a nice command list
1685 d971402f Michael Hanselmann
  for (cmd, (_, _, _, _, help_text)) in sorted(commands.items()):
1686 d971402f Michael Hanselmann
    help_lines = textwrap.wrap(help_text, 79 - 3 - mlen)
1687 d971402f Michael Hanselmann
    yield " %-*s - %s" % (mlen, cmd, help_lines.pop(0))
1688 d971402f Michael Hanselmann
    for line in help_lines:
1689 d971402f Michael Hanselmann
      yield " %-*s   %s" % (mlen, "", line)
1690 d971402f Michael Hanselmann
1691 d971402f Michael Hanselmann
  yield ""
1692 d971402f Michael Hanselmann
1693 d971402f Michael Hanselmann
1694 a8005e17 Michael Hanselmann
def _CheckArguments(cmd, args_def, args):
1695 a8005e17 Michael Hanselmann
  """Verifies the arguments using the argument definition.
1696 a8005e17 Michael Hanselmann

1697 a8005e17 Michael Hanselmann
  Algorithm:
1698 a8005e17 Michael Hanselmann

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

1701 a8005e17 Michael Hanselmann
    1. For each argument in definition
1702 a8005e17 Michael Hanselmann

1703 a8005e17 Michael Hanselmann
      1. Keep running count of minimum number of values (min_count)
1704 a8005e17 Michael Hanselmann
      1. Keep running count of maximum number of values (max_count)
1705 a8005e17 Michael Hanselmann
      1. If it has an unlimited number of values
1706 a8005e17 Michael Hanselmann

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

1709 a8005e17 Michael Hanselmann
    1. If last argument has limited number of values
1710 a8005e17 Michael Hanselmann

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

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

1715 a8005e17 Michael Hanselmann
  """
1716 a8005e17 Michael Hanselmann
  if args and not args_def:
1717 a8005e17 Michael Hanselmann
    ToStderr("Error: Command %s expects no arguments", cmd)
1718 a8005e17 Michael Hanselmann
    return False
1719 a8005e17 Michael Hanselmann
1720 a8005e17 Michael Hanselmann
  min_count = None
1721 a8005e17 Michael Hanselmann
  max_count = None
1722 a8005e17 Michael Hanselmann
  check_max = None
1723 a8005e17 Michael Hanselmann
1724 a8005e17 Michael Hanselmann
  last_idx = len(args_def) - 1
1725 a8005e17 Michael Hanselmann
1726 a8005e17 Michael Hanselmann
  for idx, arg in enumerate(args_def):
1727 a8005e17 Michael Hanselmann
    if min_count is None:
1728 a8005e17 Michael Hanselmann
      min_count = arg.min
1729 a8005e17 Michael Hanselmann
    elif arg.min is not None:
1730 a8005e17 Michael Hanselmann
      min_count += arg.min
1731 a8005e17 Michael Hanselmann
1732 a8005e17 Michael Hanselmann
    if max_count is None:
1733 a8005e17 Michael Hanselmann
      max_count = arg.max
1734 a8005e17 Michael Hanselmann
    elif arg.max is not None:
1735 a8005e17 Michael Hanselmann
      max_count += arg.max
1736 a8005e17 Michael Hanselmann
1737 a8005e17 Michael Hanselmann
    if idx == last_idx:
1738 a8005e17 Michael Hanselmann
      check_max = (arg.max is not None)
1739 a8005e17 Michael Hanselmann
1740 a8005e17 Michael Hanselmann
    elif arg.max is None:
1741 a8005e17 Michael Hanselmann
      raise errors.ProgrammerError("Only the last argument can have max=None")
1742 a8005e17 Michael Hanselmann
1743 a8005e17 Michael Hanselmann
  if check_max:
1744 a8005e17 Michael Hanselmann
    # Command with exact number of arguments
1745 a8005e17 Michael Hanselmann
    if (min_count is not None and max_count is not None and
1746 a8005e17 Michael Hanselmann
        min_count == max_count and len(args) != min_count):
1747 a8005e17 Michael Hanselmann
      ToStderr("Error: Command %s expects %d argument(s)", cmd, min_count)
1748 a8005e17 Michael Hanselmann
      return False
1749 a8005e17 Michael Hanselmann
1750 a8005e17 Michael Hanselmann
    # Command with limited number of arguments
1751 a8005e17 Michael Hanselmann
    if max_count is not None and len(args) > max_count:
1752 a8005e17 Michael Hanselmann
      ToStderr("Error: Command %s expects only %d argument(s)",
1753 a8005e17 Michael Hanselmann
               cmd, max_count)
1754 a8005e17 Michael Hanselmann
      return False
1755 a8005e17 Michael Hanselmann
1756 a8005e17 Michael Hanselmann
  # Command with some required arguments
1757 a8005e17 Michael Hanselmann
  if min_count is not None and len(args) < min_count:
1758 a8005e17 Michael Hanselmann
    ToStderr("Error: Command %s expects at least %d argument(s)",
1759 a8005e17 Michael Hanselmann
             cmd, min_count)
1760 a8005e17 Michael Hanselmann
    return False
1761 a8005e17 Michael Hanselmann
1762 a8005e17 Michael Hanselmann
  return True
1763 a8005e17 Michael Hanselmann
1764 a8005e17 Michael Hanselmann
1765 60d49723 Michael Hanselmann
def SplitNodeOption(value):
1766 60d49723 Michael Hanselmann
  """Splits the value of a --node option.
1767 60d49723 Michael Hanselmann

1768 60d49723 Michael Hanselmann
  """
1769 d0c8c01d Iustin Pop
  if value and ":" in value:
1770 d0c8c01d Iustin Pop
    return value.split(":", 1)
1771 60d49723 Michael Hanselmann
  else:
1772 60d49723 Michael Hanselmann
    return (value, None)
1773 60d49723 Michael Hanselmann
1774 60d49723 Michael Hanselmann
1775 07150497 Guido Trotter
def CalculateOSNames(os_name, os_variants):
1776 07150497 Guido Trotter
  """Calculates all the names an OS can be called, according to its variants.
1777 07150497 Guido Trotter

1778 07150497 Guido Trotter
  @type os_name: string
1779 07150497 Guido Trotter
  @param os_name: base name of the os
1780 07150497 Guido Trotter
  @type os_variants: list or None
1781 07150497 Guido Trotter
  @param os_variants: list of supported variants
1782 07150497 Guido Trotter
  @rtype: list
1783 07150497 Guido Trotter
  @return: list of valid names
1784 07150497 Guido Trotter

1785 07150497 Guido Trotter
  """
1786 07150497 Guido Trotter
  if os_variants:
1787 d0c8c01d Iustin Pop
    return ["%s+%s" % (os_name, v) for v in os_variants]
1788 07150497 Guido Trotter
  else:
1789 07150497 Guido Trotter
    return [os_name]
1790 07150497 Guido Trotter
1791 07150497 Guido Trotter
1792 a4ebd726 Michael Hanselmann
def ParseFields(selected, default):
1793 a4ebd726 Michael Hanselmann
  """Parses the values of "--field"-like options.
1794 a4ebd726 Michael Hanselmann

1795 a4ebd726 Michael Hanselmann
  @type selected: string or None
1796 a4ebd726 Michael Hanselmann
  @param selected: User-selected options
1797 a4ebd726 Michael Hanselmann
  @type default: list
1798 a4ebd726 Michael Hanselmann
  @param default: Default fields
1799 a4ebd726 Michael Hanselmann

1800 a4ebd726 Michael Hanselmann
  """
1801 a4ebd726 Michael Hanselmann
  if selected is None:
1802 a4ebd726 Michael Hanselmann
    return default
1803 a4ebd726 Michael Hanselmann
1804 a4ebd726 Michael Hanselmann
  if selected.startswith("+"):
1805 a4ebd726 Michael Hanselmann
    return default + selected[1:].split(",")
1806 a4ebd726 Michael Hanselmann
1807 a4ebd726 Michael Hanselmann
  return selected.split(",")
1808 a4ebd726 Michael Hanselmann
1809 a4ebd726 Michael Hanselmann
1810 e0e916fe Iustin Pop
UsesRPC = rpc.RunWithRPC
1811 4331f6cd Michael Hanselmann
1812 4331f6cd Michael Hanselmann
1813 47988778 Iustin Pop
def AskUser(text, choices=None):
1814 47988778 Iustin Pop
  """Ask the user a question.
1815 a8083063 Iustin Pop

1816 c41eea6e Iustin Pop
  @param text: the question to ask
1817 a8083063 Iustin Pop

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

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

1827 a8083063 Iustin Pop
  """
1828 47988778 Iustin Pop
  if choices is None:
1829 d0c8c01d Iustin Pop
    choices = [("y", True, "Perform the operation"),
1830 d0c8c01d Iustin Pop
               ("n", False, "Do not perform the operation")]
1831 47988778 Iustin Pop
  if not choices or not isinstance(choices, list):
1832 5bbd3f7f Michael Hanselmann
    raise errors.ProgrammerError("Invalid choices argument to AskUser")
1833 47988778 Iustin Pop
  for entry in choices:
1834 d0c8c01d Iustin Pop
    if not isinstance(entry, tuple) or len(entry) < 3 or entry[0] == "?":
1835 5bbd3f7f Michael Hanselmann
      raise errors.ProgrammerError("Invalid choices element to AskUser")
1836 47988778 Iustin Pop
1837 47988778 Iustin Pop
  answer = choices[-1][1]
1838 47988778 Iustin Pop
  new_text = []
1839 47988778 Iustin Pop
  for line in text.splitlines():
1840 47988778 Iustin Pop
    new_text.append(textwrap.fill(line, 70, replace_whitespace=False))
1841 47988778 Iustin Pop
  text = "\n".join(new_text)
1842 a8083063 Iustin Pop
  try:
1843 3023170f Iustin Pop
    f = file("/dev/tty", "a+")
1844 a8083063 Iustin Pop
  except IOError:
1845 47988778 Iustin Pop
    return answer
1846 a8083063 Iustin Pop
  try:
1847 47988778 Iustin Pop
    chars = [entry[0] for entry in choices]
1848 47988778 Iustin Pop
    chars[-1] = "[%s]" % chars[-1]
1849 d0c8c01d Iustin Pop
    chars.append("?")
1850 47988778 Iustin Pop
    maps = dict([(entry[0], entry[1]) for entry in choices])
1851 47988778 Iustin Pop
    while True:
1852 47988778 Iustin Pop
      f.write(text)
1853 d0c8c01d Iustin Pop
      f.write("\n")
1854 47988778 Iustin Pop
      f.write("/".join(chars))
1855 47988778 Iustin Pop
      f.write(": ")
1856 47988778 Iustin Pop
      line = f.readline(2).strip().lower()
1857 47988778 Iustin Pop
      if line in maps:
1858 47988778 Iustin Pop
        answer = maps[line]
1859 47988778 Iustin Pop
        break
1860 d0c8c01d Iustin Pop
      elif line == "?":
1861 47988778 Iustin Pop
        for entry in choices:
1862 47988778 Iustin Pop
          f.write(" %s - %s\n" % (entry[0], entry[2]))
1863 47988778 Iustin Pop
        f.write("\n")
1864 47988778 Iustin Pop
        continue
1865 a8083063 Iustin Pop
  finally:
1866 a8083063 Iustin Pop
    f.close()
1867 a8083063 Iustin Pop
  return answer
1868 a8083063 Iustin Pop
1869 a8083063 Iustin Pop
1870 e9d741b6 Iustin Pop
class JobSubmittedException(Exception):
1871 e9d741b6 Iustin Pop
  """Job was submitted, client should exit.
1872 e9d741b6 Iustin Pop

1873 e9d741b6 Iustin Pop
  This exception has one argument, the ID of the job that was
1874 e9d741b6 Iustin Pop
  submitted. The handler should print this ID.
1875 e9d741b6 Iustin Pop

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

1878 e9d741b6 Iustin Pop
  """
1879 e9d741b6 Iustin Pop
1880 e9d741b6 Iustin Pop
1881 0a1e74d9 Iustin Pop
def SendJob(ops, cl=None):
1882 0a1e74d9 Iustin Pop
  """Function to submit an opcode without waiting for the results.
1883 a8083063 Iustin Pop

1884 0a1e74d9 Iustin Pop
  @type ops: list
1885 0a1e74d9 Iustin Pop
  @param ops: list of opcodes
1886 0a1e74d9 Iustin Pop
  @type cl: luxi.Client
1887 0a1e74d9 Iustin Pop
  @param cl: the luxi client to use for communicating with the master;
1888 0a1e74d9 Iustin Pop
             if None, a new client will be created
1889 a8083063 Iustin Pop

1890 a8083063 Iustin Pop
  """
1891 e2212007 Iustin Pop
  if cl is None:
1892 b33e986b Iustin Pop
    cl = GetClient()
1893 685ee993 Iustin Pop
1894 0a1e74d9 Iustin Pop
  job_id = cl.SubmitJob(ops)
1895 0a1e74d9 Iustin Pop
1896 0a1e74d9 Iustin Pop
  return job_id
1897 0a1e74d9 Iustin Pop
1898 0a1e74d9 Iustin Pop
1899 4e338533 Michael Hanselmann
def GenericPollJob(job_id, cbs, report_cbs):
1900 4e338533 Michael Hanselmann
  """Generic job-polling function.
1901 0a1e74d9 Iustin Pop

1902 4e338533 Michael Hanselmann
  @type job_id: number
1903 4e338533 Michael Hanselmann
  @param job_id: Job ID
1904 4e338533 Michael Hanselmann
  @type cbs: Instance of L{JobPollCbBase}
1905 4e338533 Michael Hanselmann
  @param cbs: Data callbacks
1906 4e338533 Michael Hanselmann
  @type report_cbs: Instance of L{JobPollReportCbBase}
1907 4e338533 Michael Hanselmann
  @param report_cbs: Reporting callbacks
1908 0a1e74d9 Iustin Pop

1909 0a1e74d9 Iustin Pop
  """
1910 6c5a7090 Michael Hanselmann
  prev_job_info = None
1911 6c5a7090 Michael Hanselmann
  prev_logmsg_serial = None
1912 6c5a7090 Michael Hanselmann
1913 f4484122 Michael Hanselmann
  status = None
1914 f4484122 Michael Hanselmann
1915 685ee993 Iustin Pop
  while True:
1916 4e338533 Michael Hanselmann
    result = cbs.WaitForJobChangeOnce(job_id, ["status"], prev_job_info,
1917 4e338533 Michael Hanselmann
                                      prev_logmsg_serial)
1918 6c5a7090 Michael Hanselmann
    if not result:
1919 685ee993 Iustin Pop
      # job not found, go away!
1920 0bbe448c Michael Hanselmann
      raise errors.JobLost("Job with id %s lost" % job_id)
1921 4e338533 Michael Hanselmann
1922 4e338533 Michael Hanselmann
    if result == constants.JOB_NOTCHANGED:
1923 4e338533 Michael Hanselmann
      report_cbs.ReportNotChanged(job_id, status)
1924 f4484122 Michael Hanselmann
1925 f4484122 Michael Hanselmann
      # Wait again
1926 f4484122 Michael Hanselmann
      continue
1927 685ee993 Iustin Pop
1928 6c5a7090 Michael Hanselmann
    # Split result, a tuple of (field values, log entries)
1929 6c5a7090 Michael Hanselmann
    (job_info, log_entries) = result
1930 6c5a7090 Michael Hanselmann
    (status, ) = job_info
1931 6c5a7090 Michael Hanselmann
1932 6c5a7090 Michael Hanselmann
    if log_entries:
1933 6c5a7090 Michael Hanselmann
      for log_entry in log_entries:
1934 4e338533 Michael Hanselmann
        (serial, timestamp, log_type, message) = log_entry
1935 4e338533 Michael Hanselmann
        report_cbs.ReportLogMessage(job_id, serial, timestamp,
1936 4e338533 Michael Hanselmann
                                    log_type, message)
1937 6c5a7090 Michael Hanselmann
        prev_logmsg_serial = max(prev_logmsg_serial, serial)
1938 6c5a7090 Michael Hanselmann
1939 0bbe448c Michael Hanselmann
    # TODO: Handle canceled and archived jobs
1940 fbf0262f Michael Hanselmann
    elif status in (constants.JOB_STATUS_SUCCESS,
1941 fbf0262f Michael Hanselmann
                    constants.JOB_STATUS_ERROR,
1942 fbf0262f Michael Hanselmann
                    constants.JOB_STATUS_CANCELING,
1943 fbf0262f Michael Hanselmann
                    constants.JOB_STATUS_CANCELED):
1944 685ee993 Iustin Pop
      break
1945 6c5a7090 Michael Hanselmann
1946 6c5a7090 Michael Hanselmann
    prev_job_info = job_info
1947 685ee993 Iustin Pop
1948 4e338533 Michael Hanselmann
  jobs = cbs.QueryJobs([job_id], ["status", "opstatus", "opresult"])
1949 0bbe448c Michael Hanselmann
  if not jobs:
1950 0bbe448c Michael Hanselmann
    raise errors.JobLost("Job with id %s lost" % job_id)
1951 685ee993 Iustin Pop
1952 0e050889 Iustin Pop
  status, opstatus, result = jobs[0]
1953 4e338533 Michael Hanselmann
1954 0bbe448c Michael Hanselmann
  if status == constants.JOB_STATUS_SUCCESS:
1955 53c04d04 Iustin Pop
    return result
1956 4e338533 Michael Hanselmann
1957 4e338533 Michael Hanselmann
  if status in (constants.JOB_STATUS_CANCELING, constants.JOB_STATUS_CANCELED):
1958 fbf0262f Michael Hanselmann
    raise errors.OpExecError("Job was canceled")
1959 4e338533 Michael Hanselmann
1960 4e338533 Michael Hanselmann
  has_ok = False
1961 4e338533 Michael Hanselmann
  for idx, (status, msg) in enumerate(zip(opstatus, result)):
1962 4e338533 Michael Hanselmann
    if status == constants.OP_STATUS_SUCCESS:
1963 4e338533 Michael Hanselmann
      has_ok = True
1964 4e338533 Michael Hanselmann
    elif status == constants.OP_STATUS_ERROR:
1965 4e338533 Michael Hanselmann
      errors.MaybeRaise(msg)
1966 4e338533 Michael Hanselmann
1967 4e338533 Michael Hanselmann
      if has_ok:
1968 4e338533 Michael Hanselmann
        raise errors.OpExecError("partial failure (opcode %d): %s" %
1969 4e338533 Michael Hanselmann
                                 (idx, msg))
1970 4e338533 Michael Hanselmann
1971 4e338533 Michael Hanselmann
      raise errors.OpExecError(str(msg))
1972 4e338533 Michael Hanselmann
1973 4e338533 Michael Hanselmann
  # default failure mode
1974 4e338533 Michael Hanselmann
  raise errors.OpExecError(result)
1975 4e338533 Michael Hanselmann
1976 4e338533 Michael Hanselmann
1977 4e338533 Michael Hanselmann
class JobPollCbBase:
1978 4e338533 Michael Hanselmann
  """Base class for L{GenericPollJob} callbacks.
1979 4e338533 Michael Hanselmann

1980 4e338533 Michael Hanselmann
  """
1981 4e338533 Michael Hanselmann
  def __init__(self):
1982 4e338533 Michael Hanselmann
    """Initializes this class.
1983 4e338533 Michael Hanselmann

1984 4e338533 Michael Hanselmann
    """
1985 4e338533 Michael Hanselmann
1986 4e338533 Michael Hanselmann
  def WaitForJobChangeOnce(self, job_id, fields,
1987 4e338533 Michael Hanselmann
                           prev_job_info, prev_log_serial):
1988 4e338533 Michael Hanselmann
    """Waits for changes on a job.
1989 4e338533 Michael Hanselmann

1990 4e338533 Michael Hanselmann
    """
1991 4e338533 Michael Hanselmann
    raise NotImplementedError()
1992 4e338533 Michael Hanselmann
1993 4e338533 Michael Hanselmann
  def QueryJobs(self, job_ids, fields):
1994 4e338533 Michael Hanselmann
    """Returns the selected fields for the selected job IDs.
1995 4e338533 Michael Hanselmann

1996 4e338533 Michael Hanselmann
    @type job_ids: list of numbers
1997 4e338533 Michael Hanselmann
    @param job_ids: Job IDs
1998 4e338533 Michael Hanselmann
    @type fields: list of strings
1999 4e338533 Michael Hanselmann
    @param fields: Fields
2000 4e338533 Michael Hanselmann

2001 4e338533 Michael Hanselmann
    """
2002 4e338533 Michael Hanselmann
    raise NotImplementedError()
2003 4e338533 Michael Hanselmann
2004 4e338533 Michael Hanselmann
2005 4e338533 Michael Hanselmann
class JobPollReportCbBase:
2006 4e338533 Michael Hanselmann
  """Base class for L{GenericPollJob} reporting callbacks.
2007 4e338533 Michael Hanselmann

2008 4e338533 Michael Hanselmann
  """
2009 4e338533 Michael Hanselmann
  def __init__(self):
2010 4e338533 Michael Hanselmann
    """Initializes this class.
2011 4e338533 Michael Hanselmann

2012 4e338533 Michael Hanselmann
    """
2013 4e338533 Michael Hanselmann
2014 4e338533 Michael Hanselmann
  def ReportLogMessage(self, job_id, serial, timestamp, log_type, log_msg):
2015 4e338533 Michael Hanselmann
    """Handles a log message.
2016 4e338533 Michael Hanselmann

2017 4e338533 Michael Hanselmann
    """
2018 4e338533 Michael Hanselmann
    raise NotImplementedError()
2019 4e338533 Michael Hanselmann
2020 4e338533 Michael Hanselmann
  def ReportNotChanged(self, job_id, status):
2021 4e338533 Michael Hanselmann
    """Called for if a job hasn't changed in a while.
2022 4e338533 Michael Hanselmann

2023 4e338533 Michael Hanselmann
    @type job_id: number
2024 4e338533 Michael Hanselmann
    @param job_id: Job ID
2025 4e338533 Michael Hanselmann
    @type status: string or None
2026 4e338533 Michael Hanselmann
    @param status: Job status if available
2027 4e338533 Michael Hanselmann

2028 4e338533 Michael Hanselmann
    """
2029 4e338533 Michael Hanselmann
    raise NotImplementedError()
2030 4e338533 Michael Hanselmann
2031 4e338533 Michael Hanselmann
2032 4e338533 Michael Hanselmann
class _LuxiJobPollCb(JobPollCbBase):
2033 4e338533 Michael Hanselmann
  def __init__(self, cl):
2034 4e338533 Michael Hanselmann
    """Initializes this class.
2035 4e338533 Michael Hanselmann

2036 4e338533 Michael Hanselmann
    """
2037 4e338533 Michael Hanselmann
    JobPollCbBase.__init__(self)
2038 4e338533 Michael Hanselmann
    self.cl = cl
2039 4e338533 Michael Hanselmann
2040 4e338533 Michael Hanselmann
  def WaitForJobChangeOnce(self, job_id, fields,
2041 4e338533 Michael Hanselmann
                           prev_job_info, prev_log_serial):
2042 4e338533 Michael Hanselmann
    """Waits for changes on a job.
2043 4e338533 Michael Hanselmann

2044 4e338533 Michael Hanselmann
    """
2045 4e338533 Michael Hanselmann
    return self.cl.WaitForJobChangeOnce(job_id, fields,
2046 4e338533 Michael Hanselmann
                                        prev_job_info, prev_log_serial)
2047 4e338533 Michael Hanselmann
2048 4e338533 Michael Hanselmann
  def QueryJobs(self, job_ids, fields):
2049 4e338533 Michael Hanselmann
    """Returns the selected fields for the selected job IDs.
2050 4e338533 Michael Hanselmann

2051 4e338533 Michael Hanselmann
    """
2052 4e338533 Michael Hanselmann
    return self.cl.QueryJobs(job_ids, fields)
2053 4e338533 Michael Hanselmann
2054 4e338533 Michael Hanselmann
2055 4e338533 Michael Hanselmann
class FeedbackFnJobPollReportCb(JobPollReportCbBase):
2056 4e338533 Michael Hanselmann
  def __init__(self, feedback_fn):
2057 4e338533 Michael Hanselmann
    """Initializes this class.
2058 4e338533 Michael Hanselmann

2059 4e338533 Michael Hanselmann
    """
2060 4e338533 Michael Hanselmann
    JobPollReportCbBase.__init__(self)
2061 4e338533 Michael Hanselmann
2062 4e338533 Michael Hanselmann
    self.feedback_fn = feedback_fn
2063 4e338533 Michael Hanselmann
2064 4e338533 Michael Hanselmann
    assert callable(feedback_fn)
2065 4e338533 Michael Hanselmann
2066 4e338533 Michael Hanselmann
  def ReportLogMessage(self, job_id, serial, timestamp, log_type, log_msg):
2067 4e338533 Michael Hanselmann
    """Handles a log message.
2068 4e338533 Michael Hanselmann

2069 4e338533 Michael Hanselmann
    """
2070 4e338533 Michael Hanselmann
    self.feedback_fn((timestamp, log_type, log_msg))
2071 4e338533 Michael Hanselmann
2072 4e338533 Michael Hanselmann
  def ReportNotChanged(self, job_id, status):
2073 4e338533 Michael Hanselmann
    """Called if a job hasn't changed in a while.
2074 4e338533 Michael Hanselmann

2075 4e338533 Michael Hanselmann
    """
2076 4e338533 Michael Hanselmann
    # Ignore
2077 4e338533 Michael Hanselmann
2078 4e338533 Michael Hanselmann
2079 4e338533 Michael Hanselmann
class StdioJobPollReportCb(JobPollReportCbBase):
2080 4e338533 Michael Hanselmann
  def __init__(self):
2081 4e338533 Michael Hanselmann
    """Initializes this class.
2082 4e338533 Michael Hanselmann

2083 4e338533 Michael Hanselmann
    """
2084 4e338533 Michael Hanselmann
    JobPollReportCbBase.__init__(self)
2085 4e338533 Michael Hanselmann
2086 4e338533 Michael Hanselmann
    self.notified_queued = False
2087 4e338533 Michael Hanselmann
    self.notified_waitlock = False
2088 4e338533 Michael Hanselmann
2089 4e338533 Michael Hanselmann
  def ReportLogMessage(self, job_id, serial, timestamp, log_type, log_msg):
2090 4e338533 Michael Hanselmann
    """Handles a log message.
2091 4e338533 Michael Hanselmann

2092 4e338533 Michael Hanselmann
    """
2093 4e338533 Michael Hanselmann
    ToStdout("%s %s", time.ctime(utils.MergeTime(timestamp)),
2094 8a7f1c61 Michael Hanselmann
             FormatLogMessage(log_type, log_msg))
2095 4e338533 Michael Hanselmann
2096 4e338533 Michael Hanselmann
  def ReportNotChanged(self, job_id, status):
2097 4e338533 Michael Hanselmann
    """Called if a job hasn't changed in a while.
2098 4e338533 Michael Hanselmann

2099 4e338533 Michael Hanselmann
    """
2100 4e338533 Michael Hanselmann
    if status is None:
2101 4e338533 Michael Hanselmann
      return
2102 4e338533 Michael Hanselmann
2103 4e338533 Michael Hanselmann
    if status == constants.JOB_STATUS_QUEUED and not self.notified_queued:
2104 4e338533 Michael Hanselmann
      ToStderr("Job %s is waiting in queue", job_id)
2105 4e338533 Michael Hanselmann
      self.notified_queued = True
2106 4e338533 Michael Hanselmann
2107 47099cd1 Michael Hanselmann
    elif status == constants.JOB_STATUS_WAITING and not self.notified_waitlock:
2108 4e338533 Michael Hanselmann
      ToStderr("Job %s is trying to acquire all necessary locks", job_id)
2109 4e338533 Michael Hanselmann
      self.notified_waitlock = True
2110 4e338533 Michael Hanselmann
2111 4e338533 Michael Hanselmann
2112 8a7f1c61 Michael Hanselmann
def FormatLogMessage(log_type, log_msg):
2113 8a7f1c61 Michael Hanselmann
  """Formats a job message according to its type.
2114 8a7f1c61 Michael Hanselmann

2115 8a7f1c61 Michael Hanselmann
  """
2116 8a7f1c61 Michael Hanselmann
  if log_type != constants.ELOG_MESSAGE:
2117 8a7f1c61 Michael Hanselmann
    log_msg = str(log_msg)
2118 8a7f1c61 Michael Hanselmann
2119 8a7f1c61 Michael Hanselmann
  return utils.SafeEncode(log_msg)
2120 8a7f1c61 Michael Hanselmann
2121 8a7f1c61 Michael Hanselmann
2122 583163a6 Michael Hanselmann
def PollJob(job_id, cl=None, feedback_fn=None, reporter=None):
2123 4e338533 Michael Hanselmann
  """Function to poll for the result of a job.
2124 4e338533 Michael Hanselmann

2125 4e338533 Michael Hanselmann
  @type job_id: job identified
2126 4e338533 Michael Hanselmann
  @param job_id: the job to poll for results
2127 4e338533 Michael Hanselmann
  @type cl: luxi.Client
2128 4e338533 Michael Hanselmann
  @param cl: the luxi client to use for communicating with the master;
2129 4e338533 Michael Hanselmann
             if None, a new client will be created
2130 4e338533 Michael Hanselmann

2131 4e338533 Michael Hanselmann
  """
2132 4e338533 Michael Hanselmann
  if cl is None:
2133 4e338533 Michael Hanselmann
    cl = GetClient()
2134 4e338533 Michael Hanselmann
2135 583163a6 Michael Hanselmann
  if reporter is None:
2136 583163a6 Michael Hanselmann
    if feedback_fn:
2137 583163a6 Michael Hanselmann
      reporter = FeedbackFnJobPollReportCb(feedback_fn)
2138 583163a6 Michael Hanselmann
    else:
2139 583163a6 Michael Hanselmann
      reporter = StdioJobPollReportCb()
2140 583163a6 Michael Hanselmann
  elif feedback_fn:
2141 583163a6 Michael Hanselmann
    raise errors.ProgrammerError("Can't specify reporter and feedback function")
2142 4e338533 Michael Hanselmann
2143 4e338533 Michael Hanselmann
  return GenericPollJob(job_id, _LuxiJobPollCb(cl), reporter)
2144 ceab32dd Iustin Pop
2145 ceab32dd Iustin Pop
2146 583163a6 Michael Hanselmann
def SubmitOpCode(op, cl=None, feedback_fn=None, opts=None, reporter=None):
2147 0a1e74d9 Iustin Pop
  """Legacy function to submit an opcode.
2148 0a1e74d9 Iustin Pop

2149 0a1e74d9 Iustin Pop
  This is just a simple wrapper over the construction of the processor
2150 0a1e74d9 Iustin Pop
  instance. It should be extended to better handle feedback and
2151 0a1e74d9 Iustin Pop
  interaction functions.
2152 0a1e74d9 Iustin Pop

2153 0a1e74d9 Iustin Pop
  """
2154 0a1e74d9 Iustin Pop
  if cl is None:
2155 0a1e74d9 Iustin Pop
    cl = GetClient()
2156 0a1e74d9 Iustin Pop
2157 293ba2d8 Iustin Pop
  SetGenericOpcodeOpts([op], opts)
2158 293ba2d8 Iustin Pop
2159 5d297d8a Michael Hanselmann
  job_id = SendJob([op], cl=cl)
2160 0a1e74d9 Iustin Pop
2161 583163a6 Michael Hanselmann
  op_results = PollJob(job_id, cl=cl, feedback_fn=feedback_fn,
2162 583163a6 Michael Hanselmann
                       reporter=reporter)
2163 53c04d04 Iustin Pop
2164 53c04d04 Iustin Pop
  return op_results[0]
2165 0a1e74d9 Iustin Pop
2166 0a1e74d9 Iustin Pop
2167 94428652 Iustin Pop
def SubmitOrSend(op, opts, cl=None, feedback_fn=None):
2168 94428652 Iustin Pop
  """Wrapper around SubmitOpCode or SendJob.
2169 94428652 Iustin Pop

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

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

2178 94428652 Iustin Pop
  """
2179 94428652 Iustin Pop
  if opts and opts.submit_only:
2180 293ba2d8 Iustin Pop
    job = [op]
2181 293ba2d8 Iustin Pop
    SetGenericOpcodeOpts(job, opts)
2182 293ba2d8 Iustin Pop
    job_id = SendJob(job, cl=cl)
2183 e9d741b6 Iustin Pop
    raise JobSubmittedException(job_id)
2184 94428652 Iustin Pop
  else:
2185 293ba2d8 Iustin Pop
    return SubmitOpCode(op, cl=cl, feedback_fn=feedback_fn, opts=opts)
2186 293ba2d8 Iustin Pop
2187 293ba2d8 Iustin Pop
2188 293ba2d8 Iustin Pop
def SetGenericOpcodeOpts(opcode_list, options):
2189 293ba2d8 Iustin Pop
  """Processor for generic options.
2190 293ba2d8 Iustin Pop

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

2194 293ba2d8 Iustin Pop
  @param opcode_list: list of opcodes
2195 293ba2d8 Iustin Pop
  @param options: command line options or None
2196 293ba2d8 Iustin Pop
  @return: None (in-place modification)
2197 293ba2d8 Iustin Pop

2198 293ba2d8 Iustin Pop
  """
2199 293ba2d8 Iustin Pop
  if not options:
2200 293ba2d8 Iustin Pop
    return
2201 293ba2d8 Iustin Pop
  for op in opcode_list:
2202 aa06f8c6 Michael Hanselmann
    op.debug_level = options.debug
2203 a0a6ff34 Iustin Pop
    if hasattr(options, "dry_run"):
2204 a0a6ff34 Iustin Pop
      op.dry_run = options.dry_run
2205 aa06f8c6 Michael Hanselmann
    if getattr(options, "priority", None) is not None:
2206 552328b8 Michael Hanselmann
      op.priority = options.priority
2207 94428652 Iustin Pop
2208 94428652 Iustin Pop
2209 42ab9ac4 Iustin Pop
def GetClient(query=False):
2210 42ab9ac4 Iustin Pop
  """Connects to the a luxi socket and returns a client.
2211 42ab9ac4 Iustin Pop

2212 42ab9ac4 Iustin Pop
  @type query: boolean
2213 42ab9ac4 Iustin Pop
  @param query: this signifies that the client will only be
2214 42ab9ac4 Iustin Pop
      used for queries; if the build-time parameter
2215 42ab9ac4 Iustin Pop
      enable-split-queries is enabled, then the client will be
2216 42ab9ac4 Iustin Pop
      connected to the query socket instead of the masterd socket
2217 42ab9ac4 Iustin Pop

2218 42ab9ac4 Iustin Pop
  """
2219 42ab9ac4 Iustin Pop
  if query and constants.ENABLE_SPLIT_QUERY:
2220 ee4a14c0 Michael Hanselmann
    address = pathutils.QUERY_SOCKET
2221 42ab9ac4 Iustin Pop
  else:
2222 42ab9ac4 Iustin Pop
    address = None
2223 af30b2fd Michael Hanselmann
  # TODO: Cache object?
2224 b33e986b Iustin Pop
  try:
2225 42ab9ac4 Iustin Pop
    client = luxi.Client(address=address)
2226 b33e986b Iustin Pop
  except luxi.NoMasterError:
2227 d9a51679 Michael Hanselmann
    ss = ssconf.SimpleStore()
2228 d9a51679 Michael Hanselmann
2229 d9a51679 Michael Hanselmann
    # Try to read ssconf file
2230 d9a51679 Michael Hanselmann
    try:
2231 d9a51679 Michael Hanselmann
      ss.GetMasterNode()
2232 d9a51679 Michael Hanselmann
    except errors.ConfigurationError:
2233 d9a51679 Michael Hanselmann
      raise errors.OpPrereqError("Cluster not initialized or this machine is"
2234 2cfbc784 Iustin Pop
                                 " not part of a cluster",
2235 2cfbc784 Iustin Pop
                                 errors.ECODE_INVAL)
2236 d9a51679 Michael Hanselmann
2237 d9a51679 Michael Hanselmann
    master, myself = ssconf.GetMasterAndMyself(ss=ss)
2238 b33e986b Iustin Pop
    if master != myself:
2239 b33e986b Iustin Pop
      raise errors.OpPrereqError("This is not the master node, please connect"
2240 b33e986b Iustin Pop
                                 " to node '%s' and rerun the command" %
2241 2cfbc784 Iustin Pop
                                 master, errors.ECODE_INVAL)
2242 d9a51679 Michael Hanselmann
    raise
2243 b33e986b Iustin Pop
  return client
2244 af30b2fd Michael Hanselmann
2245 af30b2fd Michael Hanselmann
2246 73702ee7 Iustin Pop
def FormatError(err):
2247 73702ee7 Iustin Pop
  """Return a formatted error message for a given error.
2248 73702ee7 Iustin Pop

2249 73702ee7 Iustin Pop
  This function takes an exception instance and returns a tuple
2250 73702ee7 Iustin Pop
  consisting of two values: first, the recommended exit code, and
2251 73702ee7 Iustin Pop
  second, a string describing the error message (not
2252 73702ee7 Iustin Pop
  newline-terminated).
2253 73702ee7 Iustin Pop

2254 73702ee7 Iustin Pop
  """
2255 73702ee7 Iustin Pop
  retcode = 1
2256 73702ee7 Iustin Pop
  obuf = StringIO()
2257 e2e521d0 Iustin Pop
  msg = str(err)
2258 73702ee7 Iustin Pop
  if isinstance(err, errors.ConfigurationError):
2259 e2e521d0 Iustin Pop
    txt = "Corrupt configuration file: %s" % msg
2260 46fbdd04 Iustin Pop
    logging.error(txt)
2261 e2e521d0 Iustin Pop
    obuf.write(txt + "\n")
2262 73702ee7 Iustin Pop
    obuf.write("Aborting.")
2263 73702ee7 Iustin Pop
    retcode = 2
2264 73702ee7 Iustin Pop
  elif isinstance(err, errors.HooksAbort):
2265 73702ee7 Iustin Pop
    obuf.write("Failure: hooks execution failed:\n")
2266 73702ee7 Iustin Pop
    for node, script, out in err.args[0]:
2267 73702ee7 Iustin Pop
      if out:
2268 73702ee7 Iustin Pop
        obuf.write("  node: %s, script: %s, output: %s\n" %
2269 73702ee7 Iustin Pop
                   (node, script, out))
2270 73702ee7 Iustin Pop
      else:
2271 73702ee7 Iustin Pop
        obuf.write("  node: %s, script: %s (no output)\n" %
2272 73702ee7 Iustin Pop
                   (node, script))
2273 73702ee7 Iustin Pop
  elif isinstance(err, errors.HooksFailure):
2274 e2e521d0 Iustin Pop
    obuf.write("Failure: hooks general failure: %s" % msg)
2275 73702ee7 Iustin Pop
  elif isinstance(err, errors.ResolverError):
2276 b705c7a6 Manuel Franceschini
    this_host = netutils.Hostname.GetSysName()
2277 73702ee7 Iustin Pop
    if err.args[0] == this_host:
2278 73702ee7 Iustin Pop
      msg = "Failure: can't resolve my own hostname ('%s')"
2279 73702ee7 Iustin Pop
    else:
2280 73702ee7 Iustin Pop
      msg = "Failure: can't resolve hostname '%s'"
2281 73702ee7 Iustin Pop
    obuf.write(msg % err.args[0])
2282 73702ee7 Iustin Pop
  elif isinstance(err, errors.OpPrereqError):
2283 5c983ee5 Iustin Pop
    if len(err.args) == 2:
2284 5c983ee5 Iustin Pop
      obuf.write("Failure: prerequisites not met for this"
2285 5ae4945a Iustin Pop
                 " operation:\nerror type: %s, error details:\n%s" %
2286 5c983ee5 Iustin Pop
                 (err.args[1], err.args[0]))
2287 5c983ee5 Iustin Pop
    else:
2288 5c983ee5 Iustin Pop
      obuf.write("Failure: prerequisites not met for this"
2289 5c983ee5 Iustin Pop
                 " operation:\n%s" % msg)
2290 73702ee7 Iustin Pop
  elif isinstance(err, errors.OpExecError):
2291 e2e521d0 Iustin Pop
    obuf.write("Failure: command execution error:\n%s" % msg)
2292 73702ee7 Iustin Pop
  elif isinstance(err, errors.TagError):
2293 e2e521d0 Iustin Pop
    obuf.write("Failure: invalid tag(s) given:\n%s" % msg)
2294 686d7433 Iustin Pop
  elif isinstance(err, errors.JobQueueDrainError):
2295 686d7433 Iustin Pop
    obuf.write("Failure: the job queue is marked for drain and doesn't"
2296 686d7433 Iustin Pop
               " accept new requests\n")
2297 f87b405e Michael Hanselmann
  elif isinstance(err, errors.JobQueueFull):
2298 f87b405e Michael Hanselmann
    obuf.write("Failure: the job queue is full and doesn't accept new"
2299 f87b405e Michael Hanselmann
               " job submissions until old jobs are archived\n")
2300 a5728081 Guido Trotter
  elif isinstance(err, errors.TypeEnforcementError):
2301 a5728081 Guido Trotter
    obuf.write("Parameter Error: %s" % msg)
2302 c1ce76bb Iustin Pop
  elif isinstance(err, errors.ParameterError):
2303 c1ce76bb Iustin Pop
    obuf.write("Failure: unknown/wrong parameter name '%s'" % msg)
2304 03a8dbdc Iustin Pop
  elif isinstance(err, luxi.NoMasterError):
2305 7f5edc60 Iustin Pop
    if err.args[0] == pathutils.MASTER_SOCKET:
2306 7f5edc60 Iustin Pop
      daemon = "master"
2307 7f5edc60 Iustin Pop
    else:
2308 7f5edc60 Iustin Pop
      daemon = "config"
2309 7f5edc60 Iustin Pop
    obuf.write("Cannot communicate with the %s daemon.\nIs it running"
2310 7f5edc60 Iustin Pop
               " and listening for connections?" % daemon)
2311 03a8dbdc Iustin Pop
  elif isinstance(err, luxi.TimeoutError):
2312 cd4c86a8 Michael Hanselmann
    obuf.write("Timeout while talking to the master daemon. Jobs might have"
2313 cd4c86a8 Michael Hanselmann
               " been submitted and will continue to run even if the call"
2314 cd4c86a8 Michael Hanselmann
               " timed out. Useful commands in this situation are \"gnt-job"
2315 cd4c86a8 Michael Hanselmann
               " list\", \"gnt-job cancel\" and \"gnt-job watch\". Error:\n")
2316 cd4c86a8 Michael Hanselmann
    obuf.write(msg)
2317 5a1c22fe Iustin Pop
  elif isinstance(err, luxi.PermissionError):
2318 5a1c22fe Iustin Pop
    obuf.write("It seems you don't have permissions to connect to the"
2319 5a1c22fe Iustin Pop
               " master daemon.\nPlease retry as a different user.")
2320 03a8dbdc Iustin Pop
  elif isinstance(err, luxi.ProtocolError):
2321 03a8dbdc Iustin Pop
    obuf.write("Unhandled protocol error while talking to the master daemon:\n"
2322 03a8dbdc Iustin Pop
               "%s" % msg)
2323 91c622a8 Iustin Pop
  elif isinstance(err, errors.JobLost):
2324 91c622a8 Iustin Pop
    obuf.write("Error checking job status: %s" % msg)
2325 cb1e6c3c Michael Hanselmann
  elif isinstance(err, errors.QueryFilterParseError):
2326 cb1e6c3c Michael Hanselmann
    obuf.write("Error while parsing query filter: %s\n" % err.args[0])
2327 cb1e6c3c Michael Hanselmann
    obuf.write("\n".join(err.GetDetails()))
2328 797506fc Michael Hanselmann
  elif isinstance(err, errors.GenericError):
2329 797506fc Michael Hanselmann
    obuf.write("Unhandled Ganeti error: %s" % msg)
2330 e9d741b6 Iustin Pop
  elif isinstance(err, JobSubmittedException):
2331 e9d741b6 Iustin Pop
    obuf.write("JobID: %s\n" % err.args[0])
2332 e9d741b6 Iustin Pop
    retcode = 0
2333 73702ee7 Iustin Pop
  else:
2334 e2e521d0 Iustin Pop
    obuf.write("Unhandled exception: %s" % msg)
2335 d0c8c01d Iustin Pop
  return retcode, obuf.getvalue().rstrip("\n")
2336 73702ee7 Iustin Pop
2337 73702ee7 Iustin Pop
2338 ef9fa5b9 René Nussbaumer
def GenericMain(commands, override=None, aliases=None,
2339 ef9fa5b9 René Nussbaumer
                env_override=frozenset()):
2340 a8083063 Iustin Pop
  """Generic main function for all the gnt-* commands.
2341 a8083063 Iustin Pop

2342 ef9fa5b9 René Nussbaumer
  @param commands: a dictionary with a special structure, see the design doc
2343 ef9fa5b9 René Nussbaumer
                   for command line handling.
2344 ef9fa5b9 René Nussbaumer
  @param override: if not None, we expect a dictionary with keys that will
2345 ef9fa5b9 René Nussbaumer
                   override command line options; this can be used to pass
2346 ef9fa5b9 René Nussbaumer
                   options from the scripts to generic functions
2347 ef9fa5b9 René Nussbaumer
  @param aliases: dictionary with command aliases {'alias': 'target, ...}
2348 ef9fa5b9 René Nussbaumer
  @param env_override: list of environment names which are allowed to submit
2349 ef9fa5b9 René Nussbaumer
                       default args for commands
2350 a8083063 Iustin Pop

2351 a8083063 Iustin Pop
  """
2352 a8083063 Iustin Pop
  # save the program name and the entire command line for later logging
2353 a8083063 Iustin Pop
  if sys.argv:
2354 c1f19851 Michael Hanselmann
    binary = os.path.basename(sys.argv[0])
2355 c1f19851 Michael Hanselmann
    if not binary:
2356 c1f19851 Michael Hanselmann
      binary = sys.argv[0]
2357 c1f19851 Michael Hanselmann
2358 a8083063 Iustin Pop
    if len(sys.argv) >= 2:
2359 c1f19851 Michael Hanselmann
      logname = utils.ShellQuoteArgs([binary, sys.argv[1]])
2360 a8083063 Iustin Pop
    else:
2361 c1f19851 Michael Hanselmann
      logname = binary
2362 c1f19851 Michael Hanselmann
2363 c1f19851 Michael Hanselmann
    cmdline = utils.ShellQuoteArgs([binary] + sys.argv[1:])
2364 a8083063 Iustin Pop
  else:
2365 a8083063 Iustin Pop
    binary = "<unknown program>"
2366 c1f19851 Michael Hanselmann
    cmdline = "<unknown>"
2367 a8083063 Iustin Pop
2368 de47cf8f Guido Trotter
  if aliases is None:
2369 de47cf8f Guido Trotter
    aliases = {}
2370 de47cf8f Guido Trotter
2371 3126878d Guido Trotter
  try:
2372 d971402f Michael Hanselmann
    (func, options, args) = _ParseArgs(binary, sys.argv, commands, aliases,
2373 d971402f Michael Hanselmann
                                       env_override)
2374 d971402f Michael Hanselmann
  except _ShowVersion:
2375 d971402f Michael Hanselmann
    ToStdout("%s (ganeti %s) %s", binary, constants.VCS_VERSION,
2376 d971402f Michael Hanselmann
             constants.RELEASE_VERSION)
2377 d971402f Michael Hanselmann
    return constants.EXIT_SUCCESS
2378 d971402f Michael Hanselmann
  except _ShowUsage, err:
2379 d971402f Michael Hanselmann
    for line in _FormatUsage(binary, commands):
2380 d971402f Michael Hanselmann
      ToStdout(line)
2381 d971402f Michael Hanselmann
2382 d971402f Michael Hanselmann
    if err.exit_error:
2383 d971402f Michael Hanselmann
      return constants.EXIT_FAILURE
2384 d971402f Michael Hanselmann
    else:
2385 d971402f Michael Hanselmann
      return constants.EXIT_SUCCESS
2386 3126878d Guido Trotter
  except errors.ParameterError, err:
2387 3126878d Guido Trotter
    result, err_msg = FormatError(err)
2388 3126878d Guido Trotter
    ToStderr(err_msg)
2389 3126878d Guido Trotter
    return 1
2390 3126878d Guido Trotter
2391 a8083063 Iustin Pop
  if func is None: # parse error
2392 a8083063 Iustin Pop
    return 1
2393 a8083063 Iustin Pop
2394 334d1483 Iustin Pop
  if override is not None:
2395 334d1483 Iustin Pop
    for key, val in override.iteritems():
2396 334d1483 Iustin Pop
      setattr(options, key, val)
2397 334d1483 Iustin Pop
2398 ee4a14c0 Michael Hanselmann
  utils.SetupLogging(pathutils.LOG_COMMANDS, logname, debug=options.debug,
2399 cfcc79c6 Michael Hanselmann
                     stderr_logging=True)
2400 a8083063 Iustin Pop
2401 c1f19851 Michael Hanselmann
  logging.info("Command line: %s", cmdline)
2402 a8083063 Iustin Pop
2403 a8083063 Iustin Pop
  try:
2404 a4af651e Iustin Pop
    result = func(options, args)
2405 d8353c3a Iustin Pop
  except (errors.GenericError, luxi.ProtocolError,
2406 d8353c3a Iustin Pop
          JobSubmittedException), err:
2407 a4af651e Iustin Pop
    result, err_msg = FormatError(err)
2408 5bbd3f7f Michael Hanselmann
    logging.exception("Error during command processing")
2409 46fbdd04 Iustin Pop
    ToStderr(err_msg)
2410 8a53b55f Iustin Pop
  except KeyboardInterrupt:
2411 8a53b55f Iustin Pop
    result = constants.EXIT_FAILURE
2412 8a53b55f Iustin Pop
    ToStderr("Aborted. Note that if the operation created any jobs, they"
2413 8a53b55f Iustin Pop
             " might have been submitted and"
2414 8a53b55f Iustin Pop
             " will continue to run in the background.")
2415 225e2544 Iustin Pop
  except IOError, err:
2416 225e2544 Iustin Pop
    if err.errno == errno.EPIPE:
2417 225e2544 Iustin Pop
      # our terminal went away, we'll exit
2418 225e2544 Iustin Pop
      sys.exit(constants.EXIT_FAILURE)
2419 225e2544 Iustin Pop
    else:
2420 225e2544 Iustin Pop
      raise
2421 a8083063 Iustin Pop
2422 a8083063 Iustin Pop
  return result
2423 137161c9 Michael Hanselmann
2424 137161c9 Michael Hanselmann
2425 845c79d8 Michael Hanselmann
def ParseNicOption(optvalue):
2426 845c79d8 Michael Hanselmann
  """Parses the value of the --net option(s).
2427 845c79d8 Michael Hanselmann

2428 845c79d8 Michael Hanselmann
  """
2429 845c79d8 Michael Hanselmann
  try:
2430 845c79d8 Michael Hanselmann
    nic_max = max(int(nidx[0]) + 1 for nidx in optvalue)
2431 845c79d8 Michael Hanselmann
  except (TypeError, ValueError), err:
2432 2cfbc784 Iustin Pop
    raise errors.OpPrereqError("Invalid NIC index passed: %s" % str(err),
2433 2cfbc784 Iustin Pop
                               errors.ECODE_INVAL)
2434 845c79d8 Michael Hanselmann
2435 845c79d8 Michael Hanselmann
  nics = [{}] * nic_max
2436 845c79d8 Michael Hanselmann
  for nidx, ndict in optvalue:
2437 845c79d8 Michael Hanselmann
    nidx = int(nidx)
2438 845c79d8 Michael Hanselmann
2439 845c79d8 Michael Hanselmann
    if not isinstance(ndict, dict):
2440 845c79d8 Michael Hanselmann
      raise errors.OpPrereqError("Invalid nic/%d value: expected dict,"
2441 2cfbc784 Iustin Pop
                                 " got %s" % (nidx, ndict), errors.ECODE_INVAL)
2442 845c79d8 Michael Hanselmann
2443 845c79d8 Michael Hanselmann
    utils.ForceDictType(ndict, constants.INIC_PARAMS_TYPES)
2444 845c79d8 Michael Hanselmann
2445 845c79d8 Michael Hanselmann
    nics[nidx] = ndict
2446 845c79d8 Michael Hanselmann
2447 845c79d8 Michael Hanselmann
  return nics
2448 845c79d8 Michael Hanselmann
2449 845c79d8 Michael Hanselmann
2450 d77490c5 Iustin Pop
def GenericInstanceCreate(mode, opts, args):
2451 d77490c5 Iustin Pop
  """Add an instance to the cluster via either creation or import.
2452 d77490c5 Iustin Pop

2453 d77490c5 Iustin Pop
  @param mode: constants.INSTANCE_CREATE or constants.INSTANCE_IMPORT
2454 d77490c5 Iustin Pop
  @param opts: the command line options selected by the user
2455 d77490c5 Iustin Pop
  @type args: list
2456 d77490c5 Iustin Pop
  @param args: should contain only one element, the new instance name
2457 d77490c5 Iustin Pop
  @rtype: int
2458 d77490c5 Iustin Pop
  @return: the desired exit code
2459 d77490c5 Iustin Pop

2460 d77490c5 Iustin Pop
  """
2461 d77490c5 Iustin Pop
  instance = args[0]
2462 d77490c5 Iustin Pop
2463 d77490c5 Iustin Pop
  (pnode, snode) = SplitNodeOption(opts.node)
2464 d77490c5 Iustin Pop
2465 d77490c5 Iustin Pop
  hypervisor = None
2466 d77490c5 Iustin Pop
  hvparams = {}
2467 d77490c5 Iustin Pop
  if opts.hypervisor:
2468 d77490c5 Iustin Pop
    hypervisor, hvparams = opts.hypervisor
2469 d77490c5 Iustin Pop
2470 d77490c5 Iustin Pop
  if opts.nics:
2471 845c79d8 Michael Hanselmann
    nics = ParseNicOption(opts.nics)
2472 d77490c5 Iustin Pop
  elif opts.no_nics:
2473 d77490c5 Iustin Pop
    # no nics
2474 d77490c5 Iustin Pop
    nics = []
2475 0af0f641 Iustin Pop
  elif mode == constants.INSTANCE_CREATE:
2476 d77490c5 Iustin Pop
    # default of one nic, all auto
2477 d77490c5 Iustin Pop
    nics = [{}]
2478 0af0f641 Iustin Pop
  else:
2479 0af0f641 Iustin Pop
    # mode == import
2480 0af0f641 Iustin Pop
    nics = []
2481 d77490c5 Iustin Pop
2482 d77490c5 Iustin Pop
  if opts.disk_template == constants.DT_DISKLESS:
2483 d77490c5 Iustin Pop
    if opts.disks or opts.sd_size is not None:
2484 d77490c5 Iustin Pop
      raise errors.OpPrereqError("Diskless instance but disk"
2485 2cfbc784 Iustin Pop
                                 " information passed", errors.ECODE_INVAL)
2486 d77490c5 Iustin Pop
    disks = []
2487 d77490c5 Iustin Pop
  else:
2488 9b12ed0f Iustin Pop
    if (not opts.disks and not opts.sd_size
2489 9b12ed0f Iustin Pop
        and mode == constants.INSTANCE_CREATE):
2490 2cfbc784 Iustin Pop
      raise errors.OpPrereqError("No disk information specified",
2491 2cfbc784 Iustin Pop
                                 errors.ECODE_INVAL)
2492 d77490c5 Iustin Pop
    if opts.disks and opts.sd_size is not None:
2493 d77490c5 Iustin Pop
      raise errors.OpPrereqError("Please use either the '--disk' or"
2494 2cfbc784 Iustin Pop
                                 " '-s' option", errors.ECODE_INVAL)
2495 d77490c5 Iustin Pop
    if opts.sd_size is not None:
2496 ccfa86ba Michael Hanselmann
      opts.disks = [(0, {constants.IDISK_SIZE: opts.sd_size})]
2497 9b12ed0f Iustin Pop
2498 9b12ed0f Iustin Pop
    if opts.disks:
2499 9b12ed0f Iustin Pop
      try:
2500 9b12ed0f Iustin Pop
        disk_max = max(int(didx[0]) + 1 for didx in opts.disks)
2501 9b12ed0f Iustin Pop
      except ValueError, err:
2502 2cfbc784 Iustin Pop
        raise errors.OpPrereqError("Invalid disk index passed: %s" % str(err),
2503 2cfbc784 Iustin Pop
                                   errors.ECODE_INVAL)
2504 9b12ed0f Iustin Pop
      disks = [{}] * disk_max
2505 9b12ed0f Iustin Pop
    else:
2506 9b12ed0f Iustin Pop
      disks = []
2507 d77490c5 Iustin Pop
    for didx, ddict in opts.disks:
2508 d77490c5 Iustin Pop
      didx = int(didx)
2509 d77490c5 Iustin Pop
      if not isinstance(ddict, dict):
2510 d77490c5 Iustin Pop
        msg = "Invalid disk/%d value: expected dict, got %s" % (didx, ddict)
2511 2cfbc784 Iustin Pop
        raise errors.OpPrereqError(msg, errors.ECODE_INVAL)
2512 ccfa86ba Michael Hanselmann
      elif constants.IDISK_SIZE in ddict:
2513 ccfa86ba Michael Hanselmann
        if constants.IDISK_ADOPT in ddict:
2514 5029db65 Iustin Pop
          raise errors.OpPrereqError("Only one of 'size' and 'adopt' allowed"
2515 2cfbc784 Iustin Pop
                                     " (disk %d)" % didx, errors.ECODE_INVAL)
2516 5029db65 Iustin Pop
        try:
2517 ccfa86ba Michael Hanselmann
          ddict[constants.IDISK_SIZE] = \
2518 ccfa86ba Michael Hanselmann
            utils.ParseUnit(ddict[constants.IDISK_SIZE])
2519 5029db65 Iustin Pop
        except ValueError, err:
2520 5029db65 Iustin Pop
          raise errors.OpPrereqError("Invalid disk size for disk %d: %s" %
2521 2cfbc784 Iustin Pop
                                     (didx, err), errors.ECODE_INVAL)
2522 ccfa86ba Michael Hanselmann
      elif constants.IDISK_ADOPT in ddict:
2523 5029db65 Iustin Pop
        if mode == constants.INSTANCE_IMPORT:
2524 5029db65 Iustin Pop
          raise errors.OpPrereqError("Disk adoption not allowed for instance"
2525 2cfbc784 Iustin Pop
                                     " import", errors.ECODE_INVAL)
2526 ccfa86ba Michael Hanselmann
        ddict[constants.IDISK_SIZE] = 0
2527 5029db65 Iustin Pop
      else:
2528 5029db65 Iustin Pop
        raise errors.OpPrereqError("Missing size or adoption source for"
2529 2cfbc784 Iustin Pop
                                   " disk %d" % didx, errors.ECODE_INVAL)
2530 d77490c5 Iustin Pop
      disks[didx] = ddict
2531 d77490c5 Iustin Pop
2532 a57981c5 Apollon Oikonomopoulos
  if opts.tags is not None:
2533 0f8810df Michael Hanselmann
    tags = opts.tags.split(",")
2534 a57981c5 Apollon Oikonomopoulos
  else:
2535 a57981c5 Apollon Oikonomopoulos
    tags = []
2536 a57981c5 Apollon Oikonomopoulos
2537 b2e233a5 Guido Trotter
  utils.ForceDictType(opts.beparams, constants.BES_PARAMETER_COMPAT)
2538 d77490c5 Iustin Pop
  utils.ForceDictType(hvparams, constants.HVS_PARAMETER_TYPES)
2539 d77490c5 Iustin Pop
2540 d77490c5 Iustin Pop
  if mode == constants.INSTANCE_CREATE:
2541 d77490c5 Iustin Pop
    start = opts.start
2542 d77490c5 Iustin Pop
    os_type = opts.os
2543 1ee8e01a Guido Trotter
    force_variant = opts.force_variant
2544 d77490c5 Iustin Pop
    src_node = None
2545 d77490c5 Iustin Pop
    src_path = None
2546 25a8792c Iustin Pop
    no_install = opts.no_install
2547 e588764d Iustin Pop
    identify_defaults = False
2548 d77490c5 Iustin Pop
  elif mode == constants.INSTANCE_IMPORT:
2549 d77490c5 Iustin Pop
    start = False
2550 d77490c5 Iustin Pop
    os_type = None
2551 1ee8e01a Guido Trotter
    force_variant = False
2552 d77490c5 Iustin Pop
    src_node = opts.src_node
2553 d77490c5 Iustin Pop
    src_path = opts.src_dir
2554 25a8792c Iustin Pop
    no_install = None
2555 e588764d Iustin Pop
    identify_defaults = opts.identify_defaults
2556 d77490c5 Iustin Pop
  else:
2557 d77490c5 Iustin Pop
    raise errors.ProgrammerError("Invalid creation mode %s" % mode)
2558 d77490c5 Iustin Pop
2559 e1530b10 Iustin Pop
  op = opcodes.OpInstanceCreate(instance_name=instance,
2560 d77490c5 Iustin Pop
                                disks=disks,
2561 d77490c5 Iustin Pop
                                disk_template=opts.disk_template,
2562 d77490c5 Iustin Pop
                                nics=nics,
2563 d4117a72 Apollon Oikonomopoulos
                                conflicts_check=opts.conflicts_check,
2564 d77490c5 Iustin Pop
                                pnode=pnode, snode=snode,
2565 d77490c5 Iustin Pop
                                ip_check=opts.ip_check,
2566 460d22be Iustin Pop
                                name_check=opts.name_check,
2567 d77490c5 Iustin Pop
                                wait_for_sync=opts.wait_for_sync,
2568 d77490c5 Iustin Pop
                                file_storage_dir=opts.file_storage_dir,
2569 d77490c5 Iustin Pop
                                file_driver=opts.file_driver,
2570 d77490c5 Iustin Pop
                                iallocator=opts.iallocator,
2571 d77490c5 Iustin Pop
                                hypervisor=hypervisor,
2572 d77490c5 Iustin Pop
                                hvparams=hvparams,
2573 d77490c5 Iustin Pop
                                beparams=opts.beparams,
2574 062a7100 Iustin Pop
                                osparams=opts.osparams,
2575 d77490c5 Iustin Pop
                                mode=mode,
2576 d77490c5 Iustin Pop
                                start=start,
2577 d77490c5 Iustin Pop
                                os_type=os_type,
2578 1ee8e01a Guido Trotter
                                force_variant=force_variant,
2579 d77490c5 Iustin Pop
                                src_node=src_node,
2580 25a8792c Iustin Pop
                                src_path=src_path,
2581 a57981c5 Apollon Oikonomopoulos
                                tags=tags,
2582 e588764d Iustin Pop
                                no_install=no_install,
2583 10889e0c René Nussbaumer
                                identify_defaults=identify_defaults,
2584 10889e0c René Nussbaumer
                                ignore_ipolicy=opts.ignore_ipolicy)
2585 d77490c5 Iustin Pop
2586 d77490c5 Iustin Pop
  SubmitOrSend(op, opts)
2587 d77490c5 Iustin Pop
  return 0
2588 d77490c5 Iustin Pop
2589 d77490c5 Iustin Pop
2590 7e49b6ce Michael Hanselmann
class _RunWhileClusterStoppedHelper:
2591 7e49b6ce Michael Hanselmann
  """Helper class for L{RunWhileClusterStopped} to simplify state management
2592 7e49b6ce Michael Hanselmann

2593 7e49b6ce Michael Hanselmann
  """
2594 7e49b6ce Michael Hanselmann
  def __init__(self, feedback_fn, cluster_name, master_node, online_nodes):
2595 7e49b6ce Michael Hanselmann
    """Initializes this class.
2596 7e49b6ce Michael Hanselmann

2597 7e49b6ce Michael Hanselmann
    @type feedback_fn: callable
2598 7e49b6ce Michael Hanselmann
    @param feedback_fn: Feedback function
2599 7e49b6ce Michael Hanselmann
    @type cluster_name: string
2600 7e49b6ce Michael Hanselmann
    @param cluster_name: Cluster name
2601 7e49b6ce Michael Hanselmann
    @type master_node: string
2602 7e49b6ce Michael Hanselmann
    @param master_node Master node name
2603 7e49b6ce Michael Hanselmann
    @type online_nodes: list
2604 7e49b6ce Michael Hanselmann
    @param online_nodes: List of names of online nodes
2605 7e49b6ce Michael Hanselmann

2606 7e49b6ce Michael Hanselmann
    """
2607 7e49b6ce Michael Hanselmann
    self.feedback_fn = feedback_fn
2608 7e49b6ce Michael Hanselmann
    self.cluster_name = cluster_name
2609 7e49b6ce Michael Hanselmann
    self.master_node = master_node
2610 7e49b6ce Michael Hanselmann
    self.online_nodes = online_nodes
2611 7e49b6ce Michael Hanselmann
2612 7e49b6ce Michael Hanselmann
    self.ssh = ssh.SshRunner(self.cluster_name)
2613 7e49b6ce Michael Hanselmann
2614 7e49b6ce Michael Hanselmann
    self.nonmaster_nodes = [name for name in online_nodes
2615 7e49b6ce Michael Hanselmann
                            if name != master_node]
2616 7e49b6ce Michael Hanselmann
2617 7e49b6ce Michael Hanselmann
    assert self.master_node not in self.nonmaster_nodes
2618 7e49b6ce Michael Hanselmann
2619 7e49b6ce Michael Hanselmann
  def _RunCmd(self, node_name, cmd):
2620 7e49b6ce Michael Hanselmann
    """Runs a command on the local or a remote machine.
2621 7e49b6ce Michael Hanselmann

2622 7e49b6ce Michael Hanselmann
    @type node_name: string
2623 7e49b6ce Michael Hanselmann
    @param node_name: Machine name
2624 7e49b6ce Michael Hanselmann
    @type cmd: list
2625 7e49b6ce Michael Hanselmann
    @param cmd: Command
2626 7e49b6ce Michael Hanselmann

2627 7e49b6ce Michael Hanselmann
    """
2628 7e49b6ce Michael Hanselmann
    if node_name is None or node_name == self.master_node:
2629 7e49b6ce Michael Hanselmann
      # No need to use SSH
2630 7e49b6ce Michael Hanselmann
      result = utils.RunCmd(cmd)
2631 7e49b6ce Michael Hanselmann
    else:
2632 052783ff Michael Hanselmann
      result = self.ssh.Run(node_name, constants.SSH_LOGIN_USER,
2633 052783ff Michael Hanselmann
                            utils.ShellQuoteArgs(cmd))
2634 7e49b6ce Michael Hanselmann
2635 7e49b6ce Michael Hanselmann
    if result.failed:
2636 7e49b6ce Michael Hanselmann
      errmsg = ["Failed to run command %s" % result.cmd]
2637 7e49b6ce Michael Hanselmann
      if node_name:
2638 7e49b6ce Michael Hanselmann
        errmsg.append("on node %s" % node_name)
2639 7e49b6ce Michael Hanselmann
      errmsg.append(": exitcode %s and error %s" %
2640 7e49b6ce Michael Hanselmann
                    (result.exit_code, result.output))
2641 7e49b6ce Michael Hanselmann
      raise errors.OpExecError(" ".join(errmsg))
2642 7e49b6ce Michael Hanselmann
2643 7e49b6ce Michael Hanselmann
  def Call(self, fn, *args):
2644 7e49b6ce Michael Hanselmann
    """Call function while all daemons are stopped.
2645 7e49b6ce Michael Hanselmann

2646 7e49b6ce Michael Hanselmann
    @type fn: callable
2647 7e49b6ce Michael Hanselmann
    @param fn: Function to be called
2648 7e49b6ce Michael Hanselmann

2649 7e49b6ce Michael Hanselmann
    """
2650 7e49b6ce Michael Hanselmann
    # Pause watcher by acquiring an exclusive lock on watcher state file
2651 7e49b6ce Michael Hanselmann
    self.feedback_fn("Blocking watcher")
2652 ee4a14c0 Michael Hanselmann
    watcher_block = utils.FileLock.Open(pathutils.WATCHER_LOCK_FILE)
2653 7e49b6ce Michael Hanselmann
    try:
2654 7e49b6ce Michael Hanselmann
      # TODO: Currently, this just blocks. There's no timeout.
2655 7e49b6ce Michael Hanselmann
      # TODO: Should it be a shared lock?
2656 7e49b6ce Michael Hanselmann
      watcher_block.Exclusive(blocking=True)
2657 7e49b6ce Michael Hanselmann
2658 7e49b6ce Michael Hanselmann
      # Stop master daemons, so that no new jobs can come in and all running
2659 7e49b6ce Michael Hanselmann
      # ones are finished
2660 7e49b6ce Michael Hanselmann
      self.feedback_fn("Stopping master daemons")
2661 ee4a14c0 Michael Hanselmann
      self._RunCmd(None, [pathutils.DAEMON_UTIL, "stop-master"])
2662 7e49b6ce Michael Hanselmann
      try:
2663 7e49b6ce Michael Hanselmann
        # Stop daemons on all nodes
2664 7e49b6ce Michael Hanselmann
        for node_name in self.online_nodes:
2665 7e49b6ce Michael Hanselmann
          self.feedback_fn("Stopping daemons on %s" % node_name)
2666 ee4a14c0 Michael Hanselmann
          self._RunCmd(node_name, [pathutils.DAEMON_UTIL, "stop-all"])
2667 7e49b6ce Michael Hanselmann
2668 7e49b6ce Michael Hanselmann
        # All daemons are shut down now
2669 7e49b6ce Michael Hanselmann
        try:
2670 7e49b6ce Michael Hanselmann
          return fn(self, *args)
2671 d512e84b Michael Hanselmann
        except Exception, err:
2672 d512e84b Michael Hanselmann
          _, errmsg = FormatError(err)
2673 7e49b6ce Michael Hanselmann
          logging.exception("Caught exception")
2674 d512e84b Michael Hanselmann
          self.feedback_fn(errmsg)
2675 7e49b6ce Michael Hanselmann
          raise
2676 7e49b6ce Michael Hanselmann
      finally:
2677 7e49b6ce Michael Hanselmann
        # Start cluster again, master node last
2678 7e49b6ce Michael Hanselmann
        for node_name in self.nonmaster_nodes + [self.master_node]:
2679 7e49b6ce Michael Hanselmann
          self.feedback_fn("Starting daemons on %s" % node_name)
2680 ee4a14c0 Michael Hanselmann
          self._RunCmd(node_name, [pathutils.DAEMON_UTIL, "start-all"])
2681 7e49b6ce Michael Hanselmann
    finally:
2682 7e49b6ce Michael Hanselmann
      # Resume watcher
2683 7e49b6ce Michael Hanselmann
      watcher_block.Close()
2684 7e49b6ce Michael Hanselmann
2685 7e49b6ce Michael Hanselmann
2686 7e49b6ce Michael Hanselmann
def RunWhileClusterStopped(feedback_fn, fn, *args):
2687 7e49b6ce Michael Hanselmann
  """Calls a function while all cluster daemons are stopped.
2688 7e49b6ce Michael Hanselmann

2689 7e49b6ce Michael Hanselmann
  @type feedback_fn: callable
2690 7e49b6ce Michael Hanselmann
  @param feedback_fn: Feedback function
2691 7e49b6ce Michael Hanselmann
  @type fn: callable
2692 7e49b6ce Michael Hanselmann
  @param fn: Function to be called when daemons are stopped
2693 7e49b6ce Michael Hanselmann

2694 7e49b6ce Michael Hanselmann
  """
2695 7e49b6ce Michael Hanselmann
  feedback_fn("Gathering cluster information")
2696 7e49b6ce Michael Hanselmann
2697 7e49b6ce Michael Hanselmann
  # This ensures we're running on the master daemon
2698 7e49b6ce Michael Hanselmann
  cl = GetClient()
2699 7e49b6ce Michael Hanselmann
2700 7e49b6ce Michael Hanselmann
  (cluster_name, master_node) = \
2701 7e49b6ce Michael Hanselmann
    cl.QueryConfigValues(["cluster_name", "master_node"])
2702 7e49b6ce Michael Hanselmann
2703 7e49b6ce Michael Hanselmann
  online_nodes = GetOnlineNodes([], cl=cl)
2704 7e49b6ce Michael Hanselmann
2705 7e49b6ce Michael Hanselmann
  # Don't keep a reference to the client. The master daemon will go away.
2706 7e49b6ce Michael Hanselmann
  del cl
2707 7e49b6ce Michael Hanselmann
2708 7e49b6ce Michael Hanselmann
  assert master_node in online_nodes
2709 7e49b6ce Michael Hanselmann
2710 7e49b6ce Michael Hanselmann
  return _RunWhileClusterStoppedHelper(feedback_fn, cluster_name, master_node,
2711 7e49b6ce Michael Hanselmann
                                       online_nodes).Call(fn, *args)
2712 7e49b6ce Michael Hanselmann
2713 7e49b6ce Michael Hanselmann
2714 16be8703 Iustin Pop
def GenerateTable(headers, fields, separator, data,
2715 9fbfbb7b Iustin Pop
                  numfields=None, unitfields=None,
2716 9fbfbb7b Iustin Pop
                  units=None):
2717 137161c9 Michael Hanselmann
  """Prints a table with headers and different fields.
2718 137161c9 Michael Hanselmann

2719 9fbfbb7b Iustin Pop
  @type headers: dict
2720 9fbfbb7b Iustin Pop
  @param headers: dictionary mapping field names to headers for
2721 9fbfbb7b Iustin Pop
      the table
2722 9fbfbb7b Iustin Pop
  @type fields: list
2723 9fbfbb7b Iustin Pop
  @param fields: the field names corresponding to each row in
2724 9fbfbb7b Iustin Pop
      the data field
2725 9fbfbb7b Iustin Pop
  @param separator: the separator to be used; if this is None,
2726 9fbfbb7b Iustin Pop
      the default 'smart' algorithm is used which computes optimal
2727 9fbfbb7b Iustin Pop
      field width, otherwise just the separator is used between
2728 9fbfbb7b Iustin Pop
      each field
2729 9fbfbb7b Iustin Pop
  @type data: list
2730 9fbfbb7b Iustin Pop
  @param data: a list of lists, each sublist being one row to be output
2731 9fbfbb7b Iustin Pop
  @type numfields: list
2732 9fbfbb7b Iustin Pop
  @param numfields: a list with the fields that hold numeric
2733 9fbfbb7b Iustin Pop
      values and thus should be right-aligned
2734 9fbfbb7b Iustin Pop
  @type unitfields: list
2735 9fbfbb7b Iustin Pop
  @param unitfields: a list with the fields that hold numeric
2736 9fbfbb7b Iustin Pop
      values that should be formatted with the units field
2737 9fbfbb7b Iustin Pop
  @type units: string or None
2738 9fbfbb7b Iustin Pop
  @param units: the units we should use for formatting, or None for
2739 9fbfbb7b Iustin Pop
      automatic choice (human-readable for non-separator usage, otherwise
2740 9fbfbb7b Iustin Pop
      megabytes); this is a one-letter string
2741 137161c9 Michael Hanselmann

2742 137161c9 Michael Hanselmann
  """
2743 9fbfbb7b Iustin Pop
  if units is None:
2744 9fbfbb7b Iustin Pop
    if separator:
2745 9fbfbb7b Iustin Pop
      units = "m"
2746 9fbfbb7b Iustin Pop
    else:
2747 9fbfbb7b Iustin Pop
      units = "h"
2748 9fbfbb7b Iustin Pop
2749 137161c9 Michael Hanselmann
  if numfields is None:
2750 137161c9 Michael Hanselmann
    numfields = []
2751 137161c9 Michael Hanselmann
  if unitfields is None:
2752 137161c9 Michael Hanselmann
    unitfields = []
2753 137161c9 Michael Hanselmann
2754 b459a848 Andrea Spadaccini
  numfields = utils.FieldSet(*numfields)   # pylint: disable=W0142
2755 b459a848 Andrea Spadaccini
  unitfields = utils.FieldSet(*unitfields) # pylint: disable=W0142
2756 00430f8e Iustin Pop
2757 137161c9 Michael Hanselmann
  format_fields = []
2758 137161c9 Michael Hanselmann
  for field in fields:
2759 01ca31ae Iustin Pop
    if headers and field not in headers:
2760 ea5a5b74 Guido Trotter
      # TODO: handle better unknown fields (either revert to old
2761 71c1af58 Iustin Pop
      # style of raising exception, or deal more intelligently with
2762 71c1af58 Iustin Pop
      # variable fields)
2763 71c1af58 Iustin Pop
      headers[field] = field
2764 137161c9 Michael Hanselmann
    if separator is not None:
2765 137161c9 Michael Hanselmann
      format_fields.append("%s")
2766 00430f8e Iustin Pop
    elif numfields.Matches(field):
2767 137161c9 Michael Hanselmann
      format_fields.append("%*s")
2768 137161c9 Michael Hanselmann
    else:
2769 137161c9 Michael Hanselmann
      format_fields.append("%-*s")
2770 137161c9 Michael Hanselmann
2771 137161c9 Michael Hanselmann
  if separator is None:
2772 137161c9 Michael Hanselmann
    mlens = [0 for name in fields]
2773 d0c8c01d Iustin Pop
    format_str = " ".join(format_fields)
2774 137161c9 Michael Hanselmann
  else:
2775 c04bc777 Iustin Pop
    format_str = separator.replace("%", "%%").join(format_fields)
2776 137161c9 Michael Hanselmann
2777 137161c9 Michael Hanselmann
  for row in data:
2778 dcbd6288 Guido Trotter
    if row is None:
2779 dcbd6288 Guido Trotter
      continue
2780 137161c9 Michael Hanselmann
    for idx, val in enumerate(row):
2781 00430f8e Iustin Pop
      if unitfields.Matches(fields[idx]):
2782 137161c9 Michael Hanselmann
        try:
2783 137161c9 Michael Hanselmann
          val = int(val)
2784 691744c4 Iustin Pop
        except (TypeError, ValueError):
2785 137161c9 Michael Hanselmann
          pass
2786 137161c9 Michael Hanselmann
        else:
2787 9fbfbb7b Iustin Pop
          val = row[idx] = utils.FormatUnit(val, units)
2788 01ca31ae Iustin Pop
      val = row[idx] = str(val)
2789 137161c9 Michael Hanselmann
      if separator is None:
2790 137161c9 Michael Hanselmann
        mlens[idx] = max(mlens[idx], len(val))
2791 137161c9 Michael Hanselmann
2792 16be8703 Iustin Pop
  result = []
2793 137161c9 Michael Hanselmann
  if headers:
2794 137161c9 Michael Hanselmann
    args = []
2795 137161c9 Michael Hanselmann
    for idx, name in enumerate(fields):
2796 137161c9 Michael Hanselmann
      hdr = headers[name]
2797 137161c9 Michael Hanselmann
      if separator is None:
2798 137161c9 Michael Hanselmann
        mlens[idx] = max(mlens[idx], len(hdr))
2799 137161c9 Michael Hanselmann
        args.append(mlens[idx])
2800 137161c9 Michael Hanselmann
      args.append(hdr)
2801 c04bc777 Iustin Pop
    result.append(format_str % tuple(args))
2802 137161c9 Michael Hanselmann
2803 ec39d63c Michael Hanselmann
  if separator is None:
2804 ec39d63c Michael Hanselmann
    assert len(mlens) == len(fields)
2805 ec39d63c Michael Hanselmann
2806 ec39d63c Michael Hanselmann
    if fields and not numfields.Matches(fields[-1]):
2807 ec39d63c Michael Hanselmann
      mlens[-1] = 0
2808 ec39d63c Michael Hanselmann
2809 137161c9 Michael Hanselmann
  for line in data:
2810 137161c9 Michael Hanselmann
    args = []
2811 dcbd6288 Guido Trotter
    if line is None:
2812 d0c8c01d Iustin Pop
      line = ["-" for _ in fields]
2813 f1501b3f Michael Hanselmann
    for idx in range(len(fields)):
2814 137161c9 Michael Hanselmann
      if separator is None:
2815 137161c9 Michael Hanselmann
        args.append(mlens[idx])
2816 137161c9 Michael Hanselmann
      args.append(line[idx])
2817 c04bc777 Iustin Pop
    result.append(format_str % tuple(args))
2818 16be8703 Iustin Pop
2819 16be8703 Iustin Pop
  return result
2820 3386e7a9 Iustin Pop
2821 3386e7a9 Iustin Pop
2822 ee3aedff Michael Hanselmann
def _FormatBool(value):
2823 ee3aedff Michael Hanselmann
  """Formats a boolean value as a string.
2824 ee3aedff Michael Hanselmann

2825 ee3aedff Michael Hanselmann
  """
2826 ee3aedff Michael Hanselmann
  if value:
2827 ee3aedff Michael Hanselmann
    return "Y"
2828 ee3aedff Michael Hanselmann
  return "N"
2829 ee3aedff Michael Hanselmann
2830 ee3aedff Michael Hanselmann
2831 ee3aedff Michael Hanselmann
#: Default formatting for query results; (callback, align right)
2832 ee3aedff Michael Hanselmann
_DEFAULT_FORMAT_QUERY = {
2833 ee3aedff Michael Hanselmann
  constants.QFT_TEXT: (str, False),
2834 ee3aedff Michael Hanselmann
  constants.QFT_BOOL: (_FormatBool, False),
2835 ee3aedff Michael Hanselmann
  constants.QFT_NUMBER: (str, True),
2836 ee3aedff Michael Hanselmann
  constants.QFT_TIMESTAMP: (utils.FormatTime, False),
2837 ee3aedff Michael Hanselmann
  constants.QFT_OTHER: (str, False),
2838 ee3aedff Michael Hanselmann
  constants.QFT_UNKNOWN: (str, False),
2839 ee3aedff Michael Hanselmann
  }
2840 ee3aedff Michael Hanselmann
2841 ee3aedff Michael Hanselmann
2842 ee3aedff Michael Hanselmann
def _GetColumnFormatter(fdef, override, unit):
2843 ee3aedff Michael Hanselmann
  """Returns formatting function for a field.
2844 ee3aedff Michael Hanselmann

2845 ee3aedff Michael Hanselmann
  @type fdef: L{objects.QueryFieldDefinition}
2846 ee3aedff Michael Hanselmann
  @type override: dict
2847 ee3aedff Michael Hanselmann
  @param 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 unit: string
2850 ee3aedff Michael Hanselmann
  @param unit: Unit used for formatting fields of type L{constants.QFT_UNIT}
2851 ee3aedff Michael Hanselmann
  @rtype: tuple; (callable, bool)
2852 ee3aedff Michael Hanselmann
  @return: Returns the function to format a value (takes one parameter) and a
2853 ee3aedff Michael Hanselmann
    boolean for aligning the value on the right-hand side
2854 ee3aedff Michael Hanselmann

2855 ee3aedff Michael Hanselmann
  """
2856 ee3aedff Michael Hanselmann
  fmt = override.get(fdef.name, None)
2857 ee3aedff Michael Hanselmann
  if fmt is not None:
2858 ee3aedff Michael Hanselmann
    return fmt
2859 ee3aedff Michael Hanselmann
2860 ee3aedff Michael Hanselmann
  assert constants.QFT_UNIT not in _DEFAULT_FORMAT_QUERY
2861 ee3aedff Michael Hanselmann
2862 ee3aedff Michael Hanselmann
  if fdef.kind == constants.QFT_UNIT:
2863 ee3aedff Michael Hanselmann
    # Can't keep this information in the static dictionary
2864 ee3aedff Michael Hanselmann
    return (lambda value: utils.FormatUnit(value, unit), True)
2865 ee3aedff Michael Hanselmann
2866 ee3aedff Michael Hanselmann
  fmt = _DEFAULT_FORMAT_QUERY.get(fdef.kind, None)
2867 ee3aedff Michael Hanselmann
  if fmt is not None:
2868 ee3aedff Michael Hanselmann
    return fmt
2869 ee3aedff Michael Hanselmann
2870 ee3aedff Michael Hanselmann
  raise NotImplementedError("Can't format column type '%s'" % fdef.kind)
2871 ee3aedff Michael Hanselmann
2872 ee3aedff Michael Hanselmann
2873 ee3aedff Michael Hanselmann
class _QueryColumnFormatter:
2874 ee3aedff Michael Hanselmann
  """Callable class for formatting fields of a query.
2875 ee3aedff Michael Hanselmann

2876 ee3aedff Michael Hanselmann
  """
2877 f0b1bafe Iustin Pop
  def __init__(self, fn, status_fn, verbose):
2878 ee3aedff Michael Hanselmann
    """Initializes this class.
2879 ee3aedff Michael Hanselmann

2880 ee3aedff Michael Hanselmann
    @type fn: callable
2881 ee3aedff Michael Hanselmann
    @param fn: Formatting function
2882 ee3aedff Michael Hanselmann
    @type status_fn: callable
2883 ee3aedff Michael Hanselmann
    @param status_fn: Function to report fields' status
2884 f0b1bafe Iustin Pop
    @type verbose: boolean
2885 f0b1bafe Iustin Pop
    @param verbose: whether to use verbose field descriptions or not
2886 ee3aedff Michael Hanselmann

2887 ee3aedff Michael Hanselmann
    """
2888 ee3aedff Michael Hanselmann
    self._fn = fn
2889 ee3aedff Michael Hanselmann
    self._status_fn = status_fn
2890 cbfa4f0f Michael Hanselmann
    self._verbose = verbose
2891 ee3aedff Michael Hanselmann
2892 ee3aedff Michael Hanselmann
  def __call__(self, data):
2893 ee3aedff Michael Hanselmann
    """Returns a field's string representation.
2894 ee3aedff Michael Hanselmann

2895 ee3aedff Michael Hanselmann
    """
2896 ee3aedff Michael Hanselmann
    (status, value) = data
2897 ee3aedff Michael Hanselmann
2898 ee3aedff Michael Hanselmann
    # Report status
2899 ee3aedff Michael Hanselmann
    self._status_fn(status)
2900 ee3aedff Michael Hanselmann
2901 cfb084ae René Nussbaumer
    if status == constants.RS_NORMAL:
2902 ee3aedff Michael Hanselmann
      return self._fn(value)
2903 ee3aedff Michael Hanselmann
2904 ee3aedff Michael Hanselmann
    assert value is None, \
2905 ee3aedff Michael Hanselmann
           "Found value %r for abnormal status %s" % (value, status)
2906 ee3aedff Michael Hanselmann
2907 f2c6673d Michael Hanselmann
    return FormatResultError(status, self._verbose)
2908 ee3aedff Michael Hanselmann
2909 ee3aedff Michael Hanselmann
2910 f2c6673d Michael Hanselmann
def FormatResultError(status, verbose):
2911 ae95e419 René Nussbaumer
  """Formats result status other than L{constants.RS_NORMAL}.
2912 ee3aedff Michael Hanselmann

2913 ae95e419 René Nussbaumer
  @param status: The result status
2914 f2c6673d Michael Hanselmann
  @type verbose: boolean
2915 f2c6673d Michael Hanselmann
  @param verbose: Whether to return the verbose text
2916 ae95e419 René Nussbaumer
  @return: Text of result status
2917 a6070ef7 Michael Hanselmann

2918 ae95e419 René Nussbaumer
  """
2919 ae95e419 René Nussbaumer
  assert status != constants.RS_NORMAL, \
2920 cbfa4f0f Michael Hanselmann
         "FormatResultError called with status equal to constants.RS_NORMAL"
2921 ae95e419 René Nussbaumer
  try:
2922 cbfa4f0f Michael Hanselmann
    (verbose_text, normal_text) = constants.RSS_DESCRIPTION[status]
2923 ae95e419 René Nussbaumer
  except KeyError:
2924 ee3aedff Michael Hanselmann
    raise NotImplementedError("Unknown status %s" % status)
2925 cbfa4f0f Michael Hanselmann
  else:
2926 cbfa4f0f Michael Hanselmann
    if verbose:
2927 cbfa4f0f Michael Hanselmann
      return verbose_text
2928 cbfa4f0f Michael Hanselmann
    return normal_text
2929 ee3aedff Michael Hanselmann
2930 ee3aedff Michael Hanselmann
2931 ee3aedff Michael Hanselmann
def FormatQueryResult(result, unit=None, format_override=None, separator=None,
2932 f0b1bafe Iustin Pop
                      header=False, verbose=False):
2933 ee3aedff Michael Hanselmann
  """Formats data in L{objects.QueryResponse}.
2934 ee3aedff Michael Hanselmann

2935 ee3aedff Michael Hanselmann
  @type result: L{objects.QueryResponse}
2936 ee3aedff Michael Hanselmann
  @param result: result of query operation
2937 ee3aedff Michael Hanselmann
  @type unit: string
2938 ee3aedff Michael Hanselmann
  @param unit: Unit used for formatting fields of type L{constants.QFT_UNIT},
2939 18009c1e Iustin Pop
    see L{utils.text.FormatUnit}
2940 ee3aedff Michael Hanselmann
  @type format_override: dict
2941 ee3aedff Michael Hanselmann
  @param format_override: Dictionary for overriding field formatting functions,
2942 ee3aedff Michael Hanselmann
    indexed by field name, contents like L{_DEFAULT_FORMAT_QUERY}
2943 ee3aedff Michael Hanselmann
  @type separator: string or None
2944 ee3aedff Michael Hanselmann
  @param separator: String used to separate fields
2945 ee3aedff Michael Hanselmann
  @type header: bool
2946 ee3aedff Michael Hanselmann
  @param header: Whether to output header row
2947 f0b1bafe Iustin Pop
  @type verbose: boolean
2948 f0b1bafe Iustin Pop
  @param verbose: whether to use verbose field descriptions or not
2949 ee3aedff Michael Hanselmann

2950 ee3aedff Michael Hanselmann
  """
2951 ee3aedff Michael Hanselmann
  if unit is None:
2952 ee3aedff Michael Hanselmann
    if separator:
2953 ee3aedff Michael Hanselmann
      unit = "m"
2954 ee3aedff Michael Hanselmann
    else:
2955 ee3aedff Michael Hanselmann
      unit = "h"
2956 ee3aedff Michael Hanselmann
2957 ee3aedff Michael Hanselmann
  if format_override is None:
2958 ee3aedff Michael Hanselmann
    format_override = {}
2959 ee3aedff Michael Hanselmann
2960 cfb084ae René Nussbaumer
  stats = dict.fromkeys(constants.RS_ALL, 0)
2961 ee3aedff Michael Hanselmann
2962 ee3aedff Michael Hanselmann
  def _RecordStatus(status):
2963 ee3aedff Michael Hanselmann
    if status in stats:
2964 ee3aedff Michael Hanselmann
      stats[status] += 1
2965 ee3aedff Michael Hanselmann
2966 ee3aedff Michael Hanselmann
  columns = []
2967 ee3aedff Michael Hanselmann
  for fdef in result.fields:
2968 ee3aedff Michael Hanselmann
    assert fdef.title and fdef.name
2969 ee3aedff Michael Hanselmann
    (fn, align_right) = _GetColumnFormatter(fdef, format_override, unit)
2970 ee3aedff Michael Hanselmann
    columns.append(TableColumn(fdef.title,
2971 f0b1bafe Iustin Pop
                               _QueryColumnFormatter(fn, _RecordStatus,
2972 f0b1bafe Iustin Pop
                                                     verbose),
2973 ee3aedff Michael Hanselmann
                               align_right))
2974 ee3aedff Michael Hanselmann
2975 ee3aedff Michael Hanselmann
  table = FormatTable(result.data, columns, header, separator)
2976 ee3aedff Michael Hanselmann
2977 ee3aedff Michael Hanselmann
  # Collect statistics
2978 cfb084ae René Nussbaumer
  assert len(stats) == len(constants.RS_ALL)
2979 ee3aedff Michael Hanselmann
  assert compat.all(count >= 0 for count in stats.values())
2980 ee3aedff Michael Hanselmann
2981 ee3aedff Michael Hanselmann
  # Determine overall status. If there was no data, unknown fields must be
2982 ee3aedff Michael Hanselmann
  # detected via the field definitions.
2983 cfb084ae René Nussbaumer
  if (stats[constants.RS_UNKNOWN] or
2984 ee3aedff Michael Hanselmann
      (not result.data and _GetUnknownFields(result.fields))):
2985 ee3aedff Michael Hanselmann
    status = QR_UNKNOWN
2986 ee3aedff Michael Hanselmann
  elif compat.any(count > 0 for key, count in stats.items()
2987 cfb084ae René Nussbaumer
                  if key != constants.RS_NORMAL):
2988 ee3aedff Michael Hanselmann
    status = QR_INCOMPLETE
2989 ee3aedff Michael Hanselmann
  else:
2990 ee3aedff Michael Hanselmann
    status = QR_NORMAL
2991 ee3aedff Michael Hanselmann
2992 ee3aedff Michael Hanselmann
  return (status, table)
2993 ee3aedff Michael Hanselmann
2994 ee3aedff Michael Hanselmann
2995 ee3aedff Michael Hanselmann
def _GetUnknownFields(fdefs):
2996 ee3aedff Michael Hanselmann
  """Returns list of unknown fields included in C{fdefs}.
2997 ee3aedff Michael Hanselmann

2998 ee3aedff Michael Hanselmann
  @type fdefs: list of L{objects.QueryFieldDefinition}
2999 ee3aedff Michael Hanselmann

3000 ee3aedff Michael Hanselmann
  """
3001 ee3aedff Michael Hanselmann
  return [fdef for fdef in fdefs
3002 ee3aedff Michael Hanselmann
          if fdef.kind == constants.QFT_UNKNOWN]
3003 ee3aedff Michael Hanselmann
3004 ee3aedff Michael Hanselmann
3005 ee3aedff Michael Hanselmann
def _WarnUnknownFields(fdefs):
3006 ee3aedff Michael Hanselmann
  """Prints a warning to stderr if a query included unknown fields.
3007 ee3aedff Michael Hanselmann

3008 ee3aedff Michael Hanselmann
  @type fdefs: list of L{objects.QueryFieldDefinition}
3009 ee3aedff Michael Hanselmann

3010 ee3aedff Michael Hanselmann
  """
3011 ee3aedff Michael Hanselmann
  unknown = _GetUnknownFields(fdefs)
3012 ee3aedff Michael Hanselmann
  if unknown:
3013 ee3aedff Michael Hanselmann
    ToStderr("Warning: Queried for unknown fields %s",
3014 ee3aedff Michael Hanselmann
             utils.CommaJoin(fdef.name for fdef in unknown))
3015 ee3aedff Michael Hanselmann
    return True
3016 ee3aedff Michael Hanselmann
3017 ee3aedff Michael Hanselmann
  return False
3018 ee3aedff Michael Hanselmann
3019 ee3aedff Michael Hanselmann
3020 ee3aedff Michael Hanselmann
def GenericList(resource, fields, names, unit, separator, header, cl=None,
3021 03ec545a Michael Hanselmann
                format_override=None, verbose=False, force_filter=False,
3022 6f287cf3 Iustin Pop
                namefield=None, qfilter=None, isnumeric=False):
3023 ee3aedff Michael Hanselmann
  """Generic implementation for listing all items of a resource.
3024 ee3aedff Michael Hanselmann

3025 abd66bf8 Michael Hanselmann
  @param resource: One of L{constants.QR_VIA_LUXI}
3026 ee3aedff Michael Hanselmann
  @type fields: list of strings
3027 ee3aedff Michael Hanselmann
  @param fields: List of fields to query for
3028 ee3aedff Michael Hanselmann
  @type names: list of strings
3029 ee3aedff Michael Hanselmann
  @param names: Names of items to query for
3030 ee3aedff Michael Hanselmann
  @type unit: string or None
3031 ee3aedff Michael Hanselmann
  @param unit: Unit used for formatting fields of type L{constants.QFT_UNIT} or
3032 ee3aedff Michael Hanselmann
    None for automatic choice (human-readable for non-separator usage,
3033 ee3aedff Michael Hanselmann
    otherwise megabytes); this is a one-letter string
3034 ee3aedff Michael Hanselmann
  @type separator: string or None
3035 ee3aedff Michael Hanselmann
  @param separator: String used to separate fields
3036 ee3aedff Michael Hanselmann
  @type header: bool
3037 ee3aedff Michael Hanselmann
  @param header: Whether to show header row
3038 2928de47 Michael Hanselmann
  @type force_filter: bool
3039 2928de47 Michael Hanselmann
  @param force_filter: Whether to always treat names as filter
3040 ee3aedff Michael Hanselmann
  @type format_override: dict
3041 ee3aedff Michael Hanselmann
  @param format_override: Dictionary for overriding field formatting functions,
3042 ee3aedff Michael Hanselmann
    indexed by field name, contents like L{_DEFAULT_FORMAT_QUERY}
3043 f0b1bafe Iustin Pop
  @type verbose: boolean
3044 f0b1bafe Iustin Pop
  @param verbose: whether to use verbose field descriptions or not
3045 03ec545a Michael Hanselmann
  @type namefield: string
3046 03ec545a Michael Hanselmann
  @param namefield: Name of field to use for simple filters (see
3047 03ec545a Michael Hanselmann
    L{qlang.MakeFilter} for details)
3048 f037e9d7 Michael Hanselmann
  @type qfilter: list or None
3049 f037e9d7 Michael Hanselmann
  @param qfilter: Query filter (in addition to names)
3050 6f287cf3 Iustin Pop
  @param isnumeric: bool
3051 6f287cf3 Iustin Pop
  @param isnumeric: Whether the namefield's type is numeric, and therefore
3052 6f287cf3 Iustin Pop
    any simple filters built by namefield should use integer values to
3053 6f287cf3 Iustin Pop
    reflect that
3054 ee3aedff Michael Hanselmann

3055 ee3aedff Michael Hanselmann
  """
3056 ee3aedff Michael Hanselmann
  if not names:
3057 ee3aedff Michael Hanselmann
    names = None
3058 ee3aedff Michael Hanselmann
3059 6f287cf3 Iustin Pop
  namefilter = qlang.MakeFilter(names, force_filter, namefield=namefield,
3060 6f287cf3 Iustin Pop
                                isnumeric=isnumeric)
3061 f037e9d7 Michael Hanselmann
3062 f037e9d7 Michael Hanselmann
  if qfilter is None:
3063 f037e9d7 Michael Hanselmann
    qfilter = namefilter
3064 f037e9d7 Michael Hanselmann
  elif namefilter is not None:
3065 f037e9d7 Michael Hanselmann
    qfilter = [qlang.OP_AND, namefilter, qfilter]
3066 2928de47 Michael Hanselmann
3067 727274dd Iustin Pop
  if cl is None:
3068 727274dd Iustin Pop
    cl = GetClient()
3069 727274dd Iustin Pop
3070 2e5c33db Iustin Pop
  response = cl.Query(resource, fields, qfilter)
3071 ee3aedff Michael Hanselmann
3072 ee3aedff Michael Hanselmann
  found_unknown = _WarnUnknownFields(response.fields)
3073 ee3aedff Michael Hanselmann
3074 ee3aedff Michael Hanselmann
  (status, data) = FormatQueryResult(response, unit=unit, separator=separator,
3075 ee3aedff Michael Hanselmann
                                     header=header,
3076 f0b1bafe Iustin Pop
                                     format_override=format_override,
3077 f0b1bafe Iustin Pop
                                     verbose=verbose)
3078 ee3aedff Michael Hanselmann
3079 ee3aedff Michael Hanselmann
  for line in data:
3080 ee3aedff Michael Hanselmann
    ToStdout(line)
3081 ee3aedff Michael Hanselmann
3082 ee3aedff Michael Hanselmann
  assert ((found_unknown and status == QR_UNKNOWN) or
3083 ee3aedff Michael Hanselmann
          (not found_unknown and status != QR_UNKNOWN))
3084 ee3aedff Michael Hanselmann
3085 ee3aedff Michael Hanselmann
  if status == QR_UNKNOWN:
3086 ee3aedff Michael Hanselmann
    return constants.EXIT_UNKNOWN_FIELD
3087 ee3aedff Michael Hanselmann
3088 ee3aedff Michael Hanselmann
  # TODO: Should the list command fail if not all data could be collected?
3089 ee3aedff Michael Hanselmann
  return constants.EXIT_SUCCESS
3090 ee3aedff Michael Hanselmann
3091 ee3aedff Michael Hanselmann
3092 c1912a48 Michael Hanselmann
def _FieldDescValues(fdef):
3093 c1912a48 Michael Hanselmann
  """Helper function for L{GenericListFields} to get query field description.
3094 c1912a48 Michael Hanselmann

3095 c1912a48 Michael Hanselmann
  @type fdef: L{objects.QueryFieldDefinition}
3096 c1912a48 Michael Hanselmann
  @rtype: list
3097 c1912a48 Michael Hanselmann

3098 c1912a48 Michael Hanselmann
  """
3099 c1912a48 Michael Hanselmann
  return [
3100 c1912a48 Michael Hanselmann
    fdef.name,
3101 c1912a48 Michael Hanselmann
    _QFT_NAMES.get(fdef.kind, fdef.kind),
3102 c1912a48 Michael Hanselmann
    fdef.title,
3103 c1912a48 Michael Hanselmann
    fdef.doc,
3104 c1912a48 Michael Hanselmann
    ]
3105 c1912a48 Michael Hanselmann
3106 c1912a48 Michael Hanselmann
3107 ee3aedff Michael Hanselmann
def GenericListFields(resource, fields, separator, header, cl=None):
3108 ee3aedff Michael Hanselmann
  """Generic implementation for listing fields for a resource.
3109 ee3aedff Michael Hanselmann

3110 abd66bf8 Michael Hanselmann
  @param resource: One of L{constants.QR_VIA_LUXI}
3111 ee3aedff Michael Hanselmann
  @type fields: list of strings
3112 ee3aedff Michael Hanselmann
  @param fields: List of fields to query for
3113 ee3aedff Michael Hanselmann
  @type separator: string or None
3114 ee3aedff Michael Hanselmann
  @param separator: String used to separate fields
3115 ee3aedff Michael Hanselmann
  @type header: bool
3116 ee3aedff Michael Hanselmann
  @param header: Whether to show header row
3117 ee3aedff Michael Hanselmann

3118 ee3aedff Michael Hanselmann
  """
3119 ee3aedff Michael Hanselmann
  if cl is None:
3120 ee3aedff Michael Hanselmann
    cl = GetClient()
3121 ee3aedff Michael Hanselmann
3122 ee3aedff Michael Hanselmann
  if not fields:
3123 ee3aedff Michael Hanselmann
    fields = None
3124 ee3aedff Michael Hanselmann
3125 ee3aedff Michael Hanselmann
  response = cl.QueryFields(resource, fields)
3126 ee3aedff Michael Hanselmann
3127 ee3aedff Michael Hanselmann
  found_unknown = _WarnUnknownFields(response.fields)
3128 ee3aedff Michael Hanselmann
3129 ee3aedff Michael Hanselmann
  columns = [
3130 ee3aedff Michael Hanselmann
    TableColumn("Name", str, False),
3131 c1912a48 Michael Hanselmann
    TableColumn("Type", str, False),
3132 ee3aedff Michael Hanselmann
    TableColumn("Title", str, False),
3133 ea1440c1 Michael Hanselmann
    TableColumn("Description", str, False),
3134 ee3aedff Michael Hanselmann
    ]
3135 ee3aedff Michael Hanselmann
3136 c1912a48 Michael Hanselmann
  rows = map(_FieldDescValues, response.fields)
3137 ee3aedff Michael Hanselmann
3138 ee3aedff Michael Hanselmann
  for line in FormatTable(rows, columns, header, separator):
3139 ee3aedff Michael Hanselmann
    ToStdout(line)
3140 ee3aedff Michael Hanselmann
3141 ee3aedff Michael Hanselmann
  if found_unknown:
3142 ee3aedff Michael Hanselmann
    return constants.EXIT_UNKNOWN_FIELD
3143 ee3aedff Michael Hanselmann
3144 ee3aedff Michael Hanselmann
  return constants.EXIT_SUCCESS
3145 ee3aedff Michael Hanselmann
3146 ee3aedff Michael Hanselmann
3147 ee3aedff Michael Hanselmann
class TableColumn:
3148 ee3aedff Michael Hanselmann
  """Describes a column for L{FormatTable}.
3149 ee3aedff Michael Hanselmann

3150 ee3aedff Michael Hanselmann
  """
3151 ee3aedff Michael Hanselmann
  def __init__(self, title, fn, align_right):
3152 ee3aedff Michael Hanselmann
    """Initializes this class.
3153 ee3aedff Michael Hanselmann

3154 ee3aedff Michael Hanselmann
    @type title: string
3155 ee3aedff Michael Hanselmann
    @param title: Column title
3156 ee3aedff Michael Hanselmann
    @type fn: callable
3157 ee3aedff Michael Hanselmann
    @param fn: Formatting function
3158 ee3aedff Michael Hanselmann
    @type align_right: bool
3159 ee3aedff Michael Hanselmann
    @param align_right: Whether to align values on the right-hand side
3160 ee3aedff Michael Hanselmann

3161 ee3aedff Michael Hanselmann
    """
3162 ee3aedff Michael Hanselmann
    self.title = title
3163 ee3aedff Michael Hanselmann
    self.format = fn
3164 ee3aedff Michael Hanselmann
    self.align_right = align_right
3165 ee3aedff Michael Hanselmann
3166 ee3aedff Michael Hanselmann
3167 ee3aedff Michael Hanselmann
def _GetColFormatString(width, align_right):
3168 ee3aedff Michael Hanselmann
  """Returns the format string for a field.
3169 ee3aedff Michael Hanselmann

3170 ee3aedff Michael Hanselmann
  """
3171 ee3aedff Michael Hanselmann
  if align_right:
3172 ee3aedff Michael Hanselmann
    sign = ""
3173 ee3aedff Michael Hanselmann
  else:
3174 ee3aedff Michael Hanselmann
    sign = "-"
3175 ee3aedff Michael Hanselmann
3176 ee3aedff Michael Hanselmann
  return "%%%s%ss" % (sign, width)
3177 ee3aedff Michael Hanselmann
3178 ee3aedff Michael Hanselmann
3179 ee3aedff Michael Hanselmann
def FormatTable(rows, columns, header, separator):
3180 ee3aedff Michael Hanselmann
  """Formats data as a table.
3181 ee3aedff Michael Hanselmann

3182 ee3aedff Michael Hanselmann
  @type rows: list of lists
3183 ee3aedff Michael Hanselmann
  @param rows: Row data, one list per row
3184 ee3aedff Michael Hanselmann
  @type columns: list of L{TableColumn}
3185 ee3aedff Michael Hanselmann
  @param columns: Column descriptions
3186 ee3aedff Michael Hanselmann
  @type header: bool
3187 ee3aedff Michael Hanselmann
  @param header: Whether to show header row
3188 ee3aedff Michael Hanselmann
  @type separator: string or None
3189 ee3aedff Michael Hanselmann
  @param separator: String used to separate columns
3190 ee3aedff Michael Hanselmann

3191 ee3aedff Michael Hanselmann
  """
3192 ee3aedff Michael Hanselmann
  if header:
3193 ee3aedff Michael Hanselmann
    data = [[col.title for col in columns]]
3194 ee3aedff Michael Hanselmann
    colwidth = [len(col.title) for col in columns]
3195 ee3aedff Michael Hanselmann
  else:
3196 ee3aedff Michael Hanselmann
    data = []
3197 ee3aedff Michael Hanselmann
    colwidth = [0 for _ in columns]
3198 ee3aedff Michael Hanselmann
3199 ee3aedff Michael Hanselmann
  # Format row data
3200 ee3aedff Michael Hanselmann
  for row in rows:
3201 ee3aedff Michael Hanselmann
    assert len(row) == len(columns)
3202 ee3aedff Michael Hanselmann
3203 ee3aedff Michael Hanselmann
    formatted = [col.format(value) for value, col in zip(row, columns)]
3204 ee3aedff Michael Hanselmann
3205 ee3aedff Michael Hanselmann
    if separator is None:
3206 ee3aedff Michael Hanselmann
      # Update column widths
3207 ee3aedff Michael Hanselmann
      for idx, (oldwidth, value) in enumerate(zip(colwidth, formatted)):
3208 ee3aedff Michael Hanselmann
        # Modifying a list's items while iterating is fine
3209 ee3aedff Michael Hanselmann
        colwidth[idx] = max(oldwidth, len(value))
3210 ee3aedff Michael Hanselmann
3211 ee3aedff Michael Hanselmann
    data.append(formatted)
3212 ee3aedff Michael Hanselmann
3213 ee3aedff Michael Hanselmann
  if separator is not None:
3214 ee3aedff Michael Hanselmann
    # Return early if a separator is used
3215 ee3aedff Michael Hanselmann
    return [separator.join(row) for row in data]
3216 ee3aedff Michael Hanselmann
3217 ee3aedff Michael Hanselmann
  if columns and not columns[-1].align_right:
3218 ee3aedff Michael Hanselmann
    # Avoid unnecessary spaces at end of line
3219 ee3aedff Michael Hanselmann
    colwidth[-1] = 0
3220 ee3aedff Michael Hanselmann
3221 ee3aedff Michael Hanselmann
  # Build format string
3222 ee3aedff Michael Hanselmann
  fmt = " ".join([_GetColFormatString(width, col.align_right)
3223 ee3aedff Michael Hanselmann
                  for col, width in zip(columns, colwidth)])
3224 ee3aedff Michael Hanselmann
3225 ee3aedff Michael Hanselmann
  return [fmt % tuple(row) for row in data]
3226 ee3aedff Michael Hanselmann
3227 ee3aedff Michael Hanselmann
3228 3386e7a9 Iustin Pop
def FormatTimestamp(ts):
3229 3386e7a9 Iustin Pop
  """Formats a given timestamp.
3230 3386e7a9 Iustin Pop

3231 3386e7a9 Iustin Pop
  @type ts: timestamp
3232 3386e7a9 Iustin Pop
  @param ts: a timeval-type timestamp, a tuple of seconds and microseconds
3233 3386e7a9 Iustin Pop

3234 3386e7a9 Iustin Pop
  @rtype: string
3235 5fcc718f Iustin Pop
  @return: a string with the formatted timestamp
3236 3386e7a9 Iustin Pop

3237 3386e7a9 Iustin Pop
  """
3238 e687ec01 Michael Hanselmann
  if not isinstance(ts, (tuple, list)) or len(ts) != 2:
3239 d0c8c01d Iustin Pop
    return "?"
3240 26a72a48 Michael Hanselmann
3241 26a72a48 Michael Hanselmann
  (sec, usecs) = ts
3242 26a72a48 Michael Hanselmann
  return utils.FormatTime(sec, usecs=usecs)
3243 2241e2b9 Iustin Pop
3244 2241e2b9 Iustin Pop
3245 2241e2b9 Iustin Pop
def ParseTimespec(value):
3246 2241e2b9 Iustin Pop
  """Parse a time specification.
3247 2241e2b9 Iustin Pop

3248 2241e2b9 Iustin Pop
  The following suffixed will be recognized:
3249 2241e2b9 Iustin Pop

3250 2241e2b9 Iustin Pop
    - s: seconds
3251 2241e2b9 Iustin Pop
    - m: minutes
3252 2241e2b9 Iustin Pop
    - h: hours
3253 2241e2b9 Iustin Pop
    - d: day
3254 2241e2b9 Iustin Pop
    - w: weeks
3255 2241e2b9 Iustin Pop

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

3258 2241e2b9 Iustin Pop
  """
3259 2241e2b9 Iustin Pop
  value = str(value)
3260 2241e2b9 Iustin Pop
  if not value:
3261 2cfbc784 Iustin Pop
    raise errors.OpPrereqError("Empty time specification passed",
3262 2cfbc784 Iustin Pop
                               errors.ECODE_INVAL)
3263 2241e2b9 Iustin Pop
  suffix_map = {
3264 d0c8c01d Iustin Pop
    "s": 1,
3265 d0c8c01d Iustin Pop
    "m": 60,
3266 d0c8c01d Iustin Pop
    "h": 3600,
3267 d0c8c01d Iustin Pop
    "d": 86400,
3268 d0c8c01d Iustin Pop
    "w": 604800,
3269 2241e2b9 Iustin Pop
    }
3270 2241e2b9 Iustin Pop
  if value[-1] not in suffix_map:
3271 2241e2b9 Iustin Pop
    try:
3272 2241e2b9 Iustin Pop
      value = int(value)
3273 691744c4 Iustin Pop
    except (TypeError, ValueError):
3274 2cfbc784 Iustin Pop
      raise errors.OpPrereqError("Invalid time specification '%s'" % value,
3275 2cfbc784 Iustin Pop
                                 errors.ECODE_INVAL)
3276 2241e2b9 Iustin Pop
  else:
3277 2241e2b9 Iustin Pop
    multiplier = suffix_map[value[-1]]
3278 2241e2b9 Iustin Pop
    value = value[:-1]
3279 2241e2b9 Iustin Pop
    if not value: # no data left after stripping the suffix
3280 2241e2b9 Iustin Pop
      raise errors.OpPrereqError("Invalid time specification (only"
3281 2cfbc784 Iustin Pop
                                 " suffix passed)", errors.ECODE_INVAL)
3282 2241e2b9 Iustin Pop
    try:
3283 2241e2b9 Iustin Pop
      value = int(value) * multiplier
3284 691744c4 Iustin Pop
    except (TypeError, ValueError):
3285 2cfbc784 Iustin Pop
      raise errors.OpPrereqError("Invalid time specification '%s'" % value,
3286 2cfbc784 Iustin Pop
                                 errors.ECODE_INVAL)
3287 2241e2b9 Iustin Pop
  return value
3288 46fbdd04 Iustin Pop
3289 46fbdd04 Iustin Pop
3290 e9e26bb3 Iustin Pop
def GetOnlineNodes(nodes, cl=None, nowarn=False, secondary_ips=False,
3291 05484a24 Michael Hanselmann
                   filter_master=False, nodegroup=None):
3292 4040a784 Iustin Pop
  """Returns the names of online nodes.
3293 4040a784 Iustin Pop

3294 4040a784 Iustin Pop
  This function will also log a warning on stderr with the names of
3295 4040a784 Iustin Pop
  the online nodes.
3296 4040a784 Iustin Pop

3297 4040a784 Iustin Pop
  @param nodes: if not empty, use only this subset of nodes (minus the
3298 4040a784 Iustin Pop
      offline ones)
3299 4040a784 Iustin Pop
  @param cl: if not None, luxi client to use
3300 4040a784 Iustin Pop
  @type nowarn: boolean
3301 4040a784 Iustin Pop
  @param nowarn: by default, this function will output a note with the
3302 4040a784 Iustin Pop
      offline nodes that are skipped; if this parameter is True the
3303 4040a784 Iustin Pop
      note is not displayed
3304 e9e26bb3 Iustin Pop
  @type secondary_ips: boolean
3305 e9e26bb3 Iustin Pop
  @param secondary_ips: if True, return the secondary IPs instead of the
3306 e9e26bb3 Iustin Pop
      names, useful for doing network traffic over the replication interface
3307 e9e26bb3 Iustin Pop
      (if any)
3308 e9e26bb3 Iustin Pop
  @type filter_master: boolean
3309 e9e26bb3 Iustin Pop
  @param filter_master: if True, do not return the master node in the list
3310 e9e26bb3 Iustin Pop
      (useful in coordination with secondary_ips where we cannot check our
3311 e9e26bb3 Iustin Pop
      node name against the list)
3312 05484a24 Michael Hanselmann
  @type nodegroup: string
3313 05484a24 Michael Hanselmann
  @param nodegroup: If set, only return nodes in this node group
3314 4040a784 Iustin Pop

3315 4040a784 Iustin Pop
  """
3316 4040a784 Iustin Pop
  if cl is None:
3317 4040a784 Iustin Pop
    cl = GetClient()
3318 4040a784 Iustin Pop
3319 2e5c33db Iustin Pop
  qfilter = []
3320 05484a24 Michael Hanselmann
3321 05484a24 Michael Hanselmann
  if nodes:
3322 2e5c33db Iustin Pop
    qfilter.append(qlang.MakeSimpleFilter("name", nodes))
3323 05484a24 Michael Hanselmann
3324 05484a24 Michael Hanselmann
  if nodegroup is not None:
3325 2e5c33db Iustin Pop
    qfilter.append([qlang.OP_OR, [qlang.OP_EQUAL, "group", nodegroup],
3326 05484a24 Michael Hanselmann
                                 [qlang.OP_EQUAL, "group.uuid", nodegroup]])
3327 e9e26bb3 Iustin Pop
3328 e9e26bb3 Iustin Pop
  if filter_master:
3329 2e5c33db Iustin Pop
    qfilter.append([qlang.OP_NOT, [qlang.OP_TRUE, "master"]])
3330 05484a24 Michael Hanselmann
3331 2e5c33db Iustin Pop
  if qfilter:
3332 2e5c33db Iustin Pop
    if len(qfilter) > 1:
3333 2e5c33db Iustin Pop
      final_filter = [qlang.OP_AND] + qfilter
3334 05484a24 Michael Hanselmann
    else:
3335 2e5c33db Iustin Pop
      assert len(qfilter) == 1
3336 2e5c33db Iustin Pop
      final_filter = qfilter[0]
3337 e9e26bb3 Iustin Pop
  else:
3338 05484a24 Michael Hanselmann
    final_filter = None
3339 05484a24 Michael Hanselmann
3340 05484a24 Michael Hanselmann
  result = cl.Query(constants.QR_NODE, ["name", "offline", "sip"], final_filter)
3341 05484a24 Michael Hanselmann
3342 05484a24 Michael Hanselmann
  def _IsOffline(row):
3343 05484a24 Michael Hanselmann
    (_, (_, offline), _) = row
3344 05484a24 Michael Hanselmann
    return offline
3345 05484a24 Michael Hanselmann
3346 05484a24 Michael Hanselmann
  def _GetName(row):
3347 05484a24 Michael Hanselmann
    ((_, name), _, _) = row
3348 05484a24 Michael Hanselmann
    return name
3349 05484a24 Michael Hanselmann
3350 05484a24 Michael Hanselmann
  def _GetSip(row):
3351 05484a24 Michael Hanselmann
    (_, _, (_, sip)) = row
3352 05484a24 Michael Hanselmann
    return sip
3353 05484a24 Michael Hanselmann
3354 05484a24 Michael Hanselmann
  (offline, online) = compat.partition(result.data, _IsOffline)
3355 e9e26bb3 Iustin Pop
3356 4040a784 Iustin Pop
  if offline and not nowarn:
3357 05484a24 Michael Hanselmann
    ToStderr("Note: skipping offline node(s): %s" %
3358 05484a24 Michael Hanselmann
             utils.CommaJoin(map(_GetName, offline)))
3359 05484a24 Michael Hanselmann
3360 05484a24 Michael Hanselmann
  if secondary_ips:
3361 05484a24 Michael Hanselmann
    fn = _GetSip
3362 05484a24 Michael Hanselmann
  else:
3363 05484a24 Michael Hanselmann
    fn = _GetName
3364 05484a24 Michael Hanselmann
3365 05484a24 Michael Hanselmann
  return map(fn, online)
3366 4040a784 Iustin Pop
3367 4040a784 Iustin Pop
3368 46fbdd04 Iustin Pop
def _ToStream(stream, txt, *args):
3369 46fbdd04 Iustin Pop
  """Write a message to a stream, bypassing the logging system
3370 46fbdd04 Iustin Pop

3371 46fbdd04 Iustin Pop
  @type stream: file object
3372 46fbdd04 Iustin Pop
  @param stream: the file to which we should write
3373 46fbdd04 Iustin Pop
  @type txt: str
3374 46fbdd04 Iustin Pop
  @param txt: the message
3375 46fbdd04 Iustin Pop

3376 46fbdd04 Iustin Pop
  """
3377 225e2544 Iustin Pop
  try:
3378 225e2544 Iustin Pop
    if args:
3379 225e2544 Iustin Pop
      args = tuple(args)
3380 225e2544 Iustin Pop
      stream.write(txt % args)
3381 225e2544 Iustin Pop
    else:
3382 225e2544 Iustin Pop
      stream.write(txt)
3383 d0c8c01d Iustin Pop
    stream.write("\n")
3384 225e2544 Iustin Pop
    stream.flush()
3385 225e2544 Iustin Pop
  except IOError, err:
3386 225e2544 Iustin Pop
    if err.errno == errno.EPIPE:
3387 225e2544 Iustin Pop
      # our terminal went away, we'll exit
3388 225e2544 Iustin Pop
      sys.exit(constants.EXIT_FAILURE)
3389 225e2544 Iustin Pop
    else:
3390 225e2544 Iustin Pop
      raise
3391 46fbdd04 Iustin Pop
3392 46fbdd04 Iustin Pop
3393 46fbdd04 Iustin Pop
def ToStdout(txt, *args):
3394 46fbdd04 Iustin Pop
  """Write a message to stdout only, bypassing the logging system
3395 46fbdd04 Iustin Pop

3396 46fbdd04 Iustin Pop
  This is just a wrapper over _ToStream.
3397 46fbdd04 Iustin Pop

3398 46fbdd04 Iustin Pop
  @type txt: str
3399 46fbdd04 Iustin Pop
  @param txt: the message
3400 46fbdd04 Iustin Pop

3401 46fbdd04 Iustin Pop
  """
3402 46fbdd04 Iustin Pop
  _ToStream(sys.stdout, txt, *args)
3403 46fbdd04 Iustin Pop
3404 46fbdd04 Iustin Pop
3405 46fbdd04 Iustin Pop
def ToStderr(txt, *args):
3406 46fbdd04 Iustin Pop
  """Write a message to stderr only, bypassing the logging system
3407 46fbdd04 Iustin Pop

3408 46fbdd04 Iustin Pop
  This is just a wrapper over _ToStream.
3409 46fbdd04 Iustin Pop

3410 46fbdd04 Iustin Pop
  @type txt: str
3411 46fbdd04 Iustin Pop
  @param txt: the message
3412 46fbdd04 Iustin Pop

3413 46fbdd04 Iustin Pop
  """
3414 46fbdd04 Iustin Pop
  _ToStream(sys.stderr, txt, *args)
3415 479636a3 Iustin Pop
3416 479636a3 Iustin Pop
3417 479636a3 Iustin Pop
class JobExecutor(object):
3418 479636a3 Iustin Pop
  """Class which manages the submission and execution of multiple jobs.
3419 479636a3 Iustin Pop

3420 479636a3 Iustin Pop
  Note that instances of this class should not be reused between
3421 479636a3 Iustin Pop
  GetResults() calls.
3422 479636a3 Iustin Pop

3423 479636a3 Iustin Pop
  """
3424 919ca415 Iustin Pop
  def __init__(self, cl=None, verbose=True, opts=None, feedback_fn=None):
3425 479636a3 Iustin Pop
    self.queue = []
3426 479636a3 Iustin Pop
    if cl is None:
3427 479636a3 Iustin Pop
      cl = GetClient()
3428 479636a3 Iustin Pop
    self.cl = cl
3429 479636a3 Iustin Pop
    self.verbose = verbose
3430 23b4b983 Iustin Pop
    self.jobs = []
3431 cff5fa7f Iustin Pop
    self.opts = opts
3432 919ca415 Iustin Pop
    self.feedback_fn = feedback_fn
3433 60452edf Michael Hanselmann
    self._counter = itertools.count()
3434 479636a3 Iustin Pop
3435 8d99a8bf Michael Hanselmann
  @staticmethod
3436 8d99a8bf Michael Hanselmann
  def _IfName(name, fmt):
3437 8d99a8bf Michael Hanselmann
    """Helper function for formatting name.
3438 8d99a8bf Michael Hanselmann

3439 8d99a8bf Michael Hanselmann
    """
3440 8d99a8bf Michael Hanselmann
    if name:
3441 8d99a8bf Michael Hanselmann
      return fmt % name
3442 8d99a8bf Michael Hanselmann
3443 8d99a8bf Michael Hanselmann
    return ""
3444 8d99a8bf Michael Hanselmann
3445 479636a3 Iustin Pop
  def QueueJob(self, name, *ops):
3446 23b4b983 Iustin Pop
    """Record a job for later submit.
3447 479636a3 Iustin Pop

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

3451 479636a3 Iustin Pop
    """
3452 cff5fa7f Iustin Pop
    SetGenericOpcodeOpts(ops, self.opts)
3453 60452edf Michael Hanselmann
    self.queue.append((self._counter.next(), name, ops))
3454 23b4b983 Iustin Pop
3455 8d99a8bf Michael Hanselmann
  def AddJobId(self, name, status, job_id):
3456 8d99a8bf Michael Hanselmann
    """Adds a job ID to the internal queue.
3457 8d99a8bf Michael Hanselmann

3458 8d99a8bf Michael Hanselmann
    """
3459 8d99a8bf Michael Hanselmann
    self.jobs.append((self._counter.next(), status, job_id, name))
3460 8d99a8bf Michael Hanselmann
3461 66ecc479 Guido Trotter
  def SubmitPending(self, each=False):
3462 23b4b983 Iustin Pop
    """Submit all pending jobs.
3463 23b4b983 Iustin Pop

3464 23b4b983 Iustin Pop
    """
3465 66ecc479 Guido Trotter
    if each:
3466 66ecc479 Guido Trotter
      results = []
3467 60452edf Michael Hanselmann
      for (_, _, ops) in self.queue:
3468 66ecc479 Guido Trotter
        # SubmitJob will remove the success status, but raise an exception if
3469 66ecc479 Guido Trotter
        # the submission fails, so we'll notice that anyway.
3470 519fafa1 Andrea Spadaccini
        results.append([True, self.cl.SubmitJob(ops)[0]])
3471 66ecc479 Guido Trotter
    else:
3472 60452edf Michael Hanselmann
      results = self.cl.SubmitManyJobs([ops for (_, _, ops) in self.queue])
3473 60452edf Michael Hanselmann
    for ((status, data), (idx, name, _)) in zip(results, self.queue):
3474 5299e61f Iustin Pop
      self.jobs.append((idx, status, data, name))
3475 5299e61f Iustin Pop
3476 5299e61f Iustin Pop
  def _ChooseJob(self):
3477 5299e61f Iustin Pop
    """Choose a non-waiting/queued job to poll next.
3478 5299e61f Iustin Pop

3479 5299e61f Iustin Pop
    """
3480 5299e61f Iustin Pop
    assert self.jobs, "_ChooseJob called with empty job list"
3481 5299e61f Iustin Pop
3482 11705e3d Iustin Pop
    result = self.cl.QueryJobs([i[2] for i in self.jobs[:_CHOOSE_BATCH]],
3483 11705e3d Iustin Pop
                               ["status"])
3484 5299e61f Iustin Pop
    assert result
3485 5299e61f Iustin Pop
3486 5299e61f Iustin Pop
    for job_data, status in zip(self.jobs, result):
3487 91c622a8 Iustin Pop
      if (isinstance(status, list) and status and
3488 91c622a8 Iustin Pop
          status[0] in (constants.JOB_STATUS_QUEUED,
3489 47099cd1 Michael Hanselmann
                        constants.JOB_STATUS_WAITING,
3490 91c622a8 Iustin Pop
                        constants.JOB_STATUS_CANCELING)):
3491 91c622a8 Iustin Pop
        # job is still present and waiting
3492 5299e61f Iustin Pop
        continue
3493 91c622a8 Iustin Pop
      # good candidate found (either running job or lost job)
3494 5299e61f Iustin Pop
      self.jobs.remove(job_data)
3495 5299e61f Iustin Pop
      return job_data
3496 5299e61f Iustin Pop
3497 5299e61f Iustin Pop
    # no job found
3498 5299e61f Iustin Pop
    return self.jobs.pop(0)
3499 479636a3 Iustin Pop
3500 479636a3 Iustin Pop
  def GetResults(self):
3501 479636a3 Iustin Pop
    """Wait for and return the results of all jobs.
3502 479636a3 Iustin Pop

3503 479636a3 Iustin Pop
    @rtype: list
3504 479636a3 Iustin Pop
    @return: list of tuples (success, job results), in the same order
3505 479636a3 Iustin Pop
        as the submitted jobs; if a job has failed, instead of the result
3506 479636a3 Iustin Pop
        there will be the error message
3507 479636a3 Iustin Pop

3508 479636a3 Iustin Pop
    """
3509 23b4b983 Iustin Pop
    if not self.jobs:
3510 23b4b983 Iustin Pop
      self.SubmitPending()
3511 479636a3 Iustin Pop
    results = []
3512 479636a3 Iustin Pop
    if self.verbose:
3513 5299e61f Iustin Pop
      ok_jobs = [row[2] for row in self.jobs if row[1]]
3514 23b4b983 Iustin Pop
      if ok_jobs:
3515 4474f112 Iustin Pop
        ToStdout("Submitted jobs %s", utils.CommaJoin(ok_jobs))
3516 5299e61f Iustin Pop
3517 5299e61f Iustin Pop
    # first, remove any non-submitted jobs
3518 cea881e5 Michael Hanselmann
    self.jobs, failures = compat.partition(self.jobs, lambda x: x[1])
3519 5299e61f Iustin Pop
    for idx, _, jid, name in failures:
3520 4474f112 Iustin Pop
      ToStderr("Failed to submit job%s: %s", self._IfName(name, " for %s"), jid)
3521 c63355f2 Iustin Pop
      results.append((idx, False, jid))
3522 5299e61f Iustin Pop
3523 5299e61f Iustin Pop
    while self.jobs:
3524 5299e61f Iustin Pop
      (idx, _, jid, name) = self._ChooseJob()
3525 4474f112 Iustin Pop
      ToStdout("Waiting for job %s%s ...", jid, self._IfName(name, " for %s"))
3526 479636a3 Iustin Pop
      try:
3527 919ca415 Iustin Pop
        job_result = PollJob(jid, cl=self.cl, feedback_fn=self.feedback_fn)
3528 479636a3 Iustin Pop
        success = True
3529 91c622a8 Iustin Pop
      except errors.JobLost, err:
3530 91c622a8 Iustin Pop
        _, job_result = FormatError(err)
3531 4474f112 Iustin Pop
        ToStderr("Job %s%s has been archived, cannot check its result",
3532 4474f112 Iustin Pop
                 jid, self._IfName(name, " for %s"))
3533 91c622a8 Iustin Pop
        success = False
3534 479636a3 Iustin Pop
      except (errors.GenericError, luxi.ProtocolError), err:
3535 479636a3 Iustin Pop
        _, job_result = FormatError(err)
3536 479636a3 Iustin Pop
        success = False
3537 479636a3 Iustin Pop
        # the error message will always be shown, verbose or not
3538 4474f112 Iustin Pop
        ToStderr("Job %s%s has failed: %s",
3539 4474f112 Iustin Pop
                 jid, self._IfName(name, " for %s"), job_result)
3540 479636a3 Iustin Pop
3541 5299e61f Iustin Pop
      results.append((idx, success, job_result))
3542 5299e61f Iustin Pop
3543 5299e61f Iustin Pop
    # sort based on the index, then drop it
3544 5299e61f Iustin Pop
    results.sort()
3545 5299e61f Iustin Pop
    results = [i[1:] for i in results]
3546 5299e61f Iustin Pop
3547 479636a3 Iustin Pop
    return results
3548 479636a3 Iustin Pop
3549 479636a3 Iustin Pop
  def WaitOrShow(self, wait):
3550 479636a3 Iustin Pop
    """Wait for job results or only print the job IDs.
3551 479636a3 Iustin Pop

3552 479636a3 Iustin Pop
    @type wait: boolean
3553 479636a3 Iustin Pop
    @param wait: whether to wait or not
3554 479636a3 Iustin Pop

3555 479636a3 Iustin Pop
    """
3556 479636a3 Iustin Pop
    if wait:
3557 479636a3 Iustin Pop
      return self.GetResults()
3558 479636a3 Iustin Pop
    else:
3559 23b4b983 Iustin Pop
      if not self.jobs:
3560 23b4b983 Iustin Pop
        self.SubmitPending()
3561 71834b2a Guido Trotter
      for _, status, result, name in self.jobs:
3562 23b4b983 Iustin Pop
        if status:
3563 4474f112 Iustin Pop
          ToStdout("%s: %s", result, name)
3564 23b4b983 Iustin Pop
        else:
3565 4474f112 Iustin Pop
          ToStderr("Failure for %s: %s", name, result)
3566 53a8a54d Iustin Pop
      return [row[1:3] for row in self.jobs]
3567 acd19189 René Nussbaumer
3568 acd19189 René Nussbaumer
3569 acd19189 René Nussbaumer
def FormatParameterDict(buf, param_dict, actual, level=1):
3570 acd19189 René Nussbaumer
  """Formats a parameter dictionary.
3571 acd19189 René Nussbaumer

3572 acd19189 René Nussbaumer
  @type buf: L{StringIO}
3573 acd19189 René Nussbaumer
  @param buf: the buffer into which to write
3574 acd19189 René Nussbaumer
  @type param_dict: dict
3575 acd19189 René Nussbaumer
  @param param_dict: the own parameters
3576 acd19189 René Nussbaumer
  @type actual: dict
3577 acd19189 René Nussbaumer
  @param actual: the current parameter set (including defaults)
3578 acd19189 René Nussbaumer
  @param level: Level of indent
3579 acd19189 René Nussbaumer

3580 acd19189 René Nussbaumer
  """
3581 acd19189 René Nussbaumer
  indent = "  " * level
3582 64da5a53 René Nussbaumer
3583 acd19189 René Nussbaumer
  for key in sorted(actual):
3584 64da5a53 René Nussbaumer
    data = actual[key]
3585 64da5a53 René Nussbaumer
    buf.write("%s- %s:" % (indent, key))
3586 64da5a53 René Nussbaumer
3587 64da5a53 René Nussbaumer
    if isinstance(data, dict) and data:
3588 64da5a53 René Nussbaumer
      buf.write("\n")
3589 64da5a53 René Nussbaumer
      FormatParameterDict(buf, param_dict.get(key, {}), data,
3590 64da5a53 René Nussbaumer
                          level=level + 1)
3591 64da5a53 René Nussbaumer
    else:
3592 64da5a53 René Nussbaumer
      val = param_dict.get(key, "default (%s)" % data)
3593 64da5a53 René Nussbaumer
      buf.write(" %s\n" % val)
3594 25bd815c René Nussbaumer
3595 25bd815c René Nussbaumer
3596 25bd815c René Nussbaumer
def ConfirmOperation(names, list_type, text, extra=""):
3597 25bd815c René Nussbaumer
  """Ask the user to confirm an operation on a list of list_type.
3598 25bd815c René Nussbaumer

3599 25bd815c René Nussbaumer
  This function is used to request confirmation for doing an operation
3600 25bd815c René Nussbaumer
  on a given list of list_type.
3601 25bd815c René Nussbaumer

3602 25bd815c René Nussbaumer
  @type names: list
3603 25bd815c René Nussbaumer
  @param names: the list of names that we display when
3604 25bd815c René Nussbaumer
      we ask for confirmation
3605 25bd815c René Nussbaumer
  @type list_type: str
3606 25bd815c René Nussbaumer
  @param list_type: Human readable name for elements in the list (e.g. nodes)
3607 25bd815c René Nussbaumer
  @type text: str
3608 25bd815c René Nussbaumer
  @param text: the operation that the user should confirm
3609 25bd815c René Nussbaumer
  @rtype: boolean
3610 25bd815c René Nussbaumer
  @return: True or False depending on user's confirmation.
3611 25bd815c René Nussbaumer

3612 25bd815c René Nussbaumer
  """
3613 25bd815c René Nussbaumer
  count = len(names)
3614 25bd815c René Nussbaumer
  msg = ("The %s will operate on %d %s.\n%s"
3615 25bd815c René Nussbaumer
         "Do you want to continue?" % (text, count, list_type, extra))
3616 25bd815c René Nussbaumer
  affected = (("\nAffected %s:\n" % list_type) +
3617 25bd815c René Nussbaumer
              "\n".join(["  %s" % name for name in names]))
3618 25bd815c René Nussbaumer
3619 25bd815c René Nussbaumer
  choices = [("y", True, "Yes, execute the %s" % text),
3620 25bd815c René Nussbaumer
             ("n", False, "No, abort the %s" % text)]
3621 25bd815c René Nussbaumer
3622 25bd815c René Nussbaumer
  if count > 20:
3623 25bd815c René Nussbaumer
    choices.insert(1, ("v", "v", "View the list of affected %s" % list_type))
3624 25bd815c René Nussbaumer
    question = msg
3625 25bd815c René Nussbaumer
  else:
3626 25bd815c René Nussbaumer
    question = msg + affected
3627 25bd815c René Nussbaumer
3628 25bd815c René Nussbaumer
  choice = AskUser(question, choices)
3629 25bd815c René Nussbaumer
  if choice == "v":
3630 25bd815c René Nussbaumer
    choices.pop(1)
3631 25bd815c René Nussbaumer
    choice = AskUser(msg + affected, choices)
3632 25bd815c René Nussbaumer
  return choice
3633 703fa9ab Iustin Pop
3634 703fa9ab Iustin Pop
3635 cd415612 René Nussbaumer
def _MaybeParseUnit(elements):
3636 cd415612 René Nussbaumer
  """Parses and returns an array of potential values with units.
3637 cd415612 René Nussbaumer

3638 cd415612 René Nussbaumer
  """
3639 ef40c537 René Nussbaumer
  parsed = {}
3640 ef40c537 René Nussbaumer
  for k, v in elements.items():
3641 ef40c537 René Nussbaumer
    if v == constants.VALUE_DEFAULT:
3642 ef40c537 René Nussbaumer
      parsed[k] = v
3643 cd415612 René Nussbaumer
    else:
3644 ef40c537 René Nussbaumer
      parsed[k] = utils.ParseUnit(v)
3645 cd415612 René Nussbaumer
  return parsed
3646 cd415612 René Nussbaumer
3647 cd415612 René Nussbaumer
3648 703fa9ab Iustin Pop
def CreateIPolicyFromOpts(ispecs_mem_size=None,
3649 703fa9ab Iustin Pop
                          ispecs_cpu_count=None,
3650 703fa9ab Iustin Pop
                          ispecs_disk_count=None,
3651 703fa9ab Iustin Pop
                          ispecs_disk_size=None,
3652 703fa9ab Iustin Pop
                          ispecs_nic_count=None,
3653 703fa9ab Iustin Pop
                          ipolicy_disk_templates=None,
3654 703fa9ab Iustin Pop
                          ipolicy_vcpu_ratio=None,
3655 ad5cc6bd René Nussbaumer
                          ipolicy_spindle_ratio=None,
3656 703fa9ab Iustin Pop
                          group_ipolicy=False,
3657 703fa9ab Iustin Pop
                          allowed_values=None,
3658 703fa9ab Iustin Pop
                          fill_all=False):
3659 703fa9ab Iustin Pop
  """Creation of instance policy based on command line options.
3660 703fa9ab Iustin Pop

3661 703fa9ab Iustin Pop
  @param fill_all: whether for cluster policies we should ensure that
3662 703fa9ab Iustin Pop
    all values are filled
3663 703fa9ab Iustin Pop

3664 703fa9ab Iustin Pop

3665 703fa9ab Iustin Pop
  """
3666 d67e0a94 Iustin Pop
  try:
3667 d67e0a94 Iustin Pop
    if ispecs_mem_size:
3668 cd415612 René Nussbaumer
      ispecs_mem_size = _MaybeParseUnit(ispecs_mem_size)
3669 d67e0a94 Iustin Pop
    if ispecs_disk_size:
3670 cd415612 René Nussbaumer
      ispecs_disk_size = _MaybeParseUnit(ispecs_disk_size)
3671 d67e0a94 Iustin Pop
  except (TypeError, ValueError, errors.UnitParseError), err:
3672 d67e0a94 Iustin Pop
    raise errors.OpPrereqError("Invalid disk (%s) or memory (%s) size"
3673 d67e0a94 Iustin Pop
                               " in policy: %s" %
3674 d67e0a94 Iustin Pop
                               (ispecs_disk_size, ispecs_mem_size, err),
3675 d67e0a94 Iustin Pop
                               errors.ECODE_INVAL)
3676 d67e0a94 Iustin Pop
3677 703fa9ab Iustin Pop
  # prepare ipolicy dict
3678 703fa9ab Iustin Pop
  ipolicy_transposed = {
3679 703fa9ab Iustin Pop
    constants.ISPEC_MEM_SIZE: ispecs_mem_size,
3680 703fa9ab Iustin Pop
    constants.ISPEC_CPU_COUNT: ispecs_cpu_count,
3681 703fa9ab Iustin Pop
    constants.ISPEC_DISK_COUNT: ispecs_disk_count,
3682 703fa9ab Iustin Pop
    constants.ISPEC_DISK_SIZE: ispecs_disk_size,
3683 703fa9ab Iustin Pop
    constants.ISPEC_NIC_COUNT: ispecs_nic_count,
3684 703fa9ab Iustin Pop
    }
3685 703fa9ab Iustin Pop
3686 703fa9ab Iustin Pop
  # first, check that the values given are correct
3687 703fa9ab Iustin Pop
  if group_ipolicy:
3688 703fa9ab Iustin Pop
    forced_type = TISPECS_GROUP_TYPES
3689 703fa9ab Iustin Pop
  else:
3690 703fa9ab Iustin Pop
    forced_type = TISPECS_CLUSTER_TYPES
3691 703fa9ab Iustin Pop
3692 703fa9ab Iustin Pop
  for specs in ipolicy_transposed.values():
3693 703fa9ab Iustin Pop
    utils.ForceDictType(specs, forced_type, allowed_values=allowed_values)
3694 703fa9ab Iustin Pop
3695 703fa9ab Iustin Pop
  # then transpose
3696 703fa9ab Iustin Pop
  ipolicy_out = objects.MakeEmptyIPolicy()
3697 703fa9ab Iustin Pop
  for name, specs in ipolicy_transposed.iteritems():
3698 703fa9ab Iustin Pop
    assert name in constants.ISPECS_PARAMETERS
3699 703fa9ab Iustin Pop
    for key, val in specs.items(): # {min: .. ,max: .., std: ..}
3700 703fa9ab Iustin Pop
      ipolicy_out[key][name] = val
3701 703fa9ab Iustin Pop
3702 703fa9ab Iustin Pop
  # no filldict for non-dicts
3703 703fa9ab Iustin Pop
  if not group_ipolicy and fill_all:
3704 703fa9ab Iustin Pop
    if ipolicy_disk_templates is None:
3705 703fa9ab Iustin Pop
      ipolicy_disk_templates = constants.DISK_TEMPLATES
3706 703fa9ab Iustin Pop
    if ipolicy_vcpu_ratio is None:
3707 703fa9ab Iustin Pop
      ipolicy_vcpu_ratio = \
3708 703fa9ab Iustin Pop
        constants.IPOLICY_DEFAULTS[constants.IPOLICY_VCPU_RATIO]
3709 ad5cc6bd René Nussbaumer
    if ipolicy_spindle_ratio is None:
3710 ad5cc6bd René Nussbaumer
      ipolicy_spindle_ratio = \
3711 ad5cc6bd René Nussbaumer
        constants.IPOLICY_DEFAULTS[constants.IPOLICY_SPINDLE_RATIO]
3712 703fa9ab Iustin Pop
  if ipolicy_disk_templates is not None:
3713 703fa9ab Iustin Pop
    ipolicy_out[constants.IPOLICY_DTS] = list(ipolicy_disk_templates)
3714 703fa9ab Iustin Pop
  if ipolicy_vcpu_ratio is not None:
3715 703fa9ab Iustin Pop
    ipolicy_out[constants.IPOLICY_VCPU_RATIO] = ipolicy_vcpu_ratio
3716 ad5cc6bd René Nussbaumer
  if ipolicy_spindle_ratio is not None:
3717 ad5cc6bd René Nussbaumer
    ipolicy_out[constants.IPOLICY_SPINDLE_RATIO] = ipolicy_spindle_ratio
3718 703fa9ab Iustin Pop
3719 703fa9ab Iustin Pop
  assert not (frozenset(ipolicy_out.keys()) - constants.IPOLICY_ALL_KEYS)
3720 703fa9ab Iustin Pop
3721 703fa9ab Iustin Pop
  return ipolicy_out