Statistics
| Branch: | Tag: | Revision:

root / lib / cli.py @ d027b72b

History | View | Annotate | Download (140.7 kB)

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

369 863d7f46 Michael Hanselmann
  Value can be any of the ones passed to the constructor.
370 863d7f46 Michael Hanselmann

371 863d7f46 Michael Hanselmann
  """
372 b459a848 Andrea Spadaccini
  # pylint: disable=W0622
373 863d7f46 Michael Hanselmann
  def __init__(self, min=0, max=None, choices=None):
374 863d7f46 Michael Hanselmann
    _Argument.__init__(self, min=min, max=max)
375 863d7f46 Michael Hanselmann
    self.choices = choices
376 863d7f46 Michael Hanselmann
377 863d7f46 Michael Hanselmann
  def __repr__(self):
378 863d7f46 Michael Hanselmann
    return ("<%s min=%s max=%s choices=%r>" %
379 863d7f46 Michael Hanselmann
            (self.__class__.__name__, self.min, self.max, self.choices))
380 863d7f46 Michael Hanselmann
381 863d7f46 Michael Hanselmann
382 863d7f46 Michael Hanselmann
class ArgChoice(ArgSuggest):
383 863d7f46 Michael Hanselmann
  """Choice argument.
384 863d7f46 Michael Hanselmann

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

388 863d7f46 Michael Hanselmann
  """
389 863d7f46 Michael Hanselmann
390 863d7f46 Michael Hanselmann
391 863d7f46 Michael Hanselmann
class ArgUnknown(_Argument):
392 863d7f46 Michael Hanselmann
  """Unknown argument to program (e.g. determined at runtime).
393 863d7f46 Michael Hanselmann

394 863d7f46 Michael Hanselmann
  """
395 863d7f46 Michael Hanselmann
396 863d7f46 Michael Hanselmann
397 863d7f46 Michael Hanselmann
class ArgInstance(_Argument):
398 863d7f46 Michael Hanselmann
  """Instances argument.
399 863d7f46 Michael Hanselmann

400 863d7f46 Michael Hanselmann
  """
401 863d7f46 Michael Hanselmann
402 863d7f46 Michael Hanselmann
403 863d7f46 Michael Hanselmann
class ArgNode(_Argument):
404 863d7f46 Michael Hanselmann
  """Node argument.
405 863d7f46 Michael Hanselmann

406 863d7f46 Michael Hanselmann
  """
407 863d7f46 Michael Hanselmann
408 667dbd6b Adeodato Simo
409 9c784fb3 Dimitris Aragiorgis
class ArgNetwork(_Argument):
410 9c784fb3 Dimitris Aragiorgis
  """Network argument.
411 9c784fb3 Dimitris Aragiorgis

412 9c784fb3 Dimitris Aragiorgis
  """
413 9c784fb3 Dimitris Aragiorgis
414 3c286190 Dimitris Aragiorgis
415 667dbd6b Adeodato Simo
class ArgGroup(_Argument):
416 667dbd6b Adeodato Simo
  """Node group argument.
417 667dbd6b Adeodato Simo

418 667dbd6b Adeodato Simo
  """
419 667dbd6b Adeodato Simo
420 667dbd6b Adeodato Simo
421 863d7f46 Michael Hanselmann
class ArgJobId(_Argument):
422 863d7f46 Michael Hanselmann
  """Job ID argument.
423 863d7f46 Michael Hanselmann

424 863d7f46 Michael Hanselmann
  """
425 863d7f46 Michael Hanselmann
426 863d7f46 Michael Hanselmann
427 863d7f46 Michael Hanselmann
class ArgFile(_Argument):
428 863d7f46 Michael Hanselmann
  """File path argument.
429 863d7f46 Michael Hanselmann

430 863d7f46 Michael Hanselmann
  """
431 863d7f46 Michael Hanselmann
432 863d7f46 Michael Hanselmann
433 863d7f46 Michael Hanselmann
class ArgCommand(_Argument):
434 863d7f46 Michael Hanselmann
  """Command argument.
435 863d7f46 Michael Hanselmann

436 863d7f46 Michael Hanselmann
  """
437 863d7f46 Michael Hanselmann
438 863d7f46 Michael Hanselmann
439 83ec7961 Michael Hanselmann
class ArgHost(_Argument):
440 83ec7961 Michael Hanselmann
  """Host argument.
441 83ec7961 Michael Hanselmann

442 83ec7961 Michael Hanselmann
  """
443 83ec7961 Michael Hanselmann
444 83ec7961 Michael Hanselmann
445 f9faf9c3 René Nussbaumer
class ArgOs(_Argument):
446 f9faf9c3 René Nussbaumer
  """OS argument.
447 f9faf9c3 René Nussbaumer

448 f9faf9c3 René Nussbaumer
  """
449 f9faf9c3 René Nussbaumer
450 f9faf9c3 René Nussbaumer
451 b954f097 Constantinos Venetsanopoulos
class ArgExtStorage(_Argument):
452 b954f097 Constantinos Venetsanopoulos
  """ExtStorage argument.
453 b954f097 Constantinos Venetsanopoulos

454 b954f097 Constantinos Venetsanopoulos
  """
455 b954f097 Constantinos Venetsanopoulos
456 b954f097 Constantinos Venetsanopoulos
457 4a265c08 Michael Hanselmann
ARGS_NONE = []
458 4a265c08 Michael Hanselmann
ARGS_MANY_INSTANCES = [ArgInstance()]
459 9c784fb3 Dimitris Aragiorgis
ARGS_MANY_NETWORKS = [ArgNetwork()]
460 4a265c08 Michael Hanselmann
ARGS_MANY_NODES = [ArgNode()]
461 667dbd6b Adeodato Simo
ARGS_MANY_GROUPS = [ArgGroup()]
462 4a265c08 Michael Hanselmann
ARGS_ONE_INSTANCE = [ArgInstance(min=1, max=1)]
463 9c784fb3 Dimitris Aragiorgis
ARGS_ONE_NETWORK = [ArgNetwork(min=1, max=1)]
464 4a265c08 Michael Hanselmann
ARGS_ONE_NODE = [ArgNode(min=1, max=1)]
465 dadf6b7d Michael Hanselmann
# TODO
466 dadf6b7d Michael Hanselmann
ARGS_ONE_GROUP = [ArgGroup(min=1, max=1)]
467 f9faf9c3 René Nussbaumer
ARGS_ONE_OS = [ArgOs(min=1, max=1)]
468 4a265c08 Michael Hanselmann
469 4a265c08 Michael Hanselmann
470 846baef9 Iustin Pop
def _ExtractTagsObject(opts, args):
471 846baef9 Iustin Pop
  """Extract the tag type object.
472 846baef9 Iustin Pop

473 846baef9 Iustin Pop
  Note that this function will modify its args parameter.
474 846baef9 Iustin Pop

475 846baef9 Iustin Pop
  """
476 846baef9 Iustin Pop
  if not hasattr(opts, "tag_type"):
477 846baef9 Iustin Pop
    raise errors.ProgrammerError("tag_type not passed to _ExtractTagsObject")
478 846baef9 Iustin Pop
  kind = opts.tag_type
479 846baef9 Iustin Pop
  if kind == constants.TAG_CLUSTER:
480 5cbf7832 Jose A. Lopes
    retval = kind, ""
481 819cbfe5 Michael Hanselmann
  elif kind in (constants.TAG_NODEGROUP,
482 819cbfe5 Michael Hanselmann
                constants.TAG_NODE,
483 8140e24f Dimitris Aragiorgis
                constants.TAG_NETWORK,
484 819cbfe5 Michael Hanselmann
                constants.TAG_INSTANCE):
485 846baef9 Iustin Pop
    if not args:
486 2cfbc784 Iustin Pop
      raise errors.OpPrereqError("no arguments passed to the command",
487 2cfbc784 Iustin Pop
                                 errors.ECODE_INVAL)
488 846baef9 Iustin Pop
    name = args.pop(0)
489 846baef9 Iustin Pop
    retval = kind, name
490 846baef9 Iustin Pop
  else:
491 846baef9 Iustin Pop
    raise errors.ProgrammerError("Unhandled tag type '%s'" % kind)
492 846baef9 Iustin Pop
  return retval
493 846baef9 Iustin Pop
494 846baef9 Iustin Pop
495 810c50b7 Iustin Pop
def _ExtendTags(opts, args):
496 810c50b7 Iustin Pop
  """Extend the args if a source file has been given.
497 810c50b7 Iustin Pop

498 810c50b7 Iustin Pop
  This function will extend the tags with the contents of the file
499 810c50b7 Iustin Pop
  passed in the 'tags_source' attribute of the opts parameter. A file
500 810c50b7 Iustin Pop
  named '-' will be replaced by stdin.
501 810c50b7 Iustin Pop

502 810c50b7 Iustin Pop
  """
503 810c50b7 Iustin Pop
  fname = opts.tags_source
504 810c50b7 Iustin Pop
  if fname is None:
505 810c50b7 Iustin Pop
    return
506 810c50b7 Iustin Pop
  if fname == "-":
507 810c50b7 Iustin Pop
    new_fh = sys.stdin
508 810c50b7 Iustin Pop
  else:
509 810c50b7 Iustin Pop
    new_fh = open(fname, "r")
510 810c50b7 Iustin Pop
  new_data = []
511 810c50b7 Iustin Pop
  try:
512 810c50b7 Iustin Pop
    # we don't use the nice 'new_data = [line.strip() for line in fh]'
513 810c50b7 Iustin Pop
    # because of python bug 1633941
514 810c50b7 Iustin Pop
    while True:
515 810c50b7 Iustin Pop
      line = new_fh.readline()
516 810c50b7 Iustin Pop
      if not line:
517 810c50b7 Iustin Pop
        break
518 810c50b7 Iustin Pop
      new_data.append(line.strip())
519 810c50b7 Iustin Pop
  finally:
520 810c50b7 Iustin Pop
    new_fh.close()
521 810c50b7 Iustin Pop
  args.extend(new_data)
522 810c50b7 Iustin Pop
523 810c50b7 Iustin Pop
524 846baef9 Iustin Pop
def ListTags(opts, args):
525 846baef9 Iustin Pop
  """List the tags on a given object.
526 846baef9 Iustin Pop

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

532 846baef9 Iustin Pop
  """
533 846baef9 Iustin Pop
  kind, name = _ExtractTagsObject(opts, args)
534 f2374060 Iustin Pop
  cl = GetClient(query=True)
535 7699c3af Iustin Pop
  result = cl.QueryTags(kind, name)
536 846baef9 Iustin Pop
  result = list(result)
537 846baef9 Iustin Pop
  result.sort()
538 846baef9 Iustin Pop
  for tag in result:
539 03298ebe Michael Hanselmann
    ToStdout(tag)
540 846baef9 Iustin Pop
541 846baef9 Iustin Pop
542 846baef9 Iustin Pop
def AddTags(opts, args):
543 846baef9 Iustin Pop
  """Add tags on a given object.
544 846baef9 Iustin Pop

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

550 846baef9 Iustin Pop
  """
551 846baef9 Iustin Pop
  kind, name = _ExtractTagsObject(opts, args)
552 810c50b7 Iustin Pop
  _ExtendTags(opts, args)
553 846baef9 Iustin Pop
  if not args:
554 2cfbc784 Iustin Pop
    raise errors.OpPrereqError("No tags to be added", errors.ECODE_INVAL)
555 d1602edc Iustin Pop
  op = opcodes.OpTagsSet(kind=kind, name=name, tags=args)
556 6bc3ed14 Michael Hanselmann
  SubmitOrSend(op, opts)
557 846baef9 Iustin Pop
558 846baef9 Iustin Pop
559 846baef9 Iustin Pop
def RemoveTags(opts, args):
560 846baef9 Iustin Pop
  """Remove tags from a given object.
561 846baef9 Iustin Pop

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

567 846baef9 Iustin Pop
  """
568 846baef9 Iustin Pop
  kind, name = _ExtractTagsObject(opts, args)
569 810c50b7 Iustin Pop
  _ExtendTags(opts, args)
570 846baef9 Iustin Pop
  if not args:
571 2cfbc784 Iustin Pop
    raise errors.OpPrereqError("No tags to be removed", errors.ECODE_INVAL)
572 3f0ab95f Iustin Pop
  op = opcodes.OpTagsDel(kind=kind, name=name, tags=args)
573 6bc3ed14 Michael Hanselmann
  SubmitOrSend(op, opts)
574 846baef9 Iustin Pop
575 a8083063 Iustin Pop
576 b459a848 Andrea Spadaccini
def check_unit(option, opt, value): # pylint: disable=W0613
577 65fe4693 Iustin Pop
  """OptParsers custom converter for units.
578 65fe4693 Iustin Pop

579 65fe4693 Iustin Pop
  """
580 a8083063 Iustin Pop
  try:
581 a8083063 Iustin Pop
    return utils.ParseUnit(value)
582 a8083063 Iustin Pop
  except errors.UnitParseError, err:
583 3ecf6786 Iustin Pop
    raise OptionValueError("option %s: %s" % (opt, err))
584 a8083063 Iustin Pop
585 a8083063 Iustin Pop
586 726ae450 Bernardo Dal Seno
def _SplitKeyVal(opt, data, parse_prefixes):
587 a8469393 Iustin Pop
  """Convert a KeyVal string into a dict.
588 a8469393 Iustin Pop

589 a8469393 Iustin Pop
  This function will convert a key=val[,...] string into a dict. Empty
590 a8469393 Iustin Pop
  values will be converted specially: keys which have the prefix 'no_'
591 726ae450 Bernardo Dal Seno
  will have the value=False and the prefix stripped, keys with the prefix
592 726ae450 Bernardo Dal Seno
  "-" will have value=None and the prefix stripped, and the others will
593 a8469393 Iustin Pop
  have value=True.
594 a8469393 Iustin Pop

595 a8469393 Iustin Pop
  @type opt: string
596 a8469393 Iustin Pop
  @param opt: a string holding the option name for which we process the
597 a8469393 Iustin Pop
      data, used in building error messages
598 a8469393 Iustin Pop
  @type data: string
599 a8469393 Iustin Pop
  @param data: a string of the format key=val,key=val,...
600 726ae450 Bernardo Dal Seno
  @type parse_prefixes: bool
601 726ae450 Bernardo Dal Seno
  @param parse_prefixes: whether to handle prefixes specially
602 a8469393 Iustin Pop
  @rtype: dict
603 a8469393 Iustin Pop
  @return: {key=val, key=val}
604 a8469393 Iustin Pop
  @raises errors.ParameterError: if there are duplicate keys
605 a8469393 Iustin Pop

606 a8469393 Iustin Pop
  """
607 a8469393 Iustin Pop
  kv_dict = {}
608 4f31882e Guido Trotter
  if data:
609 1b3a7656 Iustin Pop
    for elem in utils.UnescapeAndSplit(data, sep=","):
610 4f31882e Guido Trotter
      if "=" in elem:
611 4f31882e Guido Trotter
        key, val = elem.split("=", 1)
612 726ae450 Bernardo Dal Seno
      elif parse_prefixes:
613 4f31882e Guido Trotter
        if elem.startswith(NO_PREFIX):
614 4f31882e Guido Trotter
          key, val = elem[len(NO_PREFIX):], False
615 4f31882e Guido Trotter
        elif elem.startswith(UN_PREFIX):
616 4f31882e Guido Trotter
          key, val = elem[len(UN_PREFIX):], None
617 4f31882e Guido Trotter
        else:
618 4f31882e Guido Trotter
          key, val = elem, True
619 726ae450 Bernardo Dal Seno
      else:
620 726ae450 Bernardo Dal Seno
        raise errors.ParameterError("Missing value for key '%s' in option %s" %
621 726ae450 Bernardo Dal Seno
                                    (elem, opt))
622 4f31882e Guido Trotter
      if key in kv_dict:
623 4f31882e Guido Trotter
        raise errors.ParameterError("Duplicate key '%s' in option %s" %
624 4f31882e Guido Trotter
                                    (key, opt))
625 4f31882e Guido Trotter
      kv_dict[key] = val
626 a8469393 Iustin Pop
  return kv_dict
627 a8469393 Iustin Pop
628 a8469393 Iustin Pop
629 726ae450 Bernardo Dal Seno
def _SplitIdentKeyVal(opt, value, parse_prefixes):
630 726ae450 Bernardo Dal Seno
  """Helper function to parse "ident:key=val,key=val" options.
631 552c8dff Michael Hanselmann

632 726ae450 Bernardo Dal Seno
  @type opt: string
633 726ae450 Bernardo Dal Seno
  @param opt: option name, used in error messages
634 726ae450 Bernardo Dal Seno
  @type value: string
635 726ae450 Bernardo Dal Seno
  @param value: expected to be in the format "ident:key=val,key=val,..."
636 726ae450 Bernardo Dal Seno
  @type parse_prefixes: bool
637 726ae450 Bernardo Dal Seno
  @param parse_prefixes: whether to handle prefixes specially (see
638 726ae450 Bernardo Dal Seno
      L{_SplitKeyVal})
639 726ae450 Bernardo Dal Seno
  @rtype: tuple
640 726ae450 Bernardo Dal Seno
  @return: (ident, {key=val, key=val})
641 726ae450 Bernardo Dal Seno
  @raises errors.ParameterError: in case of duplicates or other parsing errors
642 a8469393 Iustin Pop

643 a8469393 Iustin Pop
  """
644 a8469393 Iustin Pop
  if ":" not in value:
645 d0c8c01d Iustin Pop
    ident, rest = value, ""
646 a8469393 Iustin Pop
  else:
647 a8469393 Iustin Pop
    ident, rest = value.split(":", 1)
648 8b46606c Guido Trotter
649 726ae450 Bernardo Dal Seno
  if parse_prefixes and ident.startswith(NO_PREFIX):
650 8b46606c Guido Trotter
    if rest:
651 8b46606c Guido Trotter
      msg = "Cannot pass options when removing parameter groups: %s" % value
652 8b46606c Guido Trotter
      raise errors.ParameterError(msg)
653 8b46606c Guido Trotter
    retval = (ident[len(NO_PREFIX):], False)
654 726ae450 Bernardo Dal Seno
  elif (parse_prefixes and ident.startswith(UN_PREFIX) and
655 726ae450 Bernardo Dal Seno
        (len(ident) <= len(UN_PREFIX) or not ident[len(UN_PREFIX)].isdigit())):
656 8b46606c Guido Trotter
    if rest:
657 8b46606c Guido Trotter
      msg = "Cannot pass options when removing parameter groups: %s" % value
658 8b46606c Guido Trotter
      raise errors.ParameterError(msg)
659 8b46606c Guido Trotter
    retval = (ident[len(UN_PREFIX):], None)
660 8b46606c Guido Trotter
  else:
661 726ae450 Bernardo Dal Seno
    kv_dict = _SplitKeyVal(opt, rest, parse_prefixes)
662 a8469393 Iustin Pop
    retval = (ident, kv_dict)
663 a8469393 Iustin Pop
  return retval
664 a8469393 Iustin Pop
665 a8469393 Iustin Pop
666 726ae450 Bernardo Dal Seno
def check_ident_key_val(option, opt, value):  # pylint: disable=W0613
667 726ae450 Bernardo Dal Seno
  """Custom parser for ident:key=val,key=val options.
668 726ae450 Bernardo Dal Seno

669 726ae450 Bernardo Dal Seno
  This will store the parsed values as a tuple (ident, {key: val}). As such,
670 726ae450 Bernardo Dal Seno
  multiple uses of this option via action=append is possible.
671 726ae450 Bernardo Dal Seno

672 726ae450 Bernardo Dal Seno
  """
673 726ae450 Bernardo Dal Seno
  return _SplitIdentKeyVal(opt, value, True)
674 726ae450 Bernardo Dal Seno
675 726ae450 Bernardo Dal Seno
676 b459a848 Andrea Spadaccini
def check_key_val(option, opt, value):  # pylint: disable=W0613
677 552c8dff Michael Hanselmann
  """Custom parser class for key=val,key=val options.
678 552c8dff Michael Hanselmann

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

681 a8469393 Iustin Pop
  """
682 726ae450 Bernardo Dal Seno
  return _SplitKeyVal(opt, value, True)
683 726ae450 Bernardo Dal Seno
684 726ae450 Bernardo Dal Seno
685 4884f187 Santi Raffa
def check_key_private_val(option, opt, value):  # pylint: disable=W0613
686 4884f187 Santi Raffa
  """Custom parser class for private and secret key=val,key=val options.
687 4884f187 Santi Raffa

688 4884f187 Santi Raffa
  This will store the parsed values as a dict {key: val}.
689 4884f187 Santi Raffa

690 4884f187 Santi Raffa
  """
691 4884f187 Santi Raffa
  return serializer.PrivateDict(_SplitKeyVal(opt, value, True))
692 4884f187 Santi Raffa
693 4884f187 Santi Raffa
694 726ae450 Bernardo Dal Seno
def _SplitListKeyVal(opt, value):
695 726ae450 Bernardo Dal Seno
  retval = {}
696 726ae450 Bernardo Dal Seno
  for elem in value.split("/"):
697 726ae450 Bernardo Dal Seno
    if not elem:
698 726ae450 Bernardo Dal Seno
      raise errors.ParameterError("Empty section in option '%s'" % opt)
699 726ae450 Bernardo Dal Seno
    (ident, valdict) = _SplitIdentKeyVal(opt, elem, False)
700 726ae450 Bernardo Dal Seno
    if ident in retval:
701 726ae450 Bernardo Dal Seno
      msg = ("Duplicated parameter '%s' in parsing %s: %s" %
702 726ae450 Bernardo Dal Seno
             (ident, opt, elem))
703 726ae450 Bernardo Dal Seno
      raise errors.ParameterError(msg)
704 726ae450 Bernardo Dal Seno
    retval[ident] = valdict
705 726ae450 Bernardo Dal Seno
  return retval
706 726ae450 Bernardo Dal Seno
707 726ae450 Bernardo Dal Seno
708 ef99e3e8 Bernardo Dal Seno
def check_multilist_ident_key_val(_, opt, value):
709 ef99e3e8 Bernardo Dal Seno
  """Custom parser for "ident:key=val,key=val/ident:key=val//ident:.." options.
710 726ae450 Bernardo Dal Seno

711 726ae450 Bernardo Dal Seno
  @rtype: list of dictionary
712 ef99e3e8 Bernardo Dal Seno
  @return: [{ident: {key: val, key: val}, ident: {key: val}}, {ident:..}]
713 726ae450 Bernardo Dal Seno

714 726ae450 Bernardo Dal Seno
  """
715 ef99e3e8 Bernardo Dal Seno
  retval = []
716 ef99e3e8 Bernardo Dal Seno
  for line in value.split("//"):
717 ef99e3e8 Bernardo Dal Seno
    retval.append(_SplitListKeyVal(opt, line))
718 ef99e3e8 Bernardo Dal Seno
  return retval
719 a8469393 Iustin Pop
720 a8469393 Iustin Pop
721 b459a848 Andrea Spadaccini
def check_bool(option, opt, value): # pylint: disable=W0613
722 e7b61bb0 Iustin Pop
  """Custom parser for yes/no options.
723 e7b61bb0 Iustin Pop

724 e7b61bb0 Iustin Pop
  This will store the parsed value as either True or False.
725 e7b61bb0 Iustin Pop

726 e7b61bb0 Iustin Pop
  """
727 e7b61bb0 Iustin Pop
  value = value.lower()
728 e7b61bb0 Iustin Pop
  if value == constants.VALUE_FALSE or value == "no":
729 e7b61bb0 Iustin Pop
    return False
730 e7b61bb0 Iustin Pop
  elif value == constants.VALUE_TRUE or value == "yes":
731 e7b61bb0 Iustin Pop
    return True
732 e7b61bb0 Iustin Pop
  else:
733 e7b61bb0 Iustin Pop
    raise errors.ParameterError("Invalid boolean value '%s'" % value)
734 e7b61bb0 Iustin Pop
735 e7b61bb0 Iustin Pop
736 499eb088 Iustin Pop
def check_list(option, opt, value): # pylint: disable=W0613
737 499eb088 Iustin Pop
  """Custom parser for comma-separated lists.
738 499eb088 Iustin Pop

739 499eb088 Iustin Pop
  """
740 499eb088 Iustin Pop
  # we have to make this explicit check since "".split(",") is [""],
741 499eb088 Iustin Pop
  # not an empty list :(
742 499eb088 Iustin Pop
  if not value:
743 499eb088 Iustin Pop
    return []
744 499eb088 Iustin Pop
  else:
745 499eb088 Iustin Pop
    return utils.UnescapeAndSplit(value)
746 499eb088 Iustin Pop
747 499eb088 Iustin Pop
748 cd415612 René Nussbaumer
def check_maybefloat(option, opt, value): # pylint: disable=W0613
749 cd415612 René Nussbaumer
  """Custom parser for float numbers which might be also defaults.
750 cd415612 René Nussbaumer

751 cd415612 René Nussbaumer
  """
752 cd415612 René Nussbaumer
  value = value.lower()
753 cd415612 René Nussbaumer
754 cd415612 René Nussbaumer
  if value == constants.VALUE_DEFAULT:
755 cd415612 René Nussbaumer
    return value
756 cd415612 René Nussbaumer
  else:
757 cd415612 René Nussbaumer
    return float(value)
758 cd415612 René Nussbaumer
759 cd415612 René Nussbaumer
760 63d44c55 Michael Hanselmann
# completion_suggestion is normally a list. Using numeric values not evaluating
761 63d44c55 Michael Hanselmann
# to False for dynamic completion.
762 63d44c55 Michael Hanselmann
(OPT_COMPL_MANY_NODES,
763 63d44c55 Michael Hanselmann
 OPT_COMPL_ONE_NODE,
764 63d44c55 Michael Hanselmann
 OPT_COMPL_ONE_INSTANCE,
765 63d44c55 Michael Hanselmann
 OPT_COMPL_ONE_OS,
766 b954f097 Constantinos Venetsanopoulos
 OPT_COMPL_ONE_EXTSTORAGE,
767 2d3ed64b Michael Hanselmann
 OPT_COMPL_ONE_IALLOCATOR,
768 9c784fb3 Dimitris Aragiorgis
 OPT_COMPL_ONE_NETWORK,
769 36e247e1 Guido Trotter
 OPT_COMPL_INST_ADD_NODES,
770 b954f097 Constantinos Venetsanopoulos
 OPT_COMPL_ONE_NODEGROUP) = range(100, 109)
771 63d44c55 Michael Hanselmann
772 b8028dcf Michael Hanselmann
OPT_COMPL_ALL = compat.UniqueFrozenset([
773 63d44c55 Michael Hanselmann
  OPT_COMPL_MANY_NODES,
774 63d44c55 Michael Hanselmann
  OPT_COMPL_ONE_NODE,
775 63d44c55 Michael Hanselmann
  OPT_COMPL_ONE_INSTANCE,
776 63d44c55 Michael Hanselmann
  OPT_COMPL_ONE_OS,
777 b954f097 Constantinos Venetsanopoulos
  OPT_COMPL_ONE_EXTSTORAGE,
778 63d44c55 Michael Hanselmann
  OPT_COMPL_ONE_IALLOCATOR,
779 9c784fb3 Dimitris Aragiorgis
  OPT_COMPL_ONE_NETWORK,
780 2d3ed64b Michael Hanselmann
  OPT_COMPL_INST_ADD_NODES,
781 36e247e1 Guido Trotter
  OPT_COMPL_ONE_NODEGROUP,
782 63d44c55 Michael Hanselmann
  ])
783 63d44c55 Michael Hanselmann
784 63d44c55 Michael Hanselmann
785 552c8dff Michael Hanselmann
class CliOption(Option):
786 552c8dff Michael Hanselmann
  """Custom option class for optparse.
787 a8469393 Iustin Pop

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

1558 552328b8 Michael Hanselmann
  """
1559 552328b8 Michael Hanselmann
  value = _PRIONAME_TO_VALUE[value]
1560 552328b8 Michael Hanselmann
1561 552328b8 Michael Hanselmann
  setattr(parser.values, option.dest, value)
1562 552328b8 Michael Hanselmann
1563 552328b8 Michael Hanselmann
1564 84a5b33c Michael Hanselmann
PRIORITY_OPT = cli_option("--priority", default=None, dest="priority",
1565 84a5b33c Michael Hanselmann
                          metavar="|".join(name for name, _ in _PRIORITY_NAMES),
1566 84a5b33c Michael Hanselmann
                          choices=_PRIONAME_TO_VALUE.keys(),
1567 552328b8 Michael Hanselmann
                          action="callback", type="choice",
1568 552328b8 Michael Hanselmann
                          callback=_PriorityOptionCb,
1569 aa06f8c6 Michael Hanselmann
                          help="Priority for opcode processing")
1570 84a5b33c Michael Hanselmann
1571 61a14bb3 Iustin Pop
HID_OS_OPT = cli_option("--hidden", dest="hidden",
1572 61a14bb3 Iustin Pop
                        type="bool", default=None, metavar=_YORNO,
1573 61a14bb3 Iustin Pop
                        help="Sets the hidden flag on the OS")
1574 61a14bb3 Iustin Pop
1575 61a14bb3 Iustin Pop
BLK_OS_OPT = cli_option("--blacklisted", dest="blacklisted",
1576 61a14bb3 Iustin Pop
                        type="bool", default=None, metavar=_YORNO,
1577 61a14bb3 Iustin Pop
                        help="Sets the blacklisted flag on the OS")
1578 61a14bb3 Iustin Pop
1579 b883637f René Nussbaumer
PREALLOC_WIPE_DISKS_OPT = cli_option("--prealloc-wipe-disks", default=None,
1580 b883637f René Nussbaumer
                                     type="bool", metavar=_YORNO,
1581 b883637f René Nussbaumer
                                     dest="prealloc_wipe_disks",
1582 b883637f René Nussbaumer
                                     help=("Wipe disks prior to instance"
1583 b883637f René Nussbaumer
                                           " creation"))
1584 b883637f René Nussbaumer
1585 a535cef7 René Nussbaumer
NODE_PARAMS_OPT = cli_option("--node-parameters", dest="ndparams",
1586 3c2b6a98 René Nussbaumer
                             type="keyval", default=None,
1587 a535cef7 René Nussbaumer
                             help="Node parameters")
1588 a535cef7 René Nussbaumer
1589 90e99856 Adeodato Simo
ALLOC_POLICY_OPT = cli_option("--alloc-policy", dest="alloc_policy",
1590 90e99856 Adeodato Simo
                              action="store", metavar="POLICY", default=None,
1591 90e99856 Adeodato Simo
                              help="Allocation policy for the node group")
1592 90e99856 Adeodato Simo
1593 d2881c71 René Nussbaumer
NODE_POWERED_OPT = cli_option("--node-powered", default=None,
1594 d2881c71 René Nussbaumer
                              type="bool", metavar=_YORNO,
1595 d2881c71 René Nussbaumer
                              dest="node_powered",
1596 d2881c71 René Nussbaumer
                              help="Specify if the SoR for node is powered")
1597 d2881c71 René Nussbaumer
1598 41543d8b René Nussbaumer
OOB_TIMEOUT_OPT = cli_option("--oob-timeout", dest="oob_timeout", type="int",
1599 5ae4945a Iustin Pop
                             default=constants.OOB_TIMEOUT,
1600 5ae4945a Iustin Pop
                             help="Maximum time to wait for out-of-band helper")
1601 41543d8b René Nussbaumer
1602 0c086a13 René Nussbaumer
POWER_DELAY_OPT = cli_option("--power-delay", dest="power_delay", type="float",
1603 0c086a13 René Nussbaumer
                             default=constants.OOB_POWER_DELAY,
1604 0c086a13 René Nussbaumer
                             help="Time in seconds to wait between power-ons")
1605 0c086a13 René Nussbaumer
1606 442587bf Michael Hanselmann
FORCE_FILTER_OPT = cli_option("-F", "--filter", dest="force_filter",
1607 442587bf Michael Hanselmann
                              action="store_true", default=False,
1608 442587bf Michael Hanselmann
                              help=("Whether command argument should be treated"
1609 442587bf Michael Hanselmann
                                    " as filter"))
1610 442587bf Michael Hanselmann
1611 885a0fc4 Iustin Pop
NO_REMEMBER_OPT = cli_option("--no-remember",
1612 885a0fc4 Iustin Pop
                             dest="no_remember",
1613 885a0fc4 Iustin Pop
                             action="store_true", default=False,
1614 885a0fc4 Iustin Pop
                             help="Perform but do not record the change"
1615 885a0fc4 Iustin Pop
                             " in the configuration")
1616 885a0fc4 Iustin Pop
1617 aafee533 Michael Hanselmann
PRIMARY_ONLY_OPT = cli_option("-p", "--primary-only",
1618 aafee533 Michael Hanselmann
                              default=False, action="store_true",
1619 aafee533 Michael Hanselmann
                              help="Evacuate primary instances only")
1620 aafee533 Michael Hanselmann
1621 aafee533 Michael Hanselmann
SECONDARY_ONLY_OPT = cli_option("-s", "--secondary-only",
1622 aafee533 Michael Hanselmann
                                default=False, action="store_true",
1623 aafee533 Michael Hanselmann
                                help="Evacuate secondary instances only"
1624 aafee533 Michael Hanselmann
                                     " (applies only to internally mirrored"
1625 aafee533 Michael Hanselmann
                                     " disk templates, e.g. %s)" %
1626 aafee533 Michael Hanselmann
                                     utils.CommaJoin(constants.DTS_INT_MIRROR))
1627 aafee533 Michael Hanselmann
1628 323f9095 Stephen Shirley
STARTUP_PAUSED_OPT = cli_option("--paused", dest="startup_paused",
1629 323f9095 Stephen Shirley
                                action="store_true", default=False,
1630 323f9095 Stephen Shirley
                                help="Pause instance at startup")
1631 323f9095 Stephen Shirley
1632 f6eb380d Michael Hanselmann
TO_GROUP_OPT = cli_option("--to", dest="to", metavar="<group>",
1633 f6eb380d Michael Hanselmann
                          help="Destination node group (name or uuid)",
1634 f6eb380d Michael Hanselmann
                          default=None, action="append",
1635 f6eb380d Michael Hanselmann
                          completion_suggest=OPT_COMPL_ONE_NODEGROUP)
1636 f6eb380d Michael Hanselmann
1637 93f2399e Andrea Spadaccini
IGNORE_ERRORS_OPT = cli_option("-I", "--ignore-errors", default=[],
1638 93f2399e Andrea Spadaccini
                               action="append", dest="ignore_errors",
1639 93f2399e Andrea Spadaccini
                               choices=list(constants.CV_ALL_ECODES_STRINGS),
1640 93f2399e Andrea Spadaccini
                               help="Error code to be ignored")
1641 93f2399e Andrea Spadaccini
1642 38f29a36 René Nussbaumer
DISK_STATE_OPT = cli_option("--disk-state", default=[], dest="disk_state",
1643 38f29a36 René Nussbaumer
                            action="append",
1644 a1cef552 Iustin Pop
                            help=("Specify disk state information in the"
1645 a1cef552 Iustin Pop
                                  " format"
1646 a1cef552 Iustin Pop
                                  " storage_type/identifier:option=value,...;"
1647 a1cef552 Iustin Pop
                                  " note this is unused for now"),
1648 38f29a36 René Nussbaumer
                            type="identkeyval")
1649 38f29a36 René Nussbaumer
1650 38f29a36 René Nussbaumer
HV_STATE_OPT = cli_option("--hypervisor-state", default=[], dest="hv_state",
1651 38f29a36 René Nussbaumer
                          action="append",
1652 38f29a36 René Nussbaumer
                          help=("Specify hypervisor state information in the"
1653 a1cef552 Iustin Pop
                                " format hypervisor:option=value,...;"
1654 a1cef552 Iustin Pop
                                " note this is unused for now"),
1655 38f29a36 René Nussbaumer
                          type="identkeyval")
1656 38f29a36 René Nussbaumer
1657 b6aaf437 René Nussbaumer
IGNORE_IPOLICY_OPT = cli_option("--ignore-ipolicy", dest="ignore_ipolicy",
1658 b6aaf437 René Nussbaumer
                                action="store_true", default=False,
1659 b6aaf437 René Nussbaumer
                                help="Ignore instance policy violations")
1660 b6aaf437 René Nussbaumer
1661 2c0af7da Guido Trotter
RUNTIME_MEM_OPT = cli_option("-m", "--runtime-memory", dest="runtime_mem",
1662 2c0af7da Guido Trotter
                             help="Sets the instance's runtime memory,"
1663 2c0af7da Guido Trotter
                             " ballooning it up or down to the new value",
1664 2c0af7da Guido Trotter
                             default=None, type="unit", metavar="<size>")
1665 61a14bb3 Iustin Pop
1666 ef8270dc Iustin Pop
ABSOLUTE_OPT = cli_option("--absolute", dest="absolute",
1667 ef8270dc Iustin Pop
                          action="store_true", default=False,
1668 ef8270dc Iustin Pop
                          help="Marks the grow as absolute instead of the"
1669 ef8270dc Iustin Pop
                          " (default) relative mode")
1670 ef8270dc Iustin Pop
1671 9c784fb3 Dimitris Aragiorgis
NETWORK_OPT = cli_option("--network",
1672 9c784fb3 Dimitris Aragiorgis
                         action="store", default=None, dest="network",
1673 9c784fb3 Dimitris Aragiorgis
                         help="IP network in CIDR notation")
1674 9c784fb3 Dimitris Aragiorgis
1675 9c784fb3 Dimitris Aragiorgis
GATEWAY_OPT = cli_option("--gateway",
1676 9c784fb3 Dimitris Aragiorgis
                         action="store", default=None, dest="gateway",
1677 9c784fb3 Dimitris Aragiorgis
                         help="IP address of the router (gateway)")
1678 9c784fb3 Dimitris Aragiorgis
1679 9c784fb3 Dimitris Aragiorgis
ADD_RESERVED_IPS_OPT = cli_option("--add-reserved-ips",
1680 9c784fb3 Dimitris Aragiorgis
                                  action="store", default=None,
1681 9c784fb3 Dimitris Aragiorgis
                                  dest="add_reserved_ips",
1682 9c784fb3 Dimitris Aragiorgis
                                  help="Comma-separated list of"
1683 9c784fb3 Dimitris Aragiorgis
                                  " reserved IPs to add")
1684 9c784fb3 Dimitris Aragiorgis
1685 9c784fb3 Dimitris Aragiorgis
REMOVE_RESERVED_IPS_OPT = cli_option("--remove-reserved-ips",
1686 9c784fb3 Dimitris Aragiorgis
                                     action="store", default=None,
1687 9c784fb3 Dimitris Aragiorgis
                                     dest="remove_reserved_ips",
1688 9c784fb3 Dimitris Aragiorgis
                                     help="Comma-delimited list of"
1689 9c784fb3 Dimitris Aragiorgis
                                     " reserved IPs to remove")
1690 9c784fb3 Dimitris Aragiorgis
1691 9c784fb3 Dimitris Aragiorgis
NETWORK6_OPT = cli_option("--network6",
1692 9c784fb3 Dimitris Aragiorgis
                          action="store", default=None, dest="network6",
1693 9c784fb3 Dimitris Aragiorgis
                          help="IP network in CIDR notation")
1694 9c784fb3 Dimitris Aragiorgis
1695 9c784fb3 Dimitris Aragiorgis
GATEWAY6_OPT = cli_option("--gateway6",
1696 9c784fb3 Dimitris Aragiorgis
                          action="store", default=None, dest="gateway6",
1697 9c784fb3 Dimitris Aragiorgis
                          help="IP6 address of the router (gateway)")
1698 9c784fb3 Dimitris Aragiorgis
1699 9c784fb3 Dimitris Aragiorgis
NOCONFLICTSCHECK_OPT = cli_option("--no-conflicts-check",
1700 9c784fb3 Dimitris Aragiorgis
                                  dest="conflicts_check",
1701 9c784fb3 Dimitris Aragiorgis
                                  default=True,
1702 9c784fb3 Dimitris Aragiorgis
                                  action="store_false",
1703 9c784fb3 Dimitris Aragiorgis
                                  help="Don't check for conflicting IPs")
1704 9c784fb3 Dimitris Aragiorgis
1705 ea9d3b40 Bernardo Dal Seno
INCLUDEDEFAULTS_OPT = cli_option("--include-defaults", dest="include_defaults",
1706 ea9d3b40 Bernardo Dal Seno
                                 default=False, action="store_true",
1707 ea9d3b40 Bernardo Dal Seno
                                 help="Include default values")
1708 ea9d3b40 Bernardo Dal Seno
1709 df58ca1c Dimitris Aragiorgis
HOTPLUG_OPT = cli_option("--hotplug", dest="hotplug",
1710 df58ca1c Dimitris Aragiorgis
                         action="store_true", default=False,
1711 e15a00dc Dimitris Aragiorgis
                         help="Hotplug supported devices (NICs and Disks)")
1712 df58ca1c Dimitris Aragiorgis
1713 96ed3a3e Dimitris Aragiorgis
HOTPLUG_IF_POSSIBLE_OPT = cli_option("--hotplug-if-possible",
1714 96ed3a3e Dimitris Aragiorgis
                                     dest="hotplug_if_possible",
1715 96ed3a3e Dimitris Aragiorgis
                                     action="store_true", default=False,
1716 96ed3a3e Dimitris Aragiorgis
                                     help="Hotplug devices in case"
1717 96ed3a3e Dimitris Aragiorgis
                                          " hotplug is supported")
1718 96ed3a3e Dimitris Aragiorgis
1719 015f1517 Jose A. Lopes
INSTANCE_COMMUNICATION_OPT = \
1720 015f1517 Jose A. Lopes
    cli_option("-c", "--communication",
1721 015f1517 Jose A. Lopes
               default=False,
1722 015f1517 Jose A. Lopes
               dest="instance_communication",
1723 015f1517 Jose A. Lopes
               help=constants.INSTANCE_COMMUNICATION_DOC,
1724 015f1517 Jose A. Lopes
               type="bool")
1725 015f1517 Jose A. Lopes
1726 5786c087 Michael Hanselmann
#: Options provided by all commands
1727 aa4fff02 Michele Tartara
COMMON_OPTS = [DEBUG_OPT, REASON_OPT]
1728 5786c087 Michael Hanselmann
1729 d6cd74dd Klaus Aehlig
# options related to asynchronous job handling
1730 d6cd74dd Klaus Aehlig
1731 d6cd74dd Klaus Aehlig
SUBMIT_OPTS = [
1732 d6cd74dd Klaus Aehlig
  SUBMIT_OPT,
1733 d6cd74dd Klaus Aehlig
  PRINT_JOBID_OPT,
1734 d6cd74dd Klaus Aehlig
  ]
1735 d6cd74dd Klaus Aehlig
1736 eb28ecf6 Guido Trotter
# common options for creating instances. add and import then add their own
1737 eb28ecf6 Guido Trotter
# specific ones.
1738 eb28ecf6 Guido Trotter
COMMON_CREATE_OPTS = [
1739 eb28ecf6 Guido Trotter
  BACKEND_OPT,
1740 eb28ecf6 Guido Trotter
  DISK_OPT,
1741 eb28ecf6 Guido Trotter
  DISK_TEMPLATE_OPT,
1742 eb28ecf6 Guido Trotter
  FILESTORE_DIR_OPT,
1743 eb28ecf6 Guido Trotter
  FILESTORE_DRIVER_OPT,
1744 eb28ecf6 Guido Trotter
  HYPERVISOR_OPT,
1745 eb28ecf6 Guido Trotter
  IALLOCATOR_OPT,
1746 eb28ecf6 Guido Trotter
  NET_OPT,
1747 eb28ecf6 Guido Trotter
  NODE_PLACEMENT_OPT,
1748 eb28ecf6 Guido Trotter
  NOIPCHECK_OPT,
1749 9c784fb3 Dimitris Aragiorgis
  NOCONFLICTSCHECK_OPT,
1750 eb28ecf6 Guido Trotter
  NONAMECHECK_OPT,
1751 eb28ecf6 Guido Trotter
  NONICS_OPT,
1752 eb28ecf6 Guido Trotter
  NWSYNC_OPT,
1753 eb28ecf6 Guido Trotter
  OSPARAMS_OPT,
1754 d027b72b Jose A. Lopes
  OSPARAMS_PRIVATE_OPT,
1755 d027b72b Jose A. Lopes
  OSPARAMS_SECRET_OPT,
1756 eb28ecf6 Guido Trotter
  OS_SIZE_OPT,
1757 eb28ecf6 Guido Trotter
  SUBMIT_OPT,
1758 d6cd74dd Klaus Aehlig
  PRINT_JOBID_OPT,
1759 0f8810df Michael Hanselmann
  TAG_ADD_OPT,
1760 eb28ecf6 Guido Trotter
  DRY_RUN_OPT,
1761 eb28ecf6 Guido Trotter
  PRIORITY_OPT,
1762 eb28ecf6 Guido Trotter
  ]
1763 eb28ecf6 Guido Trotter
1764 0ce212e5 Iustin Pop
# common instance policy options
1765 0ce212e5 Iustin Pop
INSTANCE_POLICY_OPTS = [
1766 919db916 Bernardo Dal Seno
  IPOLICY_BOUNDS_SPECS_OPT,
1767 919db916 Bernardo Dal Seno
  IPOLICY_DISK_TEMPLATES,
1768 919db916 Bernardo Dal Seno
  IPOLICY_VCPU_RATIO,
1769 919db916 Bernardo Dal Seno
  IPOLICY_SPINDLE_RATIO,
1770 919db916 Bernardo Dal Seno
  ]
1771 919db916 Bernardo Dal Seno
1772 919db916 Bernardo Dal Seno
# instance policy split specs options
1773 919db916 Bernardo Dal Seno
SPLIT_ISPECS_OPTS = [
1774 0ce212e5 Iustin Pop
  SPECS_CPU_COUNT_OPT,
1775 0ce212e5 Iustin Pop
  SPECS_DISK_COUNT_OPT,
1776 0ce212e5 Iustin Pop
  SPECS_DISK_SIZE_OPT,
1777 0ce212e5 Iustin Pop
  SPECS_MEM_SIZE_OPT,
1778 0ce212e5 Iustin Pop
  SPECS_NIC_COUNT_OPT,
1779 0ce212e5 Iustin Pop
  ]
1780 0ce212e5 Iustin Pop
1781 771734c9 Iustin Pop
1782 d971402f Michael Hanselmann
class _ShowUsage(Exception):
1783 d971402f Michael Hanselmann
  """Exception class for L{_ParseArgs}.
1784 d971402f Michael Hanselmann

1785 d971402f Michael Hanselmann
  """
1786 d971402f Michael Hanselmann
  def __init__(self, exit_error):
1787 d971402f Michael Hanselmann
    """Initializes instances of this class.
1788 d971402f Michael Hanselmann

1789 d971402f Michael Hanselmann
    @type exit_error: bool
1790 d971402f Michael Hanselmann
    @param exit_error: Whether to report failure on exit
1791 d971402f Michael Hanselmann

1792 d971402f Michael Hanselmann
    """
1793 d971402f Michael Hanselmann
    Exception.__init__(self)
1794 d971402f Michael Hanselmann
    self.exit_error = exit_error
1795 d971402f Michael Hanselmann
1796 d971402f Michael Hanselmann
1797 d971402f Michael Hanselmann
class _ShowVersion(Exception):
1798 d971402f Michael Hanselmann
  """Exception class for L{_ParseArgs}.
1799 d971402f Michael Hanselmann

1800 d971402f Michael Hanselmann
  """
1801 d971402f Michael Hanselmann
1802 d971402f Michael Hanselmann
1803 d971402f Michael Hanselmann
def _ParseArgs(binary, argv, commands, aliases, env_override):
1804 c41eea6e Iustin Pop
  """Parser for the command line arguments.
1805 a8083063 Iustin Pop

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

1809 d971402f Michael Hanselmann
  @param binary: Script name
1810 d971402f Michael Hanselmann
  @param argv: Command line arguments
1811 d971402f Michael Hanselmann
  @param commands: Dictionary containing command definitions
1812 d971402f Michael Hanselmann
  @param aliases: dictionary with command aliases {"alias": "target", ...}
1813 ef9fa5b9 René Nussbaumer
  @param env_override: list of env variables allowed for default args
1814 d971402f Michael Hanselmann
  @raise _ShowUsage: If usage description should be shown
1815 d971402f Michael Hanselmann
  @raise _ShowVersion: If version should be shown
1816 098c0958 Michael Hanselmann

1817 a8083063 Iustin Pop
  """
1818 ef9fa5b9 René Nussbaumer
  assert not (env_override - set(commands))
1819 d971402f Michael Hanselmann
  assert not (set(aliases.keys()) & set(commands.keys()))
1820 ef9fa5b9 René Nussbaumer
1821 d971402f Michael Hanselmann
  if len(argv) > 1:
1822 d971402f Michael Hanselmann
    cmd = argv[1]
1823 a8083063 Iustin Pop
  else:
1824 d971402f Michael Hanselmann
    # No option or command given
1825 d971402f Michael Hanselmann
    raise _ShowUsage(exit_error=True)
1826 a8083063 Iustin Pop
1827 d971402f Michael Hanselmann
  if cmd == "--version":
1828 d971402f Michael Hanselmann
    raise _ShowVersion()
1829 d971402f Michael Hanselmann
  elif cmd == "--help":
1830 d971402f Michael Hanselmann
    raise _ShowUsage(exit_error=False)
1831 d971402f Michael Hanselmann
  elif not (cmd in commands or cmd in aliases):
1832 d971402f Michael Hanselmann
    raise _ShowUsage(exit_error=True)
1833 de47cf8f Guido Trotter
1834 de47cf8f Guido Trotter
  # get command, unalias it, and look it up in commands
1835 de47cf8f Guido Trotter
  if cmd in aliases:
1836 de47cf8f Guido Trotter
    if aliases[cmd] not in commands:
1837 de47cf8f Guido Trotter
      raise errors.ProgrammerError("Alias '%s' maps to non-existing"
1838 de47cf8f Guido Trotter
                                   " command '%s'" % (cmd, aliases[cmd]))
1839 de47cf8f Guido Trotter
1840 de47cf8f Guido Trotter
    cmd = aliases[cmd]
1841 de47cf8f Guido Trotter
1842 ef9fa5b9 René Nussbaumer
  if cmd in env_override:
1843 ef9fa5b9 René Nussbaumer
    args_env_name = ("%s_%s" % (binary.replace("-", "_"), cmd)).upper()
1844 ef9fa5b9 René Nussbaumer
    env_args = os.environ.get(args_env_name)
1845 ef9fa5b9 René Nussbaumer
    if env_args:
1846 d971402f Michael Hanselmann
      argv = utils.InsertAtPos(argv, 2, shlex.split(env_args))
1847 ef9fa5b9 René Nussbaumer
1848 a8005e17 Michael Hanselmann
  func, args_def, parser_opts, usage, description = commands[cmd]
1849 bf5338b3 Michael Hanselmann
  parser = OptionParser(option_list=parser_opts + COMMON_OPTS,
1850 bf5338b3 Michael Hanselmann
                        description=description,
1851 bf5338b3 Michael Hanselmann
                        formatter=TitledHelpFormatter(),
1852 bf5338b3 Michael Hanselmann
                        usage="%%prog %s %s" % (cmd, usage))
1853 a8083063 Iustin Pop
  parser.disable_interspersed_args()
1854 d971402f Michael Hanselmann
  options, args = parser.parse_args(args=argv[2:])
1855 a8005e17 Michael Hanselmann
1856 a8005e17 Michael Hanselmann
  if not _CheckArguments(cmd, args_def, args):
1857 a8083063 Iustin Pop
    return None, None, None
1858 a8083063 Iustin Pop
1859 a8083063 Iustin Pop
  return func, options, args
1860 a8083063 Iustin Pop
1861 a8083063 Iustin Pop
1862 d971402f Michael Hanselmann
def _FormatUsage(binary, commands):
1863 d971402f Michael Hanselmann
  """Generates a nice description of all commands.
1864 d971402f Michael Hanselmann

1865 d971402f Michael Hanselmann
  @param binary: Script name
1866 d971402f Michael Hanselmann
  @param commands: Dictionary containing command definitions
1867 d971402f Michael Hanselmann

1868 d971402f Michael Hanselmann
  """
1869 d971402f Michael Hanselmann
  # compute the max line length for cmd + usage
1870 d971402f Michael Hanselmann
  mlen = min(60, max(map(len, commands)))
1871 d971402f Michael Hanselmann
1872 d971402f Michael Hanselmann
  yield "Usage: %s {command} [options...] [argument...]" % binary
1873 d971402f Michael Hanselmann
  yield "%s <command> --help to see details, or man %s" % (binary, binary)
1874 d971402f Michael Hanselmann
  yield ""
1875 d971402f Michael Hanselmann
  yield "Commands:"
1876 d971402f Michael Hanselmann
1877 d971402f Michael Hanselmann
  # and format a nice command list
1878 d971402f Michael Hanselmann
  for (cmd, (_, _, _, _, help_text)) in sorted(commands.items()):
1879 d971402f Michael Hanselmann
    help_lines = textwrap.wrap(help_text, 79 - 3 - mlen)
1880 d971402f Michael Hanselmann
    yield " %-*s - %s" % (mlen, cmd, help_lines.pop(0))
1881 d971402f Michael Hanselmann
    for line in help_lines:
1882 d971402f Michael Hanselmann
      yield " %-*s   %s" % (mlen, "", line)
1883 d971402f Michael Hanselmann
1884 d971402f Michael Hanselmann
  yield ""
1885 d971402f Michael Hanselmann
1886 d971402f Michael Hanselmann
1887 a8005e17 Michael Hanselmann
def _CheckArguments(cmd, args_def, args):
1888 a8005e17 Michael Hanselmann
  """Verifies the arguments using the argument definition.
1889 a8005e17 Michael Hanselmann

1890 a8005e17 Michael Hanselmann
  Algorithm:
1891 a8005e17 Michael Hanselmann

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

1894 a8005e17 Michael Hanselmann
    1. For each argument in definition
1895 a8005e17 Michael Hanselmann

1896 a8005e17 Michael Hanselmann
      1. Keep running count of minimum number of values (min_count)
1897 a8005e17 Michael Hanselmann
      1. Keep running count of maximum number of values (max_count)
1898 a8005e17 Michael Hanselmann
      1. If it has an unlimited number of values
1899 a8005e17 Michael Hanselmann

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

1902 a8005e17 Michael Hanselmann
    1. If last argument has limited number of values
1903 a8005e17 Michael Hanselmann

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

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

1908 a8005e17 Michael Hanselmann
  """
1909 a8005e17 Michael Hanselmann
  if args and not args_def:
1910 a8005e17 Michael Hanselmann
    ToStderr("Error: Command %s expects no arguments", cmd)
1911 a8005e17 Michael Hanselmann
    return False
1912 a8005e17 Michael Hanselmann
1913 a8005e17 Michael Hanselmann
  min_count = None
1914 a8005e17 Michael Hanselmann
  max_count = None
1915 a8005e17 Michael Hanselmann
  check_max = None
1916 a8005e17 Michael Hanselmann
1917 a8005e17 Michael Hanselmann
  last_idx = len(args_def) - 1
1918 a8005e17 Michael Hanselmann
1919 a8005e17 Michael Hanselmann
  for idx, arg in enumerate(args_def):
1920 a8005e17 Michael Hanselmann
    if min_count is None:
1921 a8005e17 Michael Hanselmann
      min_count = arg.min
1922 a8005e17 Michael Hanselmann
    elif arg.min is not None:
1923 a8005e17 Michael Hanselmann
      min_count += arg.min
1924 a8005e17 Michael Hanselmann
1925 a8005e17 Michael Hanselmann
    if max_count is None:
1926 a8005e17 Michael Hanselmann
      max_count = arg.max
1927 a8005e17 Michael Hanselmann
    elif arg.max is not None:
1928 a8005e17 Michael Hanselmann
      max_count += arg.max
1929 a8005e17 Michael Hanselmann
1930 a8005e17 Michael Hanselmann
    if idx == last_idx:
1931 a8005e17 Michael Hanselmann
      check_max = (arg.max is not None)
1932 a8005e17 Michael Hanselmann
1933 a8005e17 Michael Hanselmann
    elif arg.max is None:
1934 a8005e17 Michael Hanselmann
      raise errors.ProgrammerError("Only the last argument can have max=None")
1935 a8005e17 Michael Hanselmann
1936 a8005e17 Michael Hanselmann
  if check_max:
1937 a8005e17 Michael Hanselmann
    # Command with exact number of arguments
1938 a8005e17 Michael Hanselmann
    if (min_count is not None and max_count is not None and
1939 a8005e17 Michael Hanselmann
        min_count == max_count and len(args) != min_count):
1940 a8005e17 Michael Hanselmann
      ToStderr("Error: Command %s expects %d argument(s)", cmd, min_count)
1941 a8005e17 Michael Hanselmann
      return False
1942 a8005e17 Michael Hanselmann
1943 a8005e17 Michael Hanselmann
    # Command with limited number of arguments
1944 a8005e17 Michael Hanselmann
    if max_count is not None and len(args) > max_count:
1945 a8005e17 Michael Hanselmann
      ToStderr("Error: Command %s expects only %d argument(s)",
1946 a8005e17 Michael Hanselmann
               cmd, max_count)
1947 a8005e17 Michael Hanselmann
      return False
1948 a8005e17 Michael Hanselmann
1949 a8005e17 Michael Hanselmann
  # Command with some required arguments
1950 a8005e17 Michael Hanselmann
  if min_count is not None and len(args) < min_count:
1951 a8005e17 Michael Hanselmann
    ToStderr("Error: Command %s expects at least %d argument(s)",
1952 a8005e17 Michael Hanselmann
             cmd, min_count)
1953 a8005e17 Michael Hanselmann
    return False
1954 a8005e17 Michael Hanselmann
1955 a8005e17 Michael Hanselmann
  return True
1956 a8005e17 Michael Hanselmann
1957 a8005e17 Michael Hanselmann
1958 60d49723 Michael Hanselmann
def SplitNodeOption(value):
1959 60d49723 Michael Hanselmann
  """Splits the value of a --node option.
1960 60d49723 Michael Hanselmann

1961 60d49723 Michael Hanselmann
  """
1962 d0c8c01d Iustin Pop
  if value and ":" in value:
1963 d0c8c01d Iustin Pop
    return value.split(":", 1)
1964 60d49723 Michael Hanselmann
  else:
1965 60d49723 Michael Hanselmann
    return (value, None)
1966 60d49723 Michael Hanselmann
1967 60d49723 Michael Hanselmann
1968 07150497 Guido Trotter
def CalculateOSNames(os_name, os_variants):
1969 07150497 Guido Trotter
  """Calculates all the names an OS can be called, according to its variants.
1970 07150497 Guido Trotter

1971 07150497 Guido Trotter
  @type os_name: string
1972 07150497 Guido Trotter
  @param os_name: base name of the os
1973 07150497 Guido Trotter
  @type os_variants: list or None
1974 07150497 Guido Trotter
  @param os_variants: list of supported variants
1975 07150497 Guido Trotter
  @rtype: list
1976 07150497 Guido Trotter
  @return: list of valid names
1977 07150497 Guido Trotter

1978 07150497 Guido Trotter
  """
1979 07150497 Guido Trotter
  if os_variants:
1980 d0c8c01d Iustin Pop
    return ["%s+%s" % (os_name, v) for v in os_variants]
1981 07150497 Guido Trotter
  else:
1982 07150497 Guido Trotter
    return [os_name]
1983 07150497 Guido Trotter
1984 07150497 Guido Trotter
1985 a4ebd726 Michael Hanselmann
def ParseFields(selected, default):
1986 a4ebd726 Michael Hanselmann
  """Parses the values of "--field"-like options.
1987 a4ebd726 Michael Hanselmann

1988 a4ebd726 Michael Hanselmann
  @type selected: string or None
1989 a4ebd726 Michael Hanselmann
  @param selected: User-selected options
1990 a4ebd726 Michael Hanselmann
  @type default: list
1991 a4ebd726 Michael Hanselmann
  @param default: Default fields
1992 a4ebd726 Michael Hanselmann

1993 a4ebd726 Michael Hanselmann
  """
1994 a4ebd726 Michael Hanselmann
  if selected is None:
1995 a4ebd726 Michael Hanselmann
    return default
1996 a4ebd726 Michael Hanselmann
1997 a4ebd726 Michael Hanselmann
  if selected.startswith("+"):
1998 a4ebd726 Michael Hanselmann
    return default + selected[1:].split(",")
1999 a4ebd726 Michael Hanselmann
2000 a4ebd726 Michael Hanselmann
  return selected.split(",")
2001 a4ebd726 Michael Hanselmann
2002 a4ebd726 Michael Hanselmann
2003 e0e916fe Iustin Pop
UsesRPC = rpc.RunWithRPC
2004 4331f6cd Michael Hanselmann
2005 4331f6cd Michael Hanselmann
2006 47988778 Iustin Pop
def AskUser(text, choices=None):
2007 47988778 Iustin Pop
  """Ask the user a question.
2008 a8083063 Iustin Pop

2009 c41eea6e Iustin Pop
  @param text: the question to ask
2010 a8083063 Iustin Pop

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

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

2020 a8083063 Iustin Pop
  """
2021 47988778 Iustin Pop
  if choices is None:
2022 d0c8c01d Iustin Pop
    choices = [("y", True, "Perform the operation"),
2023 d0c8c01d Iustin Pop
               ("n", False, "Do not perform the operation")]
2024 47988778 Iustin Pop
  if not choices or not isinstance(choices, list):
2025 5bbd3f7f Michael Hanselmann
    raise errors.ProgrammerError("Invalid choices argument to AskUser")
2026 47988778 Iustin Pop
  for entry in choices:
2027 d0c8c01d Iustin Pop
    if not isinstance(entry, tuple) or len(entry) < 3 or entry[0] == "?":
2028 5bbd3f7f Michael Hanselmann
      raise errors.ProgrammerError("Invalid choices element to AskUser")
2029 47988778 Iustin Pop
2030 47988778 Iustin Pop
  answer = choices[-1][1]
2031 47988778 Iustin Pop
  new_text = []
2032 47988778 Iustin Pop
  for line in text.splitlines():
2033 47988778 Iustin Pop
    new_text.append(textwrap.fill(line, 70, replace_whitespace=False))
2034 47988778 Iustin Pop
  text = "\n".join(new_text)
2035 a8083063 Iustin Pop
  try:
2036 3023170f Iustin Pop
    f = file("/dev/tty", "a+")
2037 a8083063 Iustin Pop
  except IOError:
2038 47988778 Iustin Pop
    return answer
2039 a8083063 Iustin Pop
  try:
2040 47988778 Iustin Pop
    chars = [entry[0] for entry in choices]
2041 47988778 Iustin Pop
    chars[-1] = "[%s]" % chars[-1]
2042 d0c8c01d Iustin Pop
    chars.append("?")
2043 47988778 Iustin Pop
    maps = dict([(entry[0], entry[1]) for entry in choices])
2044 47988778 Iustin Pop
    while True:
2045 47988778 Iustin Pop
      f.write(text)
2046 d0c8c01d Iustin Pop
      f.write("\n")
2047 47988778 Iustin Pop
      f.write("/".join(chars))
2048 47988778 Iustin Pop
      f.write(": ")
2049 47988778 Iustin Pop
      line = f.readline(2).strip().lower()
2050 47988778 Iustin Pop
      if line in maps:
2051 47988778 Iustin Pop
        answer = maps[line]
2052 47988778 Iustin Pop
        break
2053 d0c8c01d Iustin Pop
      elif line == "?":
2054 47988778 Iustin Pop
        for entry in choices:
2055 47988778 Iustin Pop
          f.write(" %s - %s\n" % (entry[0], entry[2]))
2056 47988778 Iustin Pop
        f.write("\n")
2057 47988778 Iustin Pop
        continue
2058 a8083063 Iustin Pop
  finally:
2059 a8083063 Iustin Pop
    f.close()
2060 a8083063 Iustin Pop
  return answer
2061 a8083063 Iustin Pop
2062 a8083063 Iustin Pop
2063 e9d741b6 Iustin Pop
class JobSubmittedException(Exception):
2064 e9d741b6 Iustin Pop
  """Job was submitted, client should exit.
2065 e9d741b6 Iustin Pop

2066 e9d741b6 Iustin Pop
  This exception has one argument, the ID of the job that was
2067 e9d741b6 Iustin Pop
  submitted. The handler should print this ID.
2068 e9d741b6 Iustin Pop

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

2071 e9d741b6 Iustin Pop
  """
2072 e9d741b6 Iustin Pop
2073 e9d741b6 Iustin Pop
2074 0a1e74d9 Iustin Pop
def SendJob(ops, cl=None):
2075 0a1e74d9 Iustin Pop
  """Function to submit an opcode without waiting for the results.
2076 a8083063 Iustin Pop

2077 0a1e74d9 Iustin Pop
  @type ops: list
2078 0a1e74d9 Iustin Pop
  @param ops: list of opcodes
2079 0a1e74d9 Iustin Pop
  @type cl: luxi.Client
2080 0a1e74d9 Iustin Pop
  @param cl: the luxi client to use for communicating with the master;
2081 0a1e74d9 Iustin Pop
             if None, a new client will be created
2082 a8083063 Iustin Pop

2083 a8083063 Iustin Pop
  """
2084 e2212007 Iustin Pop
  if cl is None:
2085 b33e986b Iustin Pop
    cl = GetClient()
2086 685ee993 Iustin Pop
2087 0a1e74d9 Iustin Pop
  job_id = cl.SubmitJob(ops)
2088 0a1e74d9 Iustin Pop
2089 0a1e74d9 Iustin Pop
  return job_id
2090 0a1e74d9 Iustin Pop
2091 0a1e74d9 Iustin Pop
2092 4e338533 Michael Hanselmann
def GenericPollJob(job_id, cbs, report_cbs):
2093 4e338533 Michael Hanselmann
  """Generic job-polling function.
2094 0a1e74d9 Iustin Pop

2095 4e338533 Michael Hanselmann
  @type job_id: number
2096 4e338533 Michael Hanselmann
  @param job_id: Job ID
2097 4e338533 Michael Hanselmann
  @type cbs: Instance of L{JobPollCbBase}
2098 4e338533 Michael Hanselmann
  @param cbs: Data callbacks
2099 4e338533 Michael Hanselmann
  @type report_cbs: Instance of L{JobPollReportCbBase}
2100 4e338533 Michael Hanselmann
  @param report_cbs: Reporting callbacks
2101 0a1e74d9 Iustin Pop

2102 0a1e74d9 Iustin Pop
  """
2103 6c5a7090 Michael Hanselmann
  prev_job_info = None
2104 6c5a7090 Michael Hanselmann
  prev_logmsg_serial = None
2105 6c5a7090 Michael Hanselmann
2106 f4484122 Michael Hanselmann
  status = None
2107 f4484122 Michael Hanselmann
2108 685ee993 Iustin Pop
  while True:
2109 4e338533 Michael Hanselmann
    result = cbs.WaitForJobChangeOnce(job_id, ["status"], prev_job_info,
2110 4e338533 Michael Hanselmann
                                      prev_logmsg_serial)
2111 6c5a7090 Michael Hanselmann
    if not result:
2112 685ee993 Iustin Pop
      # job not found, go away!
2113 0bbe448c Michael Hanselmann
      raise errors.JobLost("Job with id %s lost" % job_id)
2114 4e338533 Michael Hanselmann
2115 4e338533 Michael Hanselmann
    if result == constants.JOB_NOTCHANGED:
2116 4e338533 Michael Hanselmann
      report_cbs.ReportNotChanged(job_id, status)
2117 f4484122 Michael Hanselmann
2118 f4484122 Michael Hanselmann
      # Wait again
2119 f4484122 Michael Hanselmann
      continue
2120 685ee993 Iustin Pop
2121 6c5a7090 Michael Hanselmann
    # Split result, a tuple of (field values, log entries)
2122 6c5a7090 Michael Hanselmann
    (job_info, log_entries) = result
2123 6c5a7090 Michael Hanselmann
    (status, ) = job_info
2124 6c5a7090 Michael Hanselmann
2125 6c5a7090 Michael Hanselmann
    if log_entries:
2126 6c5a7090 Michael Hanselmann
      for log_entry in log_entries:
2127 4e338533 Michael Hanselmann
        (serial, timestamp, log_type, message) = log_entry
2128 4e338533 Michael Hanselmann
        report_cbs.ReportLogMessage(job_id, serial, timestamp,
2129 4e338533 Michael Hanselmann
                                    log_type, message)
2130 6c5a7090 Michael Hanselmann
        prev_logmsg_serial = max(prev_logmsg_serial, serial)
2131 6c5a7090 Michael Hanselmann
2132 0bbe448c Michael Hanselmann
    # TODO: Handle canceled and archived jobs
2133 fbf0262f Michael Hanselmann
    elif status in (constants.JOB_STATUS_SUCCESS,
2134 fbf0262f Michael Hanselmann
                    constants.JOB_STATUS_ERROR,
2135 fbf0262f Michael Hanselmann
                    constants.JOB_STATUS_CANCELING,
2136 fbf0262f Michael Hanselmann
                    constants.JOB_STATUS_CANCELED):
2137 685ee993 Iustin Pop
      break
2138 6c5a7090 Michael Hanselmann
2139 6c5a7090 Michael Hanselmann
    prev_job_info = job_info
2140 685ee993 Iustin Pop
2141 4e338533 Michael Hanselmann
  jobs = cbs.QueryJobs([job_id], ["status", "opstatus", "opresult"])
2142 0bbe448c Michael Hanselmann
  if not jobs:
2143 0bbe448c Michael Hanselmann
    raise errors.JobLost("Job with id %s lost" % job_id)
2144 685ee993 Iustin Pop
2145 0e050889 Iustin Pop
  status, opstatus, result = jobs[0]
2146 4e338533 Michael Hanselmann
2147 0bbe448c Michael Hanselmann
  if status == constants.JOB_STATUS_SUCCESS:
2148 53c04d04 Iustin Pop
    return result
2149 4e338533 Michael Hanselmann
2150 4e338533 Michael Hanselmann
  if status in (constants.JOB_STATUS_CANCELING, constants.JOB_STATUS_CANCELED):
2151 fbf0262f Michael Hanselmann
    raise errors.OpExecError("Job was canceled")
2152 4e338533 Michael Hanselmann
2153 4e338533 Michael Hanselmann
  has_ok = False
2154 4e338533 Michael Hanselmann
  for idx, (status, msg) in enumerate(zip(opstatus, result)):
2155 4e338533 Michael Hanselmann
    if status == constants.OP_STATUS_SUCCESS:
2156 4e338533 Michael Hanselmann
      has_ok = True
2157 4e338533 Michael Hanselmann
    elif status == constants.OP_STATUS_ERROR:
2158 4e338533 Michael Hanselmann
      errors.MaybeRaise(msg)
2159 4e338533 Michael Hanselmann
2160 4e338533 Michael Hanselmann
      if has_ok:
2161 4e338533 Michael Hanselmann
        raise errors.OpExecError("partial failure (opcode %d): %s" %
2162 4e338533 Michael Hanselmann
                                 (idx, msg))
2163 4e338533 Michael Hanselmann
2164 4e338533 Michael Hanselmann
      raise errors.OpExecError(str(msg))
2165 4e338533 Michael Hanselmann
2166 4e338533 Michael Hanselmann
  # default failure mode
2167 4e338533 Michael Hanselmann
  raise errors.OpExecError(result)
2168 4e338533 Michael Hanselmann
2169 4e338533 Michael Hanselmann
2170 4e338533 Michael Hanselmann
class JobPollCbBase:
2171 4e338533 Michael Hanselmann
  """Base class for L{GenericPollJob} callbacks.
2172 4e338533 Michael Hanselmann

2173 4e338533 Michael Hanselmann
  """
2174 4e338533 Michael Hanselmann
  def __init__(self):
2175 4e338533 Michael Hanselmann
    """Initializes this class.
2176 4e338533 Michael Hanselmann

2177 4e338533 Michael Hanselmann
    """
2178 4e338533 Michael Hanselmann
2179 4e338533 Michael Hanselmann
  def WaitForJobChangeOnce(self, job_id, fields,
2180 4e338533 Michael Hanselmann
                           prev_job_info, prev_log_serial):
2181 4e338533 Michael Hanselmann
    """Waits for changes on a job.
2182 4e338533 Michael Hanselmann

2183 4e338533 Michael Hanselmann
    """
2184 4e338533 Michael Hanselmann
    raise NotImplementedError()
2185 4e338533 Michael Hanselmann
2186 4e338533 Michael Hanselmann
  def QueryJobs(self, job_ids, fields):
2187 4e338533 Michael Hanselmann
    """Returns the selected fields for the selected job IDs.
2188 4e338533 Michael Hanselmann

2189 4e338533 Michael Hanselmann
    @type job_ids: list of numbers
2190 4e338533 Michael Hanselmann
    @param job_ids: Job IDs
2191 4e338533 Michael Hanselmann
    @type fields: list of strings
2192 4e338533 Michael Hanselmann
    @param fields: Fields
2193 4e338533 Michael Hanselmann

2194 4e338533 Michael Hanselmann
    """
2195 4e338533 Michael Hanselmann
    raise NotImplementedError()
2196 4e338533 Michael Hanselmann
2197 4e338533 Michael Hanselmann
2198 4e338533 Michael Hanselmann
class JobPollReportCbBase:
2199 4e338533 Michael Hanselmann
  """Base class for L{GenericPollJob} reporting callbacks.
2200 4e338533 Michael Hanselmann

2201 4e338533 Michael Hanselmann
  """
2202 4e338533 Michael Hanselmann
  def __init__(self):
2203 4e338533 Michael Hanselmann
    """Initializes this class.
2204 4e338533 Michael Hanselmann

2205 4e338533 Michael Hanselmann
    """
2206 4e338533 Michael Hanselmann
2207 4e338533 Michael Hanselmann
  def ReportLogMessage(self, job_id, serial, timestamp, log_type, log_msg):
2208 4e338533 Michael Hanselmann
    """Handles a log message.
2209 4e338533 Michael Hanselmann

2210 4e338533 Michael Hanselmann
    """
2211 4e338533 Michael Hanselmann
    raise NotImplementedError()
2212 4e338533 Michael Hanselmann
2213 4e338533 Michael Hanselmann
  def ReportNotChanged(self, job_id, status):
2214 4e338533 Michael Hanselmann
    """Called for if a job hasn't changed in a while.
2215 4e338533 Michael Hanselmann

2216 4e338533 Michael Hanselmann
    @type job_id: number
2217 4e338533 Michael Hanselmann
    @param job_id: Job ID
2218 4e338533 Michael Hanselmann
    @type status: string or None
2219 4e338533 Michael Hanselmann
    @param status: Job status if available
2220 4e338533 Michael Hanselmann

2221 4e338533 Michael Hanselmann
    """
2222 4e338533 Michael Hanselmann
    raise NotImplementedError()
2223 4e338533 Michael Hanselmann
2224 4e338533 Michael Hanselmann
2225 4e338533 Michael Hanselmann
class _LuxiJobPollCb(JobPollCbBase):
2226 4e338533 Michael Hanselmann
  def __init__(self, cl):
2227 4e338533 Michael Hanselmann
    """Initializes this class.
2228 4e338533 Michael Hanselmann

2229 4e338533 Michael Hanselmann
    """
2230 4e338533 Michael Hanselmann
    JobPollCbBase.__init__(self)
2231 4e338533 Michael Hanselmann
    self.cl = cl
2232 4e338533 Michael Hanselmann
2233 4e338533 Michael Hanselmann
  def WaitForJobChangeOnce(self, job_id, fields,
2234 4e338533 Michael Hanselmann
                           prev_job_info, prev_log_serial):
2235 4e338533 Michael Hanselmann
    """Waits for changes on a job.
2236 4e338533 Michael Hanselmann

2237 4e338533 Michael Hanselmann
    """
2238 4e338533 Michael Hanselmann
    return self.cl.WaitForJobChangeOnce(job_id, fields,
2239 4e338533 Michael Hanselmann
                                        prev_job_info, prev_log_serial)
2240 4e338533 Michael Hanselmann
2241 4e338533 Michael Hanselmann
  def QueryJobs(self, job_ids, fields):
2242 4e338533 Michael Hanselmann
    """Returns the selected fields for the selected job IDs.
2243 4e338533 Michael Hanselmann

2244 4e338533 Michael Hanselmann
    """
2245 4e338533 Michael Hanselmann
    return self.cl.QueryJobs(job_ids, fields)
2246 4e338533 Michael Hanselmann
2247 4e338533 Michael Hanselmann
2248 4e338533 Michael Hanselmann
class FeedbackFnJobPollReportCb(JobPollReportCbBase):
2249 4e338533 Michael Hanselmann
  def __init__(self, feedback_fn):
2250 4e338533 Michael Hanselmann
    """Initializes this class.
2251 4e338533 Michael Hanselmann

2252 4e338533 Michael Hanselmann
    """
2253 4e338533 Michael Hanselmann
    JobPollReportCbBase.__init__(self)
2254 4e338533 Michael Hanselmann
2255 4e338533 Michael Hanselmann
    self.feedback_fn = feedback_fn
2256 4e338533 Michael Hanselmann
2257 4e338533 Michael Hanselmann
    assert callable(feedback_fn)
2258 4e338533 Michael Hanselmann
2259 4e338533 Michael Hanselmann
  def ReportLogMessage(self, job_id, serial, timestamp, log_type, log_msg):
2260 4e338533 Michael Hanselmann
    """Handles a log message.
2261 4e338533 Michael Hanselmann

2262 4e338533 Michael Hanselmann
    """
2263 4e338533 Michael Hanselmann
    self.feedback_fn((timestamp, log_type, log_msg))
2264 4e338533 Michael Hanselmann
2265 4e338533 Michael Hanselmann
  def ReportNotChanged(self, job_id, status):
2266 4e338533 Michael Hanselmann
    """Called if a job hasn't changed in a while.
2267 4e338533 Michael Hanselmann

2268 4e338533 Michael Hanselmann
    """
2269 4e338533 Michael Hanselmann
    # Ignore
2270 4e338533 Michael Hanselmann
2271 4e338533 Michael Hanselmann
2272 4e338533 Michael Hanselmann
class StdioJobPollReportCb(JobPollReportCbBase):
2273 4e338533 Michael Hanselmann
  def __init__(self):
2274 4e338533 Michael Hanselmann
    """Initializes this class.
2275 4e338533 Michael Hanselmann

2276 4e338533 Michael Hanselmann
    """
2277 4e338533 Michael Hanselmann
    JobPollReportCbBase.__init__(self)
2278 4e338533 Michael Hanselmann
2279 4e338533 Michael Hanselmann
    self.notified_queued = False
2280 4e338533 Michael Hanselmann
    self.notified_waitlock = False
2281 4e338533 Michael Hanselmann
2282 4e338533 Michael Hanselmann
  def ReportLogMessage(self, job_id, serial, timestamp, log_type, log_msg):
2283 4e338533 Michael Hanselmann
    """Handles a log message.
2284 4e338533 Michael Hanselmann

2285 4e338533 Michael Hanselmann
    """
2286 4e338533 Michael Hanselmann
    ToStdout("%s %s", time.ctime(utils.MergeTime(timestamp)),
2287 8a7f1c61 Michael Hanselmann
             FormatLogMessage(log_type, log_msg))
2288 4e338533 Michael Hanselmann
2289 4e338533 Michael Hanselmann
  def ReportNotChanged(self, job_id, status):
2290 4e338533 Michael Hanselmann
    """Called if a job hasn't changed in a while.
2291 4e338533 Michael Hanselmann

2292 4e338533 Michael Hanselmann
    """
2293 4e338533 Michael Hanselmann
    if status is None:
2294 4e338533 Michael Hanselmann
      return
2295 4e338533 Michael Hanselmann
2296 4e338533 Michael Hanselmann
    if status == constants.JOB_STATUS_QUEUED and not self.notified_queued:
2297 4e338533 Michael Hanselmann
      ToStderr("Job %s is waiting in queue", job_id)
2298 4e338533 Michael Hanselmann
      self.notified_queued = True
2299 4e338533 Michael Hanselmann
2300 47099cd1 Michael Hanselmann
    elif status == constants.JOB_STATUS_WAITING and not self.notified_waitlock:
2301 4e338533 Michael Hanselmann
      ToStderr("Job %s is trying to acquire all necessary locks", job_id)
2302 4e338533 Michael Hanselmann
      self.notified_waitlock = True
2303 4e338533 Michael Hanselmann
2304 4e338533 Michael Hanselmann
2305 8a7f1c61 Michael Hanselmann
def FormatLogMessage(log_type, log_msg):
2306 8a7f1c61 Michael Hanselmann
  """Formats a job message according to its type.
2307 8a7f1c61 Michael Hanselmann

2308 8a7f1c61 Michael Hanselmann
  """
2309 8a7f1c61 Michael Hanselmann
  if log_type != constants.ELOG_MESSAGE:
2310 8a7f1c61 Michael Hanselmann
    log_msg = str(log_msg)
2311 8a7f1c61 Michael Hanselmann
2312 8a7f1c61 Michael Hanselmann
  return utils.SafeEncode(log_msg)
2313 8a7f1c61 Michael Hanselmann
2314 8a7f1c61 Michael Hanselmann
2315 583163a6 Michael Hanselmann
def PollJob(job_id, cl=None, feedback_fn=None, reporter=None):
2316 4e338533 Michael Hanselmann
  """Function to poll for the result of a job.
2317 4e338533 Michael Hanselmann

2318 4e338533 Michael Hanselmann
  @type job_id: job identified
2319 4e338533 Michael Hanselmann
  @param job_id: the job to poll for results
2320 4e338533 Michael Hanselmann
  @type cl: luxi.Client
2321 4e338533 Michael Hanselmann
  @param cl: the luxi client to use for communicating with the master;
2322 4e338533 Michael Hanselmann
             if None, a new client will be created
2323 4e338533 Michael Hanselmann

2324 4e338533 Michael Hanselmann
  """
2325 4e338533 Michael Hanselmann
  if cl is None:
2326 4e338533 Michael Hanselmann
    cl = GetClient()
2327 4e338533 Michael Hanselmann
2328 583163a6 Michael Hanselmann
  if reporter is None:
2329 583163a6 Michael Hanselmann
    if feedback_fn:
2330 583163a6 Michael Hanselmann
      reporter = FeedbackFnJobPollReportCb(feedback_fn)
2331 583163a6 Michael Hanselmann
    else:
2332 583163a6 Michael Hanselmann
      reporter = StdioJobPollReportCb()
2333 583163a6 Michael Hanselmann
  elif feedback_fn:
2334 583163a6 Michael Hanselmann
    raise errors.ProgrammerError("Can't specify reporter and feedback function")
2335 4e338533 Michael Hanselmann
2336 4e338533 Michael Hanselmann
  return GenericPollJob(job_id, _LuxiJobPollCb(cl), reporter)
2337 ceab32dd Iustin Pop
2338 ceab32dd Iustin Pop
2339 583163a6 Michael Hanselmann
def SubmitOpCode(op, cl=None, feedback_fn=None, opts=None, reporter=None):
2340 0a1e74d9 Iustin Pop
  """Legacy function to submit an opcode.
2341 0a1e74d9 Iustin Pop

2342 0a1e74d9 Iustin Pop
  This is just a simple wrapper over the construction of the processor
2343 0a1e74d9 Iustin Pop
  instance. It should be extended to better handle feedback and
2344 0a1e74d9 Iustin Pop
  interaction functions.
2345 0a1e74d9 Iustin Pop

2346 0a1e74d9 Iustin Pop
  """
2347 0a1e74d9 Iustin Pop
  if cl is None:
2348 0a1e74d9 Iustin Pop
    cl = GetClient()
2349 0a1e74d9 Iustin Pop
2350 293ba2d8 Iustin Pop
  SetGenericOpcodeOpts([op], opts)
2351 293ba2d8 Iustin Pop
2352 5d297d8a Michael Hanselmann
  job_id = SendJob([op], cl=cl)
2353 fe5a2780 Klaus Aehlig
  if hasattr(opts, "print_jobid") and opts.print_jobid:
2354 d6cd74dd Klaus Aehlig
    ToStdout("%d" % job_id)
2355 0a1e74d9 Iustin Pop
2356 583163a6 Michael Hanselmann
  op_results = PollJob(job_id, cl=cl, feedback_fn=feedback_fn,
2357 583163a6 Michael Hanselmann
                       reporter=reporter)
2358 53c04d04 Iustin Pop
2359 53c04d04 Iustin Pop
  return op_results[0]
2360 0a1e74d9 Iustin Pop
2361 0a1e74d9 Iustin Pop
2362 346c3037 Klaus Aehlig
def SubmitOpCodeToDrainedQueue(op):
2363 346c3037 Klaus Aehlig
  """Forcefully insert a job in the queue, even if it is drained.
2364 346c3037 Klaus Aehlig

2365 346c3037 Klaus Aehlig
  """
2366 346c3037 Klaus Aehlig
  cl = GetClient()
2367 346c3037 Klaus Aehlig
  job_id = cl.SubmitJobToDrainedQueue([op])
2368 346c3037 Klaus Aehlig
  op_results = PollJob(job_id, cl=cl)
2369 346c3037 Klaus Aehlig
  return op_results[0]
2370 346c3037 Klaus Aehlig
2371 346c3037 Klaus Aehlig
2372 94428652 Iustin Pop
def SubmitOrSend(op, opts, cl=None, feedback_fn=None):
2373 94428652 Iustin Pop
  """Wrapper around SubmitOpCode or SendJob.
2374 94428652 Iustin Pop

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

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

2383 94428652 Iustin Pop
  """
2384 94428652 Iustin Pop
  if opts and opts.submit_only:
2385 293ba2d8 Iustin Pop
    job = [op]
2386 293ba2d8 Iustin Pop
    SetGenericOpcodeOpts(job, opts)
2387 293ba2d8 Iustin Pop
    job_id = SendJob(job, cl=cl)
2388 d6cd74dd Klaus Aehlig
    if opts.print_jobid:
2389 d6cd74dd Klaus Aehlig
      ToStdout("%d" % job_id)
2390 e9d741b6 Iustin Pop
    raise JobSubmittedException(job_id)
2391 94428652 Iustin Pop
  else:
2392 293ba2d8 Iustin Pop
    return SubmitOpCode(op, cl=cl, feedback_fn=feedback_fn, opts=opts)
2393 293ba2d8 Iustin Pop
2394 293ba2d8 Iustin Pop
2395 276e51bd Michele Tartara
def _InitReasonTrail(op, opts):
2396 276e51bd Michele Tartara
  """Builds the first part of the reason trail
2397 276e51bd Michele Tartara

2398 276e51bd Michele Tartara
  Builds the initial part of the reason trail, adding the user provided reason
2399 276e51bd Michele Tartara
  (if it exists) and the name of the command starting the operation.
2400 276e51bd Michele Tartara

2401 276e51bd Michele Tartara
  @param op: the opcode the reason trail will be added to
2402 276e51bd Michele Tartara
  @param opts: the command line options selected by the user
2403 276e51bd Michele Tartara

2404 276e51bd Michele Tartara
  """
2405 276e51bd Michele Tartara
  assert len(sys.argv) >= 2
2406 276e51bd Michele Tartara
  trail = []
2407 276e51bd Michele Tartara
2408 276e51bd Michele Tartara
  if opts.reason:
2409 276e51bd Michele Tartara
    trail.append((constants.OPCODE_REASON_SRC_USER,
2410 276e51bd Michele Tartara
                  opts.reason,
2411 276e51bd Michele Tartara
                  utils.EpochNano()))
2412 276e51bd Michele Tartara
2413 276e51bd Michele Tartara
  binary = os.path.basename(sys.argv[0])
2414 276e51bd Michele Tartara
  source = "%s:%s" % (constants.OPCODE_REASON_SRC_CLIENT, binary)
2415 276e51bd Michele Tartara
  command = sys.argv[1]
2416 276e51bd Michele Tartara
  trail.append((source, command, utils.EpochNano()))
2417 276e51bd Michele Tartara
  op.reason = trail
2418 276e51bd Michele Tartara
2419 276e51bd Michele Tartara
2420 293ba2d8 Iustin Pop
def SetGenericOpcodeOpts(opcode_list, options):
2421 293ba2d8 Iustin Pop
  """Processor for generic options.
2422 293ba2d8 Iustin Pop

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

2426 293ba2d8 Iustin Pop
  @param opcode_list: list of opcodes
2427 293ba2d8 Iustin Pop
  @param options: command line options or None
2428 293ba2d8 Iustin Pop
  @return: None (in-place modification)
2429 293ba2d8 Iustin Pop

2430 293ba2d8 Iustin Pop
  """
2431 293ba2d8 Iustin Pop
  if not options:
2432 293ba2d8 Iustin Pop
    return
2433 293ba2d8 Iustin Pop
  for op in opcode_list:
2434 aa06f8c6 Michael Hanselmann
    op.debug_level = options.debug
2435 a0a6ff34 Iustin Pop
    if hasattr(options, "dry_run"):
2436 a0a6ff34 Iustin Pop
      op.dry_run = options.dry_run
2437 aa06f8c6 Michael Hanselmann
    if getattr(options, "priority", None) is not None:
2438 552328b8 Michael Hanselmann
      op.priority = options.priority
2439 276e51bd Michele Tartara
    _InitReasonTrail(op, options)
2440 94428652 Iustin Pop
2441 94428652 Iustin Pop
2442 73702ee7 Iustin Pop
def FormatError(err):
2443 73702ee7 Iustin Pop
  """Return a formatted error message for a given error.
2444 73702ee7 Iustin Pop

2445 73702ee7 Iustin Pop
  This function takes an exception instance and returns a tuple
2446 73702ee7 Iustin Pop
  consisting of two values: first, the recommended exit code, and
2447 73702ee7 Iustin Pop
  second, a string describing the error message (not
2448 73702ee7 Iustin Pop
  newline-terminated).
2449 73702ee7 Iustin Pop

2450 73702ee7 Iustin Pop
  """
2451 73702ee7 Iustin Pop
  retcode = 1
2452 73702ee7 Iustin Pop
  obuf = StringIO()
2453 e2e521d0 Iustin Pop
  msg = str(err)
2454 73702ee7 Iustin Pop
  if isinstance(err, errors.ConfigurationError):
2455 e2e521d0 Iustin Pop
    txt = "Corrupt configuration file: %s" % msg
2456 46fbdd04 Iustin Pop
    logging.error(txt)
2457 e2e521d0 Iustin Pop
    obuf.write(txt + "\n")
2458 73702ee7 Iustin Pop
    obuf.write("Aborting.")
2459 73702ee7 Iustin Pop
    retcode = 2
2460 73702ee7 Iustin Pop
  elif isinstance(err, errors.HooksAbort):
2461 73702ee7 Iustin Pop
    obuf.write("Failure: hooks execution failed:\n")
2462 73702ee7 Iustin Pop
    for node, script, out in err.args[0]:
2463 73702ee7 Iustin Pop
      if out:
2464 73702ee7 Iustin Pop
        obuf.write("  node: %s, script: %s, output: %s\n" %
2465 73702ee7 Iustin Pop
                   (node, script, out))
2466 73702ee7 Iustin Pop
      else:
2467 73702ee7 Iustin Pop
        obuf.write("  node: %s, script: %s (no output)\n" %
2468 73702ee7 Iustin Pop
                   (node, script))
2469 73702ee7 Iustin Pop
  elif isinstance(err, errors.HooksFailure):
2470 e2e521d0 Iustin Pop
    obuf.write("Failure: hooks general failure: %s" % msg)
2471 73702ee7 Iustin Pop
  elif isinstance(err, errors.ResolverError):
2472 b705c7a6 Manuel Franceschini
    this_host = netutils.Hostname.GetSysName()
2473 73702ee7 Iustin Pop
    if err.args[0] == this_host:
2474 73702ee7 Iustin Pop
      msg = "Failure: can't resolve my own hostname ('%s')"
2475 73702ee7 Iustin Pop
    else:
2476 73702ee7 Iustin Pop
      msg = "Failure: can't resolve hostname '%s'"
2477 73702ee7 Iustin Pop
    obuf.write(msg % err.args[0])
2478 73702ee7 Iustin Pop
  elif isinstance(err, errors.OpPrereqError):
2479 5c983ee5 Iustin Pop
    if len(err.args) == 2:
2480 5c983ee5 Iustin Pop
      obuf.write("Failure: prerequisites not met for this"
2481 5ae4945a Iustin Pop
                 " operation:\nerror type: %s, error details:\n%s" %
2482 5c983ee5 Iustin Pop
                 (err.args[1], err.args[0]))
2483 5c983ee5 Iustin Pop
    else:
2484 5c983ee5 Iustin Pop
      obuf.write("Failure: prerequisites not met for this"
2485 5c983ee5 Iustin Pop
                 " operation:\n%s" % msg)
2486 73702ee7 Iustin Pop
  elif isinstance(err, errors.OpExecError):
2487 e2e521d0 Iustin Pop
    obuf.write("Failure: command execution error:\n%s" % msg)
2488 73702ee7 Iustin Pop
  elif isinstance(err, errors.TagError):
2489 e2e521d0 Iustin Pop
    obuf.write("Failure: invalid tag(s) given:\n%s" % msg)
2490 686d7433 Iustin Pop
  elif isinstance(err, errors.JobQueueDrainError):
2491 686d7433 Iustin Pop
    obuf.write("Failure: the job queue is marked for drain and doesn't"
2492 686d7433 Iustin Pop
               " accept new requests\n")
2493 f87b405e Michael Hanselmann
  elif isinstance(err, errors.JobQueueFull):
2494 f87b405e Michael Hanselmann
    obuf.write("Failure: the job queue is full and doesn't accept new"
2495 f87b405e Michael Hanselmann
               " job submissions until old jobs are archived\n")
2496 a5728081 Guido Trotter
  elif isinstance(err, errors.TypeEnforcementError):
2497 a5728081 Guido Trotter
    obuf.write("Parameter Error: %s" % msg)
2498 c1ce76bb Iustin Pop
  elif isinstance(err, errors.ParameterError):
2499 c1ce76bb Iustin Pop
    obuf.write("Failure: unknown/wrong parameter name '%s'" % msg)
2500 9ba38706 Petr Pudlak
  elif isinstance(err, rpcerr.NoMasterError):
2501 7f5edc60 Iustin Pop
    if err.args[0] == pathutils.MASTER_SOCKET:
2502 055d6ac0 Iustin Pop
      daemon = "the master daemon"
2503 055d6ac0 Iustin Pop
    elif err.args[0] == pathutils.QUERY_SOCKET:
2504 055d6ac0 Iustin Pop
      daemon = "the config daemon"
2505 7f5edc60 Iustin Pop
    else:
2506 055d6ac0 Iustin Pop
      daemon = "socket '%s'" % str(err.args[0])
2507 055d6ac0 Iustin Pop
    obuf.write("Cannot communicate with %s.\nIs the process running"
2508 7f5edc60 Iustin Pop
               " and listening for connections?" % daemon)
2509 9ba38706 Petr Pudlak
  elif isinstance(err, rpcerr.TimeoutError):
2510 cd4c86a8 Michael Hanselmann
    obuf.write("Timeout while talking to the master daemon. Jobs might have"
2511 cd4c86a8 Michael Hanselmann
               " been submitted and will continue to run even if the call"
2512 cd4c86a8 Michael Hanselmann
               " timed out. Useful commands in this situation are \"gnt-job"
2513 cd4c86a8 Michael Hanselmann
               " list\", \"gnt-job cancel\" and \"gnt-job watch\". Error:\n")
2514 cd4c86a8 Michael Hanselmann
    obuf.write(msg)
2515 9ba38706 Petr Pudlak
  elif isinstance(err, rpcerr.PermissionError):
2516 5a1c22fe Iustin Pop
    obuf.write("It seems you don't have permissions to connect to the"
2517 5a1c22fe Iustin Pop
               " master daemon.\nPlease retry as a different user.")
2518 9ba38706 Petr Pudlak
  elif isinstance(err, rpcerr.ProtocolError):
2519 03a8dbdc Iustin Pop
    obuf.write("Unhandled protocol error while talking to the master daemon:\n"
2520 03a8dbdc Iustin Pop
               "%s" % msg)
2521 91c622a8 Iustin Pop
  elif isinstance(err, errors.JobLost):
2522 91c622a8 Iustin Pop
    obuf.write("Error checking job status: %s" % msg)
2523 cb1e6c3c Michael Hanselmann
  elif isinstance(err, errors.QueryFilterParseError):
2524 cb1e6c3c Michael Hanselmann
    obuf.write("Error while parsing query filter: %s\n" % err.args[0])
2525 cb1e6c3c Michael Hanselmann
    obuf.write("\n".join(err.GetDetails()))
2526 797506fc Michael Hanselmann
  elif isinstance(err, errors.GenericError):
2527 797506fc Michael Hanselmann
    obuf.write("Unhandled Ganeti error: %s" % msg)
2528 e9d741b6 Iustin Pop
  elif isinstance(err, JobSubmittedException):
2529 e9d741b6 Iustin Pop
    obuf.write("JobID: %s\n" % err.args[0])
2530 e9d741b6 Iustin Pop
    retcode = 0
2531 73702ee7 Iustin Pop
  else:
2532 e2e521d0 Iustin Pop
    obuf.write("Unhandled exception: %s" % msg)
2533 d0c8c01d Iustin Pop
  return retcode, obuf.getvalue().rstrip("\n")
2534 73702ee7 Iustin Pop
2535 73702ee7 Iustin Pop
2536 ef9fa5b9 René Nussbaumer
def GenericMain(commands, override=None, aliases=None,
2537 ef9fa5b9 René Nussbaumer
                env_override=frozenset()):
2538 a8083063 Iustin Pop
  """Generic main function for all the gnt-* commands.
2539 a8083063 Iustin Pop

2540 ef9fa5b9 René Nussbaumer
  @param commands: a dictionary with a special structure, see the design doc
2541 ef9fa5b9 René Nussbaumer
                   for command line handling.
2542 ef9fa5b9 René Nussbaumer
  @param override: if not None, we expect a dictionary with keys that will
2543 ef9fa5b9 René Nussbaumer
                   override command line options; this can be used to pass
2544 ef9fa5b9 René Nussbaumer
                   options from the scripts to generic functions
2545 ef9fa5b9 René Nussbaumer
  @param aliases: dictionary with command aliases {'alias': 'target, ...}
2546 ef9fa5b9 René Nussbaumer
  @param env_override: list of environment names which are allowed to submit
2547 ef9fa5b9 René Nussbaumer
                       default args for commands
2548 a8083063 Iustin Pop

2549 a8083063 Iustin Pop
  """
2550 a8083063 Iustin Pop
  # save the program name and the entire command line for later logging
2551 a8083063 Iustin Pop
  if sys.argv:
2552 c1f19851 Michael Hanselmann
    binary = os.path.basename(sys.argv[0])
2553 c1f19851 Michael Hanselmann
    if not binary:
2554 c1f19851 Michael Hanselmann
      binary = sys.argv[0]
2555 c1f19851 Michael Hanselmann
2556 a8083063 Iustin Pop
    if len(sys.argv) >= 2:
2557 c1f19851 Michael Hanselmann
      logname = utils.ShellQuoteArgs([binary, sys.argv[1]])
2558 a8083063 Iustin Pop
    else:
2559 c1f19851 Michael Hanselmann
      logname = binary
2560 c1f19851 Michael Hanselmann
2561 c1f19851 Michael Hanselmann
    cmdline = utils.ShellQuoteArgs([binary] + sys.argv[1:])
2562 a8083063 Iustin Pop
  else:
2563 a8083063 Iustin Pop
    binary = "<unknown program>"
2564 c1f19851 Michael Hanselmann
    cmdline = "<unknown>"
2565 a8083063 Iustin Pop
2566 de47cf8f Guido Trotter
  if aliases is None:
2567 de47cf8f Guido Trotter
    aliases = {}
2568 de47cf8f Guido Trotter
2569 3126878d Guido Trotter
  try:
2570 d971402f Michael Hanselmann
    (func, options, args) = _ParseArgs(binary, sys.argv, commands, aliases,
2571 d971402f Michael Hanselmann
                                       env_override)
2572 d971402f Michael Hanselmann
  except _ShowVersion:
2573 d971402f Michael Hanselmann
    ToStdout("%s (ganeti %s) %s", binary, constants.VCS_VERSION,
2574 d971402f Michael Hanselmann
             constants.RELEASE_VERSION)
2575 d971402f Michael Hanselmann
    return constants.EXIT_SUCCESS
2576 d971402f Michael Hanselmann
  except _ShowUsage, err:
2577 d971402f Michael Hanselmann
    for line in _FormatUsage(binary, commands):
2578 d971402f Michael Hanselmann
      ToStdout(line)
2579 d971402f Michael Hanselmann
2580 d971402f Michael Hanselmann
    if err.exit_error:
2581 d971402f Michael Hanselmann
      return constants.EXIT_FAILURE
2582 d971402f Michael Hanselmann
    else:
2583 d971402f Michael Hanselmann
      return constants.EXIT_SUCCESS
2584 3126878d Guido Trotter
  except errors.ParameterError, err:
2585 3126878d Guido Trotter
    result, err_msg = FormatError(err)
2586 3126878d Guido Trotter
    ToStderr(err_msg)
2587 3126878d Guido Trotter
    return 1
2588 3126878d Guido Trotter
2589 a8083063 Iustin Pop
  if func is None: # parse error
2590 a8083063 Iustin Pop
    return 1
2591 a8083063 Iustin Pop
2592 334d1483 Iustin Pop
  if override is not None:
2593 334d1483 Iustin Pop
    for key, val in override.iteritems():
2594 334d1483 Iustin Pop
      setattr(options, key, val)
2595 334d1483 Iustin Pop
2596 ee4a14c0 Michael Hanselmann
  utils.SetupLogging(pathutils.LOG_COMMANDS, logname, debug=options.debug,
2597 cfcc79c6 Michael Hanselmann
                     stderr_logging=True)
2598 a8083063 Iustin Pop
2599 3062d395 Santi Raffa
  logging.debug("Command line: %s", cmdline)
2600 a8083063 Iustin Pop
2601 a8083063 Iustin Pop
  try:
2602 a4af651e Iustin Pop
    result = func(options, args)
2603 9ba38706 Petr Pudlak
  except (errors.GenericError, rpcerr.ProtocolError,
2604 d8353c3a Iustin Pop
          JobSubmittedException), err:
2605 a4af651e Iustin Pop
    result, err_msg = FormatError(err)
2606 5bbd3f7f Michael Hanselmann
    logging.exception("Error during command processing")
2607 46fbdd04 Iustin Pop
    ToStderr(err_msg)
2608 8a53b55f Iustin Pop
  except KeyboardInterrupt:
2609 8a53b55f Iustin Pop
    result = constants.EXIT_FAILURE
2610 8a53b55f Iustin Pop
    ToStderr("Aborted. Note that if the operation created any jobs, they"
2611 8a53b55f Iustin Pop
             " might have been submitted and"
2612 8a53b55f Iustin Pop
             " will continue to run in the background.")
2613 225e2544 Iustin Pop
  except IOError, err:
2614 225e2544 Iustin Pop
    if err.errno == errno.EPIPE:
2615 225e2544 Iustin Pop
      # our terminal went away, we'll exit
2616 225e2544 Iustin Pop
      sys.exit(constants.EXIT_FAILURE)
2617 225e2544 Iustin Pop
    else:
2618 225e2544 Iustin Pop
      raise
2619 a8083063 Iustin Pop
2620 a8083063 Iustin Pop
  return result
2621 137161c9 Michael Hanselmann
2622 137161c9 Michael Hanselmann
2623 845c79d8 Michael Hanselmann
def ParseNicOption(optvalue):
2624 845c79d8 Michael Hanselmann
  """Parses the value of the --net option(s).
2625 845c79d8 Michael Hanselmann

2626 845c79d8 Michael Hanselmann
  """
2627 845c79d8 Michael Hanselmann
  try:
2628 845c79d8 Michael Hanselmann
    nic_max = max(int(nidx[0]) + 1 for nidx in optvalue)
2629 845c79d8 Michael Hanselmann
  except (TypeError, ValueError), err:
2630 2cfbc784 Iustin Pop
    raise errors.OpPrereqError("Invalid NIC index passed: %s" % str(err),
2631 2cfbc784 Iustin Pop
                               errors.ECODE_INVAL)
2632 845c79d8 Michael Hanselmann
2633 845c79d8 Michael Hanselmann
  nics = [{}] * nic_max
2634 845c79d8 Michael Hanselmann
  for nidx, ndict in optvalue:
2635 845c79d8 Michael Hanselmann
    nidx = int(nidx)
2636 845c79d8 Michael Hanselmann
2637 845c79d8 Michael Hanselmann
    if not isinstance(ndict, dict):
2638 845c79d8 Michael Hanselmann
      raise errors.OpPrereqError("Invalid nic/%d value: expected dict,"
2639 2cfbc784 Iustin Pop
                                 " got %s" % (nidx, ndict), errors.ECODE_INVAL)
2640 845c79d8 Michael Hanselmann
2641 845c79d8 Michael Hanselmann
    utils.ForceDictType(ndict, constants.INIC_PARAMS_TYPES)
2642 845c79d8 Michael Hanselmann
2643 845c79d8 Michael Hanselmann
    nics[nidx] = ndict
2644 845c79d8 Michael Hanselmann
2645 845c79d8 Michael Hanselmann
  return nics
2646 845c79d8 Michael Hanselmann
2647 845c79d8 Michael Hanselmann
2648 02a6b50a Michele Tartara
def FixHvParams(hvparams):
2649 02a6b50a Michele Tartara
  # In Ganeti 2.8.4 the separator for the usb_devices hvparam was changed from
2650 02a6b50a Michele Tartara
  # comma to space because commas cannot be accepted on the command line
2651 02a6b50a Michele Tartara
  # (they already act as the separator between different hvparams). Still,
2652 02a6b50a Michele Tartara
  # RAPI should be able to accept commas for backwards compatibility.
2653 02a6b50a Michele Tartara
  # Therefore, we convert spaces into commas here, and we keep the old
2654 02a6b50a Michele Tartara
  # parsing logic everywhere else.
2655 02a6b50a Michele Tartara
  try:
2656 02a6b50a Michele Tartara
    new_usb_devices = hvparams[constants.HV_USB_DEVICES].replace(" ", ",")
2657 02a6b50a Michele Tartara
    hvparams[constants.HV_USB_DEVICES] = new_usb_devices
2658 02a6b50a Michele Tartara
  except KeyError:
2659 02a6b50a Michele Tartara
    #No usb_devices, no modification required
2660 02a6b50a Michele Tartara
    pass
2661 02a6b50a Michele Tartara
2662 02a6b50a Michele Tartara
2663 d77490c5 Iustin Pop
def GenericInstanceCreate(mode, opts, args):
2664 d77490c5 Iustin Pop
  """Add an instance to the cluster via either creation or import.
2665 d77490c5 Iustin Pop

2666 d77490c5 Iustin Pop
  @param mode: constants.INSTANCE_CREATE or constants.INSTANCE_IMPORT
2667 d77490c5 Iustin Pop
  @param opts: the command line options selected by the user
2668 d77490c5 Iustin Pop
  @type args: list
2669 d77490c5 Iustin Pop
  @param args: should contain only one element, the new instance name
2670 d77490c5 Iustin Pop
  @rtype: int
2671 d77490c5 Iustin Pop
  @return: the desired exit code
2672 d77490c5 Iustin Pop

2673 d77490c5 Iustin Pop
  """
2674 d77490c5 Iustin Pop
  instance = args[0]
2675 d77490c5 Iustin Pop
2676 d77490c5 Iustin Pop
  (pnode, snode) = SplitNodeOption(opts.node)
2677 d77490c5 Iustin Pop
2678 d77490c5 Iustin Pop
  hypervisor = None
2679 d77490c5 Iustin Pop
  hvparams = {}
2680 d77490c5 Iustin Pop
  if opts.hypervisor:
2681 d77490c5 Iustin Pop
    hypervisor, hvparams = opts.hypervisor
2682 d77490c5 Iustin Pop
2683 d77490c5 Iustin Pop
  if opts.nics:
2684 845c79d8 Michael Hanselmann
    nics = ParseNicOption(opts.nics)
2685 d77490c5 Iustin Pop
  elif opts.no_nics:
2686 d77490c5 Iustin Pop
    # no nics
2687 d77490c5 Iustin Pop
    nics = []
2688 0af0f641 Iustin Pop
  elif mode == constants.INSTANCE_CREATE:
2689 d77490c5 Iustin Pop
    # default of one nic, all auto
2690 d77490c5 Iustin Pop
    nics = [{}]
2691 0af0f641 Iustin Pop
  else:
2692 0af0f641 Iustin Pop
    # mode == import
2693 0af0f641 Iustin Pop
    nics = []
2694 d77490c5 Iustin Pop
2695 d77490c5 Iustin Pop
  if opts.disk_template == constants.DT_DISKLESS:
2696 d77490c5 Iustin Pop
    if opts.disks or opts.sd_size is not None:
2697 d77490c5 Iustin Pop
      raise errors.OpPrereqError("Diskless instance but disk"
2698 2cfbc784 Iustin Pop
                                 " information passed", errors.ECODE_INVAL)
2699 d77490c5 Iustin Pop
    disks = []
2700 d77490c5 Iustin Pop
  else:
2701 9b12ed0f Iustin Pop
    if (not opts.disks and not opts.sd_size
2702 9b12ed0f Iustin Pop
        and mode == constants.INSTANCE_CREATE):
2703 2cfbc784 Iustin Pop
      raise errors.OpPrereqError("No disk information specified",
2704 2cfbc784 Iustin Pop
                                 errors.ECODE_INVAL)
2705 d77490c5 Iustin Pop
    if opts.disks and opts.sd_size is not None:
2706 d77490c5 Iustin Pop
      raise errors.OpPrereqError("Please use either the '--disk' or"
2707 2cfbc784 Iustin Pop
                                 " '-s' option", errors.ECODE_INVAL)
2708 d77490c5 Iustin Pop
    if opts.sd_size is not None:
2709 ccfa86ba Michael Hanselmann
      opts.disks = [(0, {constants.IDISK_SIZE: opts.sd_size})]
2710 9b12ed0f Iustin Pop
2711 9b12ed0f Iustin Pop
    if opts.disks:
2712 9b12ed0f Iustin Pop
      try:
2713 9b12ed0f Iustin Pop
        disk_max = max(int(didx[0]) + 1 for didx in opts.disks)
2714 9b12ed0f Iustin Pop
      except ValueError, err:
2715 2cfbc784 Iustin Pop
        raise errors.OpPrereqError("Invalid disk index passed: %s" % str(err),
2716 2cfbc784 Iustin Pop
                                   errors.ECODE_INVAL)
2717 9b12ed0f Iustin Pop
      disks = [{}] * disk_max
2718 9b12ed0f Iustin Pop
    else:
2719 9b12ed0f Iustin Pop
      disks = []
2720 d77490c5 Iustin Pop
    for didx, ddict in opts.disks:
2721 d77490c5 Iustin Pop
      didx = int(didx)
2722 d77490c5 Iustin Pop
      if not isinstance(ddict, dict):
2723 d77490c5 Iustin Pop
        msg = "Invalid disk/%d value: expected dict, got %s" % (didx, ddict)
2724 2cfbc784 Iustin Pop
        raise errors.OpPrereqError(msg, errors.ECODE_INVAL)
2725 ccfa86ba Michael Hanselmann
      elif constants.IDISK_SIZE in ddict:
2726 ccfa86ba Michael Hanselmann
        if constants.IDISK_ADOPT in ddict:
2727 5029db65 Iustin Pop
          raise errors.OpPrereqError("Only one of 'size' and 'adopt' allowed"
2728 2cfbc784 Iustin Pop
                                     " (disk %d)" % didx, errors.ECODE_INVAL)
2729 5029db65 Iustin Pop
        try:
2730 ccfa86ba Michael Hanselmann
          ddict[constants.IDISK_SIZE] = \
2731 ccfa86ba Michael Hanselmann
            utils.ParseUnit(ddict[constants.IDISK_SIZE])
2732 5029db65 Iustin Pop
        except ValueError, err:
2733 5029db65 Iustin Pop
          raise errors.OpPrereqError("Invalid disk size for disk %d: %s" %
2734 2cfbc784 Iustin Pop
                                     (didx, err), errors.ECODE_INVAL)
2735 ccfa86ba Michael Hanselmann
      elif constants.IDISK_ADOPT in ddict:
2736 c615590c Bernardo Dal Seno
        if constants.IDISK_SPINDLES in ddict:
2737 c615590c Bernardo Dal Seno
          raise errors.OpPrereqError("spindles is not a valid option when"
2738 c615590c Bernardo Dal Seno
                                     " adopting a disk", errors.ECODE_INVAL)
2739 5029db65 Iustin Pop
        if mode == constants.INSTANCE_IMPORT:
2740 5029db65 Iustin Pop
          raise errors.OpPrereqError("Disk adoption not allowed for instance"
2741 2cfbc784 Iustin Pop
                                     " import", errors.ECODE_INVAL)
2742 ccfa86ba Michael Hanselmann
        ddict[constants.IDISK_SIZE] = 0
2743 5029db65 Iustin Pop
      else:
2744 5029db65 Iustin Pop
        raise errors.OpPrereqError("Missing size or adoption source for"
2745 2cfbc784 Iustin Pop
                                   " disk %d" % didx, errors.ECODE_INVAL)
2746 e33c9e68 Helga Velroyen
      if constants.IDISK_SPINDLES in ddict:
2747 b8f36e88 Helga Velroyen
        ddict[constants.IDISK_SPINDLES] = int(ddict[constants.IDISK_SPINDLES])
2748 e33c9e68 Helga Velroyen
2749 d77490c5 Iustin Pop
      disks[didx] = ddict
2750 d77490c5 Iustin Pop
2751 a57981c5 Apollon Oikonomopoulos
  if opts.tags is not None:
2752 0f8810df Michael Hanselmann
    tags = opts.tags.split(",")
2753 a57981c5 Apollon Oikonomopoulos
  else:
2754 a57981c5 Apollon Oikonomopoulos
    tags = []
2755 a57981c5 Apollon Oikonomopoulos
2756 b2e233a5 Guido Trotter
  utils.ForceDictType(opts.beparams, constants.BES_PARAMETER_COMPAT)
2757 d77490c5 Iustin Pop
  utils.ForceDictType(hvparams, constants.HVS_PARAMETER_TYPES)
2758 02a6b50a Michele Tartara
  FixHvParams(hvparams)
2759 d77490c5 Iustin Pop
2760 d027b72b Jose A. Lopes
  osparams_private = opts.osparams_private or serializer.PrivateDict()
2761 d027b72b Jose A. Lopes
  osparams_secret = opts.osparams_secret or serializer.PrivateDict()
2762 d027b72b Jose A. Lopes
2763 d77490c5 Iustin Pop
  if mode == constants.INSTANCE_CREATE:
2764 d77490c5 Iustin Pop
    start = opts.start
2765 d77490c5 Iustin Pop
    os_type = opts.os
2766 1ee8e01a Guido Trotter
    force_variant = opts.force_variant
2767 d77490c5 Iustin Pop
    src_node = None
2768 d77490c5 Iustin Pop
    src_path = None
2769 25a8792c Iustin Pop
    no_install = opts.no_install
2770 e588764d Iustin Pop
    identify_defaults = False
2771 8ca22fef Thomas Thrainer
    compress = constants.IEC_NONE
2772 015f1517 Jose A. Lopes
    instance_communication = opts.instance_communication
2773 d77490c5 Iustin Pop
  elif mode == constants.INSTANCE_IMPORT:
2774 d77490c5 Iustin Pop
    start = False
2775 d77490c5 Iustin Pop
    os_type = None
2776 1ee8e01a Guido Trotter
    force_variant = False
2777 d77490c5 Iustin Pop
    src_node = opts.src_node
2778 d77490c5 Iustin Pop
    src_path = opts.src_dir
2779 25a8792c Iustin Pop
    no_install = None
2780 e588764d Iustin Pop
    identify_defaults = opts.identify_defaults
2781 8ca22fef Thomas Thrainer
    compress = opts.compress
2782 015f1517 Jose A. Lopes
    instance_communication = False
2783 d77490c5 Iustin Pop
  else:
2784 d77490c5 Iustin Pop
    raise errors.ProgrammerError("Invalid creation mode %s" % mode)
2785 d77490c5 Iustin Pop
2786 e1530b10 Iustin Pop
  op = opcodes.OpInstanceCreate(instance_name=instance,
2787 d77490c5 Iustin Pop
                                disks=disks,
2788 d77490c5 Iustin Pop
                                disk_template=opts.disk_template,
2789 d77490c5 Iustin Pop
                                nics=nics,
2790 d4117a72 Apollon Oikonomopoulos
                                conflicts_check=opts.conflicts_check,
2791 d77490c5 Iustin Pop
                                pnode=pnode, snode=snode,
2792 d77490c5 Iustin Pop
                                ip_check=opts.ip_check,
2793 460d22be Iustin Pop
                                name_check=opts.name_check,
2794 d77490c5 Iustin Pop
                                wait_for_sync=opts.wait_for_sync,
2795 d77490c5 Iustin Pop
                                file_storage_dir=opts.file_storage_dir,
2796 d77490c5 Iustin Pop
                                file_driver=opts.file_driver,
2797 d77490c5 Iustin Pop
                                iallocator=opts.iallocator,
2798 d77490c5 Iustin Pop
                                hypervisor=hypervisor,
2799 d77490c5 Iustin Pop
                                hvparams=hvparams,
2800 d77490c5 Iustin Pop
                                beparams=opts.beparams,
2801 062a7100 Iustin Pop
                                osparams=opts.osparams,
2802 31d3b918 Santi Raffa
                                osparams_private=osparams_private,
2803 31d3b918 Santi Raffa
                                osparams_secret=osparams_secret,
2804 d77490c5 Iustin Pop
                                mode=mode,
2805 d77490c5 Iustin Pop
                                start=start,
2806 d77490c5 Iustin Pop
                                os_type=os_type,
2807 1ee8e01a Guido Trotter
                                force_variant=force_variant,
2808 d77490c5 Iustin Pop
                                src_node=src_node,
2809 25a8792c Iustin Pop
                                src_path=src_path,
2810 8ca22fef Thomas Thrainer
                                compress=compress,
2811 a57981c5 Apollon Oikonomopoulos
                                tags=tags,
2812 e588764d Iustin Pop
                                no_install=no_install,
2813 10889e0c René Nussbaumer
                                identify_defaults=identify_defaults,
2814 015f1517 Jose A. Lopes
                                ignore_ipolicy=opts.ignore_ipolicy,
2815 015f1517 Jose A. Lopes
                                instance_communication=instance_communication)
2816 d77490c5 Iustin Pop
2817 d77490c5 Iustin Pop
  SubmitOrSend(op, opts)
2818 d77490c5 Iustin Pop
  return 0
2819 d77490c5 Iustin Pop
2820 d77490c5 Iustin Pop
2821 7e49b6ce Michael Hanselmann
class _RunWhileClusterStoppedHelper:
2822 7e49b6ce Michael Hanselmann
  """Helper class for L{RunWhileClusterStopped} to simplify state management
2823 7e49b6ce Michael Hanselmann

2824 7e49b6ce Michael Hanselmann
  """
2825 651ce6a3 Petr Pudlak
  def __init__(self, feedback_fn, cluster_name, master_node,
2826 651ce6a3 Petr Pudlak
               online_nodes, ssh_ports):
2827 7e49b6ce Michael Hanselmann
    """Initializes this class.
2828 7e49b6ce Michael Hanselmann

2829 7e49b6ce Michael Hanselmann
    @type feedback_fn: callable
2830 7e49b6ce Michael Hanselmann
    @param feedback_fn: Feedback function
2831 7e49b6ce Michael Hanselmann
    @type cluster_name: string
2832 7e49b6ce Michael Hanselmann
    @param cluster_name: Cluster name
2833 7e49b6ce Michael Hanselmann
    @type master_node: string
2834 7e49b6ce Michael Hanselmann
    @param master_node Master node name
2835 7e49b6ce Michael Hanselmann
    @type online_nodes: list
2836 7e49b6ce Michael Hanselmann
    @param online_nodes: List of names of online nodes
2837 651ce6a3 Petr Pudlak
    @type ssh_ports: list
2838 651ce6a3 Petr Pudlak
    @param ssh_ports: List of SSH ports of online nodes
2839 7e49b6ce Michael Hanselmann

2840 7e49b6ce Michael Hanselmann
    """
2841 7e49b6ce Michael Hanselmann
    self.feedback_fn = feedback_fn
2842 7e49b6ce Michael Hanselmann
    self.cluster_name = cluster_name
2843 7e49b6ce Michael Hanselmann
    self.master_node = master_node
2844 7e49b6ce Michael Hanselmann
    self.online_nodes = online_nodes
2845 651ce6a3 Petr Pudlak
    self.ssh_ports = dict(zip(online_nodes, ssh_ports))
2846 7e49b6ce Michael Hanselmann
2847 7e49b6ce Michael Hanselmann
    self.ssh = ssh.SshRunner(self.cluster_name)
2848 7e49b6ce Michael Hanselmann
2849 7e49b6ce Michael Hanselmann
    self.nonmaster_nodes = [name for name in online_nodes
2850 7e49b6ce Michael Hanselmann
                            if name != master_node]
2851 7e49b6ce Michael Hanselmann
2852 7e49b6ce Michael Hanselmann
    assert self.master_node not in self.nonmaster_nodes
2853 7e49b6ce Michael Hanselmann
2854 7e49b6ce Michael Hanselmann
  def _RunCmd(self, node_name, cmd):
2855 7e49b6ce Michael Hanselmann
    """Runs a command on the local or a remote machine.
2856 7e49b6ce Michael Hanselmann

2857 7e49b6ce Michael Hanselmann
    @type node_name: string
2858 7e49b6ce Michael Hanselmann
    @param node_name: Machine name
2859 7e49b6ce Michael Hanselmann
    @type cmd: list
2860 7e49b6ce Michael Hanselmann
    @param cmd: Command
2861 7e49b6ce Michael Hanselmann

2862 7e49b6ce Michael Hanselmann
    """
2863 7e49b6ce Michael Hanselmann
    if node_name is None or node_name == self.master_node:
2864 7e49b6ce Michael Hanselmann
      # No need to use SSH
2865 7e49b6ce Michael Hanselmann
      result = utils.RunCmd(cmd)
2866 7e49b6ce Michael Hanselmann
    else:
2867 052783ff Michael Hanselmann
      result = self.ssh.Run(node_name, constants.SSH_LOGIN_USER,
2868 651ce6a3 Petr Pudlak
                            utils.ShellQuoteArgs(cmd),
2869 651ce6a3 Petr Pudlak
                            port=self.ssh_ports[node_name])
2870 7e49b6ce Michael Hanselmann
2871 7e49b6ce Michael Hanselmann
    if result.failed:
2872 7e49b6ce Michael Hanselmann
      errmsg = ["Failed to run command %s" % result.cmd]
2873 7e49b6ce Michael Hanselmann
      if node_name:
2874 7e49b6ce Michael Hanselmann
        errmsg.append("on node %s" % node_name)
2875 7e49b6ce Michael Hanselmann
      errmsg.append(": exitcode %s and error %s" %
2876 7e49b6ce Michael Hanselmann
                    (result.exit_code, result.output))
2877 7e49b6ce Michael Hanselmann
      raise errors.OpExecError(" ".join(errmsg))
2878 7e49b6ce Michael Hanselmann
2879 7e49b6ce Michael Hanselmann
  def Call(self, fn, *args):
2880 7e49b6ce Michael Hanselmann
    """Call function while all daemons are stopped.
2881 7e49b6ce Michael Hanselmann

2882 7e49b6ce Michael Hanselmann
    @type fn: callable
2883 7e49b6ce Michael Hanselmann
    @param fn: Function to be called
2884 7e49b6ce Michael Hanselmann

2885 7e49b6ce Michael Hanselmann
    """
2886 7e49b6ce Michael Hanselmann
    # Pause watcher by acquiring an exclusive lock on watcher state file
2887 7e49b6ce Michael Hanselmann
    self.feedback_fn("Blocking watcher")
2888 ee4a14c0 Michael Hanselmann
    watcher_block = utils.FileLock.Open(pathutils.WATCHER_LOCK_FILE)
2889 7e49b6ce Michael Hanselmann
    try:
2890 7e49b6ce Michael Hanselmann
      # TODO: Currently, this just blocks. There's no timeout.
2891 7e49b6ce Michael Hanselmann
      # TODO: Should it be a shared lock?
2892 7e49b6ce Michael Hanselmann
      watcher_block.Exclusive(blocking=True)
2893 7e49b6ce Michael Hanselmann
2894 7e49b6ce Michael Hanselmann
      # Stop master daemons, so that no new jobs can come in and all running
2895 7e49b6ce Michael Hanselmann
      # ones are finished
2896 7e49b6ce Michael Hanselmann
      self.feedback_fn("Stopping master daemons")
2897 ee4a14c0 Michael Hanselmann
      self._RunCmd(None, [pathutils.DAEMON_UTIL, "stop-master"])
2898 7e49b6ce Michael Hanselmann
      try:
2899 7e49b6ce Michael Hanselmann
        # Stop daemons on all nodes
2900 7e49b6ce Michael Hanselmann
        for node_name in self.online_nodes:
2901 7e49b6ce Michael Hanselmann
          self.feedback_fn("Stopping daemons on %s" % node_name)
2902 ee4a14c0 Michael Hanselmann
          self._RunCmd(node_name, [pathutils.DAEMON_UTIL, "stop-all"])
2903 7e49b6ce Michael Hanselmann
2904 7e49b6ce Michael Hanselmann
        # All daemons are shut down now
2905 7e49b6ce Michael Hanselmann
        try:
2906 7e49b6ce Michael Hanselmann
          return fn(self, *args)
2907 d512e84b Michael Hanselmann
        except Exception, err:
2908 d512e84b Michael Hanselmann
          _, errmsg = FormatError(err)
2909 7e49b6ce Michael Hanselmann
          logging.exception("Caught exception")
2910 d512e84b Michael Hanselmann
          self.feedback_fn(errmsg)
2911 7e49b6ce Michael Hanselmann
          raise
2912 7e49b6ce Michael Hanselmann
      finally:
2913 7e49b6ce Michael Hanselmann
        # Start cluster again, master node last
2914 7e49b6ce Michael Hanselmann
        for node_name in self.nonmaster_nodes + [self.master_node]:
2915 7e49b6ce Michael Hanselmann
          self.feedback_fn("Starting daemons on %s" % node_name)
2916 ee4a14c0 Michael Hanselmann
          self._RunCmd(node_name, [pathutils.DAEMON_UTIL, "start-all"])
2917 7e49b6ce Michael Hanselmann
    finally:
2918 7e49b6ce Michael Hanselmann
      # Resume watcher
2919 7e49b6ce Michael Hanselmann
      watcher_block.Close()
2920 7e49b6ce Michael Hanselmann
2921 7e49b6ce Michael Hanselmann
2922 7e49b6ce Michael Hanselmann
def RunWhileClusterStopped(feedback_fn, fn, *args):
2923 7e49b6ce Michael Hanselmann
  """Calls a function while all cluster daemons are stopped.
2924 7e49b6ce Michael Hanselmann

2925 7e49b6ce Michael Hanselmann
  @type feedback_fn: callable
2926 7e49b6ce Michael Hanselmann
  @param feedback_fn: Feedback function
2927 7e49b6ce Michael Hanselmann
  @type fn: callable
2928 7e49b6ce Michael Hanselmann
  @param fn: Function to be called when daemons are stopped
2929 7e49b6ce Michael Hanselmann

2930 7e49b6ce Michael Hanselmann
  """
2931 7e49b6ce Michael Hanselmann
  feedback_fn("Gathering cluster information")
2932 7e49b6ce Michael Hanselmann
2933 7e49b6ce Michael Hanselmann
  # This ensures we're running on the master daemon
2934 7e49b6ce Michael Hanselmann
  cl = GetClient()
2935 bc57fa8d Helga Velroyen
  # Query client
2936 bc57fa8d Helga Velroyen
  qcl = GetClient(query=True)
2937 7e49b6ce Michael Hanselmann
2938 7e49b6ce Michael Hanselmann
  (cluster_name, master_node) = \
2939 7e49b6ce Michael Hanselmann
    cl.QueryConfigValues(["cluster_name", "master_node"])
2940 7e49b6ce Michael Hanselmann
2941 bc57fa8d Helga Velroyen
  online_nodes = GetOnlineNodes([], cl=qcl)
2942 bc57fa8d Helga Velroyen
  ssh_ports = GetNodesSshPorts(online_nodes, qcl)
2943 7e49b6ce Michael Hanselmann
2944 7e49b6ce Michael Hanselmann
  # Don't keep a reference to the client. The master daemon will go away.
2945 7e49b6ce Michael Hanselmann
  del cl
2946 bc57fa8d Helga Velroyen
  del qcl
2947 7e49b6ce Michael Hanselmann
2948 7e49b6ce Michael Hanselmann
  assert master_node in online_nodes
2949 7e49b6ce Michael Hanselmann
2950 7e49b6ce Michael Hanselmann
  return _RunWhileClusterStoppedHelper(feedback_fn, cluster_name, master_node,
2951 651ce6a3 Petr Pudlak
                                       online_nodes, ssh_ports).Call(fn, *args)
2952 7e49b6ce Michael Hanselmann
2953 7e49b6ce Michael Hanselmann
2954 16be8703 Iustin Pop
def GenerateTable(headers, fields, separator, data,
2955 9fbfbb7b Iustin Pop
                  numfields=None, unitfields=None,
2956 9fbfbb7b Iustin Pop
                  units=None):
2957 137161c9 Michael Hanselmann
  """Prints a table with headers and different fields.
2958 137161c9 Michael Hanselmann

2959 9fbfbb7b Iustin Pop
  @type headers: dict
2960 9fbfbb7b Iustin Pop
  @param headers: dictionary mapping field names to headers for
2961 9fbfbb7b Iustin Pop
      the table
2962 9fbfbb7b Iustin Pop
  @type fields: list
2963 9fbfbb7b Iustin Pop
  @param fields: the field names corresponding to each row in
2964 9fbfbb7b Iustin Pop
      the data field
2965 9fbfbb7b Iustin Pop
  @param separator: the separator to be used; if this is None,
2966 9fbfbb7b Iustin Pop
      the default 'smart' algorithm is used which computes optimal
2967 9fbfbb7b Iustin Pop
      field width, otherwise just the separator is used between
2968 9fbfbb7b Iustin Pop
      each field
2969 9fbfbb7b Iustin Pop
  @type data: list
2970 9fbfbb7b Iustin Pop
  @param data: a list of lists, each sublist being one row to be output
2971 9fbfbb7b Iustin Pop
  @type numfields: list
2972 9fbfbb7b Iustin Pop
  @param numfields: a list with the fields that hold numeric
2973 9fbfbb7b Iustin Pop
      values and thus should be right-aligned
2974 9fbfbb7b Iustin Pop
  @type unitfields: list
2975 9fbfbb7b Iustin Pop
  @param unitfields: a list with the fields that hold numeric
2976 9fbfbb7b Iustin Pop
      values that should be formatted with the units field
2977 9fbfbb7b Iustin Pop
  @type units: string or None
2978 9fbfbb7b Iustin Pop
  @param units: the units we should use for formatting, or None for
2979 9fbfbb7b Iustin Pop
      automatic choice (human-readable for non-separator usage, otherwise
2980 9fbfbb7b Iustin Pop
      megabytes); this is a one-letter string
2981 137161c9 Michael Hanselmann

2982 137161c9 Michael Hanselmann
  """
2983 9fbfbb7b Iustin Pop
  if units is None:
2984 9fbfbb7b Iustin Pop
    if separator:
2985 9fbfbb7b Iustin Pop
      units = "m"
2986 9fbfbb7b Iustin Pop
    else:
2987 9fbfbb7b Iustin Pop
      units = "h"
2988 9fbfbb7b Iustin Pop
2989 137161c9 Michael Hanselmann
  if numfields is None:
2990 137161c9 Michael Hanselmann
    numfields = []
2991 137161c9 Michael Hanselmann
  if unitfields is None:
2992 137161c9 Michael Hanselmann
    unitfields = []
2993 137161c9 Michael Hanselmann
2994 b459a848 Andrea Spadaccini
  numfields = utils.FieldSet(*numfields)   # pylint: disable=W0142
2995 b459a848 Andrea Spadaccini
  unitfields = utils.FieldSet(*unitfields) # pylint: disable=W0142
2996 00430f8e Iustin Pop
2997 137161c9 Michael Hanselmann
  format_fields = []
2998 137161c9 Michael Hanselmann
  for field in fields:
2999 01ca31ae Iustin Pop
    if headers and field not in headers:
3000 ea5a5b74 Guido Trotter
      # TODO: handle better unknown fields (either revert to old
3001 71c1af58 Iustin Pop
      # style of raising exception, or deal more intelligently with
3002 71c1af58 Iustin Pop
      # variable fields)
3003 71c1af58 Iustin Pop
      headers[field] = field
3004 137161c9 Michael Hanselmann
    if separator is not None:
3005 137161c9 Michael Hanselmann
      format_fields.append("%s")
3006 00430f8e Iustin Pop
    elif numfields.Matches(field):
3007 137161c9 Michael Hanselmann
      format_fields.append("%*s")
3008 137161c9 Michael Hanselmann
    else:
3009 137161c9 Michael Hanselmann
      format_fields.append("%-*s")
3010 137161c9 Michael Hanselmann
3011 137161c9 Michael Hanselmann
  if separator is None:
3012 137161c9 Michael Hanselmann
    mlens = [0 for name in fields]
3013 d0c8c01d Iustin Pop
    format_str = " ".join(format_fields)
3014 137161c9 Michael Hanselmann
  else:
3015 c04bc777 Iustin Pop
    format_str = separator.replace("%", "%%").join(format_fields)
3016 137161c9 Michael Hanselmann
3017 137161c9 Michael Hanselmann
  for row in data:
3018 dcbd6288 Guido Trotter
    if row is None:
3019 dcbd6288 Guido Trotter
      continue
3020 137161c9 Michael Hanselmann
    for idx, val in enumerate(row):
3021 00430f8e Iustin Pop
      if unitfields.Matches(fields[idx]):
3022 137161c9 Michael Hanselmann
        try:
3023 137161c9 Michael Hanselmann
          val = int(val)
3024 691744c4 Iustin Pop
        except (TypeError, ValueError):
3025 137161c9 Michael Hanselmann
          pass
3026 137161c9 Michael Hanselmann
        else:
3027 9fbfbb7b Iustin Pop
          val = row[idx] = utils.FormatUnit(val, units)
3028 01ca31ae Iustin Pop
      val = row[idx] = str(val)
3029 137161c9 Michael Hanselmann
      if separator is None:
3030 137161c9 Michael Hanselmann
        mlens[idx] = max(mlens[idx], len(val))
3031 137161c9 Michael Hanselmann
3032 16be8703 Iustin Pop
  result = []
3033 137161c9 Michael Hanselmann
  if headers:
3034 137161c9 Michael Hanselmann
    args = []
3035 137161c9 Michael Hanselmann
    for idx, name in enumerate(fields):
3036 137161c9 Michael Hanselmann
      hdr = headers[name]
3037 137161c9 Michael Hanselmann
      if separator is None:
3038 137161c9 Michael Hanselmann
        mlens[idx] = max(mlens[idx], len(hdr))
3039 137161c9 Michael Hanselmann
        args.append(mlens[idx])
3040 137161c9 Michael Hanselmann
      args.append(hdr)
3041 c04bc777 Iustin Pop
    result.append(format_str % tuple(args))
3042 137161c9 Michael Hanselmann
3043 ec39d63c Michael Hanselmann
  if separator is None:
3044 ec39d63c Michael Hanselmann
    assert len(mlens) == len(fields)
3045 ec39d63c Michael Hanselmann
3046 ec39d63c Michael Hanselmann
    if fields and not numfields.Matches(fields[-1]):
3047 ec39d63c Michael Hanselmann
      mlens[-1] = 0
3048 ec39d63c Michael Hanselmann
3049 137161c9 Michael Hanselmann
  for line in data:
3050 137161c9 Michael Hanselmann
    args = []
3051 dcbd6288 Guido Trotter
    if line is None:
3052 d0c8c01d Iustin Pop
      line = ["-" for _ in fields]
3053 f1501b3f Michael Hanselmann
    for idx in range(len(fields)):
3054 137161c9 Michael Hanselmann
      if separator is None:
3055 137161c9 Michael Hanselmann
        args.append(mlens[idx])
3056 137161c9 Michael Hanselmann
      args.append(line[idx])
3057 c04bc777 Iustin Pop
    result.append(format_str % tuple(args))
3058 16be8703 Iustin Pop
3059 16be8703 Iustin Pop
  return result
3060 3386e7a9 Iustin Pop
3061 3386e7a9 Iustin Pop
3062 ee3aedff Michael Hanselmann
def _FormatBool(value):
3063 ee3aedff Michael Hanselmann
  """Formats a boolean value as a string.
3064 ee3aedff Michael Hanselmann

3065 ee3aedff Michael Hanselmann
  """
3066 ee3aedff Michael Hanselmann
  if value:
3067 ee3aedff Michael Hanselmann
    return "Y"
3068 ee3aedff Michael Hanselmann
  return "N"
3069 ee3aedff Michael Hanselmann
3070 ee3aedff Michael Hanselmann
3071 ee3aedff Michael Hanselmann
#: Default formatting for query results; (callback, align right)
3072 ee3aedff Michael Hanselmann
_DEFAULT_FORMAT_QUERY = {
3073 ee3aedff Michael Hanselmann
  constants.QFT_TEXT: (str, False),
3074 ee3aedff Michael Hanselmann
  constants.QFT_BOOL: (_FormatBool, False),
3075 ee3aedff Michael Hanselmann
  constants.QFT_NUMBER: (str, True),
3076 ee3aedff Michael Hanselmann
  constants.QFT_TIMESTAMP: (utils.FormatTime, False),
3077 ee3aedff Michael Hanselmann
  constants.QFT_OTHER: (str, False),
3078 ee3aedff Michael Hanselmann
  constants.QFT_UNKNOWN: (str, False),
3079 ee3aedff Michael Hanselmann
  }
3080 ee3aedff Michael Hanselmann
3081 ee3aedff Michael Hanselmann
3082 ee3aedff Michael Hanselmann
def _GetColumnFormatter(fdef, override, unit):
3083 ee3aedff Michael Hanselmann
  """Returns formatting function for a field.
3084 ee3aedff Michael Hanselmann

3085 ee3aedff Michael Hanselmann
  @type fdef: L{objects.QueryFieldDefinition}
3086 ee3aedff Michael Hanselmann
  @type override: dict
3087 ee3aedff Michael Hanselmann
  @param override: Dictionary for overriding field formatting functions,
3088 ee3aedff Michael Hanselmann
    indexed by field name, contents like L{_DEFAULT_FORMAT_QUERY}
3089 ee3aedff Michael Hanselmann
  @type unit: string
3090 ee3aedff Michael Hanselmann
  @param unit: Unit used for formatting fields of type L{constants.QFT_UNIT}
3091 ee3aedff Michael Hanselmann
  @rtype: tuple; (callable, bool)
3092 ee3aedff Michael Hanselmann
  @return: Returns the function to format a value (takes one parameter) and a
3093 ee3aedff Michael Hanselmann
    boolean for aligning the value on the right-hand side
3094 ee3aedff Michael Hanselmann

3095 ee3aedff Michael Hanselmann
  """
3096 ee3aedff Michael Hanselmann
  fmt = override.get(fdef.name, None)
3097 ee3aedff Michael Hanselmann
  if fmt is not None:
3098 ee3aedff Michael Hanselmann
    return fmt
3099 ee3aedff Michael Hanselmann
3100 ee3aedff Michael Hanselmann
  assert constants.QFT_UNIT not in _DEFAULT_FORMAT_QUERY
3101 ee3aedff Michael Hanselmann
3102 ee3aedff Michael Hanselmann
  if fdef.kind == constants.QFT_UNIT:
3103 ee3aedff Michael Hanselmann
    # Can't keep this information in the static dictionary
3104 ee3aedff Michael Hanselmann
    return (lambda value: utils.FormatUnit(value, unit), True)
3105 ee3aedff Michael Hanselmann
3106 ee3aedff Michael Hanselmann
  fmt = _DEFAULT_FORMAT_QUERY.get(fdef.kind, None)
3107 ee3aedff Michael Hanselmann
  if fmt is not None:
3108 ee3aedff Michael Hanselmann
    return fmt
3109 ee3aedff Michael Hanselmann
3110 ee3aedff Michael Hanselmann
  raise NotImplementedError("Can't format column type '%s'" % fdef.kind)
3111 ee3aedff Michael Hanselmann
3112 ee3aedff Michael Hanselmann
3113 ee3aedff Michael Hanselmann
class _QueryColumnFormatter:
3114 ee3aedff Michael Hanselmann
  """Callable class for formatting fields of a query.
3115 ee3aedff Michael Hanselmann

3116 ee3aedff Michael Hanselmann
  """
3117 f0b1bafe Iustin Pop
  def __init__(self, fn, status_fn, verbose):
3118 ee3aedff Michael Hanselmann
    """Initializes this class.
3119 ee3aedff Michael Hanselmann

3120 ee3aedff Michael Hanselmann
    @type fn: callable
3121 ee3aedff Michael Hanselmann
    @param fn: Formatting function
3122 ee3aedff Michael Hanselmann
    @type status_fn: callable
3123 ee3aedff Michael Hanselmann
    @param status_fn: Function to report fields' status
3124 f0b1bafe Iustin Pop
    @type verbose: boolean
3125 f0b1bafe Iustin Pop
    @param verbose: whether to use verbose field descriptions or not
3126 ee3aedff Michael Hanselmann

3127 ee3aedff Michael Hanselmann
    """
3128 ee3aedff Michael Hanselmann
    self._fn = fn
3129 ee3aedff Michael Hanselmann
    self._status_fn = status_fn
3130 cbfa4f0f Michael Hanselmann
    self._verbose = verbose
3131 ee3aedff Michael Hanselmann
3132 ee3aedff Michael Hanselmann
  def __call__(self, data):
3133 ee3aedff Michael Hanselmann
    """Returns a field's string representation.
3134 ee3aedff Michael Hanselmann

3135 ee3aedff Michael Hanselmann
    """
3136 ee3aedff Michael Hanselmann
    (status, value) = data
3137 ee3aedff Michael Hanselmann
3138 ee3aedff Michael Hanselmann
    # Report status
3139 ee3aedff Michael Hanselmann
    self._status_fn(status)
3140 ee3aedff Michael Hanselmann
3141 cfb084ae René Nussbaumer
    if status == constants.RS_NORMAL:
3142 ee3aedff Michael Hanselmann
      return self._fn(value)
3143 ee3aedff Michael Hanselmann
3144 ee3aedff Michael Hanselmann
    assert value is None, \
3145 ee3aedff Michael Hanselmann
           "Found value %r for abnormal status %s" % (value, status)
3146 ee3aedff Michael Hanselmann
3147 f2c6673d Michael Hanselmann
    return FormatResultError(status, self._verbose)
3148 ee3aedff Michael Hanselmann
3149 ee3aedff Michael Hanselmann
3150 f2c6673d Michael Hanselmann
def FormatResultError(status, verbose):
3151 ae95e419 René Nussbaumer
  """Formats result status other than L{constants.RS_NORMAL}.
3152 ee3aedff Michael Hanselmann

3153 ae95e419 René Nussbaumer
  @param status: The result status
3154 f2c6673d Michael Hanselmann
  @type verbose: boolean
3155 f2c6673d Michael Hanselmann
  @param verbose: Whether to return the verbose text
3156 ae95e419 René Nussbaumer
  @return: Text of result status
3157 a6070ef7 Michael Hanselmann

3158 ae95e419 René Nussbaumer
  """
3159 ae95e419 René Nussbaumer
  assert status != constants.RS_NORMAL, \
3160 cbfa4f0f Michael Hanselmann
         "FormatResultError called with status equal to constants.RS_NORMAL"
3161 ae95e419 René Nussbaumer
  try:
3162 cbfa4f0f Michael Hanselmann
    (verbose_text, normal_text) = constants.RSS_DESCRIPTION[status]
3163 ae95e419 René Nussbaumer
  except KeyError:
3164 ee3aedff Michael Hanselmann
    raise NotImplementedError("Unknown status %s" % status)
3165 cbfa4f0f Michael Hanselmann
  else:
3166 cbfa4f0f Michael Hanselmann
    if verbose:
3167 cbfa4f0f Michael Hanselmann
      return verbose_text
3168 cbfa4f0f Michael Hanselmann
    return normal_text
3169 ee3aedff Michael Hanselmann
3170 ee3aedff Michael Hanselmann
3171 ee3aedff Michael Hanselmann
def FormatQueryResult(result, unit=None, format_override=None, separator=None,
3172 f0b1bafe Iustin Pop
                      header=False, verbose=False):
3173 ee3aedff Michael Hanselmann
  """Formats data in L{objects.QueryResponse}.
3174 ee3aedff Michael Hanselmann

3175 ee3aedff Michael Hanselmann
  @type result: L{objects.QueryResponse}
3176 ee3aedff Michael Hanselmann
  @param result: result of query operation
3177 ee3aedff Michael Hanselmann
  @type unit: string
3178 ee3aedff Michael Hanselmann
  @param unit: Unit used for formatting fields of type L{constants.QFT_UNIT},
3179 18009c1e Iustin Pop
    see L{utils.text.FormatUnit}
3180 ee3aedff Michael Hanselmann
  @type format_override: dict
3181 ee3aedff Michael Hanselmann
  @param format_override: Dictionary for overriding field formatting functions,
3182 ee3aedff Michael Hanselmann
    indexed by field name, contents like L{_DEFAULT_FORMAT_QUERY}
3183 ee3aedff Michael Hanselmann
  @type separator: string or None
3184 ee3aedff Michael Hanselmann
  @param separator: String used to separate fields
3185 ee3aedff Michael Hanselmann
  @type header: bool
3186 ee3aedff Michael Hanselmann
  @param header: Whether to output header row
3187 f0b1bafe Iustin Pop
  @type verbose: boolean
3188 f0b1bafe Iustin Pop
  @param verbose: whether to use verbose field descriptions or not
3189 ee3aedff Michael Hanselmann

3190 ee3aedff Michael Hanselmann
  """
3191 ee3aedff Michael Hanselmann
  if unit is None:
3192 ee3aedff Michael Hanselmann
    if separator:
3193 ee3aedff Michael Hanselmann
      unit = "m"
3194 ee3aedff Michael Hanselmann
    else:
3195 ee3aedff Michael Hanselmann
      unit = "h"
3196 ee3aedff Michael Hanselmann
3197 ee3aedff Michael Hanselmann
  if format_override is None:
3198 ee3aedff Michael Hanselmann
    format_override = {}
3199 ee3aedff Michael Hanselmann
3200 cfb084ae René Nussbaumer
  stats = dict.fromkeys(constants.RS_ALL, 0)
3201 ee3aedff Michael Hanselmann
3202 ee3aedff Michael Hanselmann
  def _RecordStatus(status):
3203 ee3aedff Michael Hanselmann
    if status in stats:
3204 ee3aedff Michael Hanselmann
      stats[status] += 1
3205 ee3aedff Michael Hanselmann
3206 ee3aedff Michael Hanselmann
  columns = []
3207 ee3aedff Michael Hanselmann
  for fdef in result.fields:
3208 ee3aedff Michael Hanselmann
    assert fdef.title and fdef.name
3209 ee3aedff Michael Hanselmann
    (fn, align_right) = _GetColumnFormatter(fdef, format_override, unit)
3210 ee3aedff Michael Hanselmann
    columns.append(TableColumn(fdef.title,
3211 f0b1bafe Iustin Pop
                               _QueryColumnFormatter(fn, _RecordStatus,
3212 f0b1bafe Iustin Pop
                                                     verbose),
3213 ee3aedff Michael Hanselmann
                               align_right))
3214 ee3aedff Michael Hanselmann
3215 ee3aedff Michael Hanselmann
  table = FormatTable(result.data, columns, header, separator)
3216 ee3aedff Michael Hanselmann
3217 ee3aedff Michael Hanselmann
  # Collect statistics
3218 cfb084ae René Nussbaumer
  assert len(stats) == len(constants.RS_ALL)
3219 ee3aedff Michael Hanselmann
  assert compat.all(count >= 0 for count in stats.values())
3220 ee3aedff Michael Hanselmann
3221 ee3aedff Michael Hanselmann
  # Determine overall status. If there was no data, unknown fields must be
3222 ee3aedff Michael Hanselmann
  # detected via the field definitions.
3223 cfb084ae René Nussbaumer
  if (stats[constants.RS_UNKNOWN] or
3224 ee3aedff Michael Hanselmann
      (not result.data and _GetUnknownFields(result.fields))):
3225 ee3aedff Michael Hanselmann
    status = QR_UNKNOWN
3226 ee3aedff Michael Hanselmann
  elif compat.any(count > 0 for key, count in stats.items()
3227 cfb084ae René Nussbaumer
                  if key != constants.RS_NORMAL):
3228 ee3aedff Michael Hanselmann
    status = QR_INCOMPLETE
3229 ee3aedff Michael Hanselmann
  else:
3230 ee3aedff Michael Hanselmann
    status = QR_NORMAL
3231 ee3aedff Michael Hanselmann
3232 ee3aedff Michael Hanselmann
  return (status, table)
3233 ee3aedff Michael Hanselmann
3234 ee3aedff Michael Hanselmann
3235 ee3aedff Michael Hanselmann
def _GetUnknownFields(fdefs):
3236 ee3aedff Michael Hanselmann
  """Returns list of unknown fields included in C{fdefs}.
3237 ee3aedff Michael Hanselmann

3238 ee3aedff Michael Hanselmann
  @type fdefs: list of L{objects.QueryFieldDefinition}
3239 ee3aedff Michael Hanselmann

3240 ee3aedff Michael Hanselmann
  """
3241 ee3aedff Michael Hanselmann
  return [fdef for fdef in fdefs
3242 ee3aedff Michael Hanselmann
          if fdef.kind == constants.QFT_UNKNOWN]
3243 ee3aedff Michael Hanselmann
3244 ee3aedff Michael Hanselmann
3245 ee3aedff Michael Hanselmann
def _WarnUnknownFields(fdefs):
3246 ee3aedff Michael Hanselmann
  """Prints a warning to stderr if a query included unknown fields.
3247 ee3aedff Michael Hanselmann

3248 ee3aedff Michael Hanselmann
  @type fdefs: list of L{objects.QueryFieldDefinition}
3249 ee3aedff Michael Hanselmann

3250 ee3aedff Michael Hanselmann
  """
3251 ee3aedff Michael Hanselmann
  unknown = _GetUnknownFields(fdefs)
3252 ee3aedff Michael Hanselmann
  if unknown:
3253 ee3aedff Michael Hanselmann
    ToStderr("Warning: Queried for unknown fields %s",
3254 ee3aedff Michael Hanselmann
             utils.CommaJoin(fdef.name for fdef in unknown))
3255 ee3aedff Michael Hanselmann
    return True
3256 ee3aedff Michael Hanselmann
3257 ee3aedff Michael Hanselmann
  return False
3258 ee3aedff Michael Hanselmann
3259 ee3aedff Michael Hanselmann
3260 ee3aedff Michael Hanselmann
def GenericList(resource, fields, names, unit, separator, header, cl=None,
3261 03ec545a Michael Hanselmann
                format_override=None, verbose=False, force_filter=False,
3262 6f287cf3 Iustin Pop
                namefield=None, qfilter=None, isnumeric=False):
3263 ee3aedff Michael Hanselmann
  """Generic implementation for listing all items of a resource.
3264 ee3aedff Michael Hanselmann

3265 abd66bf8 Michael Hanselmann
  @param resource: One of L{constants.QR_VIA_LUXI}
3266 ee3aedff Michael Hanselmann
  @type fields: list of strings
3267 ee3aedff Michael Hanselmann
  @param fields: List of fields to query for
3268 ee3aedff Michael Hanselmann
  @type names: list of strings
3269 ee3aedff Michael Hanselmann
  @param names: Names of items to query for
3270 ee3aedff Michael Hanselmann
  @type unit: string or None
3271 ee3aedff Michael Hanselmann
  @param unit: Unit used for formatting fields of type L{constants.QFT_UNIT} or
3272 ee3aedff Michael Hanselmann
    None for automatic choice (human-readable for non-separator usage,
3273 ee3aedff Michael Hanselmann
    otherwise megabytes); this is a one-letter string
3274 ee3aedff Michael Hanselmann
  @type separator: string or None
3275 ee3aedff Michael Hanselmann
  @param separator: String used to separate fields
3276 ee3aedff Michael Hanselmann
  @type header: bool
3277 ee3aedff Michael Hanselmann
  @param header: Whether to show header row
3278 2928de47 Michael Hanselmann
  @type force_filter: bool
3279 2928de47 Michael Hanselmann
  @param force_filter: Whether to always treat names as filter
3280 ee3aedff Michael Hanselmann
  @type format_override: dict
3281 ee3aedff Michael Hanselmann
  @param format_override: Dictionary for overriding field formatting functions,
3282 ee3aedff Michael Hanselmann
    indexed by field name, contents like L{_DEFAULT_FORMAT_QUERY}
3283 f0b1bafe Iustin Pop
  @type verbose: boolean
3284 f0b1bafe Iustin Pop
  @param verbose: whether to use verbose field descriptions or not
3285 03ec545a Michael Hanselmann
  @type namefield: string
3286 03ec545a Michael Hanselmann
  @param namefield: Name of field to use for simple filters (see
3287 03ec545a Michael Hanselmann
    L{qlang.MakeFilter} for details)
3288 f037e9d7 Michael Hanselmann
  @type qfilter: list or None
3289 f037e9d7 Michael Hanselmann
  @param qfilter: Query filter (in addition to names)
3290 6f287cf3 Iustin Pop
  @param isnumeric: bool
3291 6f287cf3 Iustin Pop
  @param isnumeric: Whether the namefield's type is numeric, and therefore
3292 6f287cf3 Iustin Pop
    any simple filters built by namefield should use integer values to
3293 6f287cf3 Iustin Pop
    reflect that
3294 ee3aedff Michael Hanselmann

3295 ee3aedff Michael Hanselmann
  """
3296 ee3aedff Michael Hanselmann
  if not names:
3297 ee3aedff Michael Hanselmann
    names = None
3298 ee3aedff Michael Hanselmann
3299 6f287cf3 Iustin Pop
  namefilter = qlang.MakeFilter(names, force_filter, namefield=namefield,
3300 6f287cf3 Iustin Pop
                                isnumeric=isnumeric)
3301 f037e9d7 Michael Hanselmann
3302 f037e9d7 Michael Hanselmann
  if qfilter is None:
3303 f037e9d7 Michael Hanselmann
    qfilter = namefilter
3304 f037e9d7 Michael Hanselmann
  elif namefilter is not None:
3305 f037e9d7 Michael Hanselmann
    qfilter = [qlang.OP_AND, namefilter, qfilter]
3306 2928de47 Michael Hanselmann
3307 727274dd Iustin Pop
  if cl is None:
3308 727274dd Iustin Pop
    cl = GetClient()
3309 727274dd Iustin Pop
3310 2e5c33db Iustin Pop
  response = cl.Query(resource, fields, qfilter)
3311 ee3aedff Michael Hanselmann
3312 ee3aedff Michael Hanselmann
  found_unknown = _WarnUnknownFields(response.fields)
3313 ee3aedff Michael Hanselmann
3314 ee3aedff Michael Hanselmann
  (status, data) = FormatQueryResult(response, unit=unit, separator=separator,
3315 ee3aedff Michael Hanselmann
                                     header=header,
3316 f0b1bafe Iustin Pop
                                     format_override=format_override,
3317 f0b1bafe Iustin Pop
                                     verbose=verbose)
3318 ee3aedff Michael Hanselmann
3319 ee3aedff Michael Hanselmann
  for line in data:
3320 ee3aedff Michael Hanselmann
    ToStdout(line)
3321 ee3aedff Michael Hanselmann
3322 ee3aedff Michael Hanselmann
  assert ((found_unknown and status == QR_UNKNOWN) or
3323 ee3aedff Michael Hanselmann
          (not found_unknown and status != QR_UNKNOWN))
3324 ee3aedff Michael Hanselmann
3325 ee3aedff Michael Hanselmann
  if status == QR_UNKNOWN:
3326 ee3aedff Michael Hanselmann
    return constants.EXIT_UNKNOWN_FIELD
3327 ee3aedff Michael Hanselmann
3328 ee3aedff Michael Hanselmann
  # TODO: Should the list command fail if not all data could be collected?
3329 ee3aedff Michael Hanselmann
  return constants.EXIT_SUCCESS
3330 ee3aedff Michael Hanselmann
3331 ee3aedff Michael Hanselmann
3332 c1912a48 Michael Hanselmann
def _FieldDescValues(fdef):
3333 c1912a48 Michael Hanselmann
  """Helper function for L{GenericListFields} to get query field description.
3334 c1912a48 Michael Hanselmann

3335 c1912a48 Michael Hanselmann
  @type fdef: L{objects.QueryFieldDefinition}
3336 c1912a48 Michael Hanselmann
  @rtype: list
3337 c1912a48 Michael Hanselmann

3338 c1912a48 Michael Hanselmann
  """
3339 c1912a48 Michael Hanselmann
  return [
3340 c1912a48 Michael Hanselmann
    fdef.name,
3341 c1912a48 Michael Hanselmann
    _QFT_NAMES.get(fdef.kind, fdef.kind),
3342 c1912a48 Michael Hanselmann
    fdef.title,
3343 c1912a48 Michael Hanselmann
    fdef.doc,
3344 c1912a48 Michael Hanselmann
    ]
3345 c1912a48 Michael Hanselmann
3346 c1912a48 Michael Hanselmann
3347 ee3aedff Michael Hanselmann
def GenericListFields(resource, fields, separator, header, cl=None):
3348 ee3aedff Michael Hanselmann
  """Generic implementation for listing fields for a resource.
3349 ee3aedff Michael Hanselmann

3350 abd66bf8 Michael Hanselmann
  @param resource: One of L{constants.QR_VIA_LUXI}
3351 ee3aedff Michael Hanselmann
  @type fields: list of strings
3352 ee3aedff Michael Hanselmann
  @param fields: List of fields to query for
3353 ee3aedff Michael Hanselmann
  @type separator: string or None
3354 ee3aedff Michael Hanselmann
  @param separator: String used to separate fields
3355 ee3aedff Michael Hanselmann
  @type header: bool
3356 ee3aedff Michael Hanselmann
  @param header: Whether to show header row
3357 ee3aedff Michael Hanselmann

3358 ee3aedff Michael Hanselmann
  """
3359 ee3aedff Michael Hanselmann
  if cl is None:
3360 ee3aedff Michael Hanselmann
    cl = GetClient()
3361 ee3aedff Michael Hanselmann
3362 ee3aedff Michael Hanselmann
  if not fields:
3363 ee3aedff Michael Hanselmann
    fields = None
3364 ee3aedff Michael Hanselmann
3365 ee3aedff Michael Hanselmann
  response = cl.QueryFields(resource, fields)
3366 ee3aedff Michael Hanselmann
3367 ee3aedff Michael Hanselmann
  found_unknown = _WarnUnknownFields(response.fields)
3368 ee3aedff Michael Hanselmann
3369 ee3aedff Michael Hanselmann
  columns = [
3370 ee3aedff Michael Hanselmann
    TableColumn("Name", str, False),
3371 c1912a48 Michael Hanselmann
    TableColumn("Type", str, False),
3372 ee3aedff Michael Hanselmann
    TableColumn("Title", str, False),
3373 ea1440c1 Michael Hanselmann
    TableColumn("Description", str, False),
3374 ee3aedff Michael Hanselmann
    ]
3375 ee3aedff Michael Hanselmann
3376 c1912a48 Michael Hanselmann
  rows = map(_FieldDescValues, response.fields)
3377 ee3aedff Michael Hanselmann
3378 ee3aedff Michael Hanselmann
  for line in FormatTable(rows, columns, header, separator):
3379 ee3aedff Michael Hanselmann
    ToStdout(line)
3380 ee3aedff Michael Hanselmann
3381 ee3aedff Michael Hanselmann
  if found_unknown:
3382 ee3aedff Michael Hanselmann
    return constants.EXIT_UNKNOWN_FIELD
3383 ee3aedff Michael Hanselmann
3384 ee3aedff Michael Hanselmann
  return constants.EXIT_SUCCESS
3385 ee3aedff Michael Hanselmann
3386 ee3aedff Michael Hanselmann
3387 ee3aedff Michael Hanselmann
class TableColumn:
3388 ee3aedff Michael Hanselmann
  """Describes a column for L{FormatTable}.
3389 ee3aedff Michael Hanselmann

3390 ee3aedff Michael Hanselmann
  """
3391 ee3aedff Michael Hanselmann
  def __init__(self, title, fn, align_right):
3392 ee3aedff Michael Hanselmann
    """Initializes this class.
3393 ee3aedff Michael Hanselmann

3394 ee3aedff Michael Hanselmann
    @type title: string
3395 ee3aedff Michael Hanselmann
    @param title: Column title
3396 ee3aedff Michael Hanselmann
    @type fn: callable
3397 ee3aedff Michael Hanselmann
    @param fn: Formatting function
3398 ee3aedff Michael Hanselmann
    @type align_right: bool
3399 ee3aedff Michael Hanselmann
    @param align_right: Whether to align values on the right-hand side
3400 ee3aedff Michael Hanselmann

3401 ee3aedff Michael Hanselmann
    """
3402 ee3aedff Michael Hanselmann
    self.title = title
3403 ee3aedff Michael Hanselmann
    self.format = fn
3404 ee3aedff Michael Hanselmann
    self.align_right = align_right
3405 ee3aedff Michael Hanselmann
3406 ee3aedff Michael Hanselmann
3407 ee3aedff Michael Hanselmann
def _GetColFormatString(width, align_right):
3408 ee3aedff Michael Hanselmann
  """Returns the format string for a field.
3409 ee3aedff Michael Hanselmann

3410 ee3aedff Michael Hanselmann
  """
3411 ee3aedff Michael Hanselmann
  if align_right:
3412 ee3aedff Michael Hanselmann
    sign = ""
3413 ee3aedff Michael Hanselmann
  else:
3414 ee3aedff Michael Hanselmann
    sign = "-"
3415 ee3aedff Michael Hanselmann
3416 ee3aedff Michael Hanselmann
  return "%%%s%ss" % (sign, width)
3417 ee3aedff Michael Hanselmann
3418 ee3aedff Michael Hanselmann
3419 ee3aedff Michael Hanselmann
def FormatTable(rows, columns, header, separator):
3420 ee3aedff Michael Hanselmann
  """Formats data as a table.
3421 ee3aedff Michael Hanselmann

3422 ee3aedff Michael Hanselmann
  @type rows: list of lists
3423 ee3aedff Michael Hanselmann
  @param rows: Row data, one list per row
3424 ee3aedff Michael Hanselmann
  @type columns: list of L{TableColumn}
3425 ee3aedff Michael Hanselmann
  @param columns: Column descriptions
3426 ee3aedff Michael Hanselmann
  @type header: bool
3427 ee3aedff Michael Hanselmann
  @param header: Whether to show header row
3428 ee3aedff Michael Hanselmann
  @type separator: string or None
3429 ee3aedff Michael Hanselmann
  @param separator: String used to separate columns
3430 ee3aedff Michael Hanselmann

3431 ee3aedff Michael Hanselmann
  """
3432 ee3aedff Michael Hanselmann
  if header:
3433 ee3aedff Michael Hanselmann
    data = [[col.title for col in columns]]
3434 ee3aedff Michael Hanselmann
    colwidth = [len(col.title) for col in columns]
3435 ee3aedff Michael Hanselmann
  else:
3436 ee3aedff Michael Hanselmann
    data = []
3437 ee3aedff Michael Hanselmann
    colwidth = [0 for _ in columns]
3438 ee3aedff Michael Hanselmann
3439 ee3aedff Michael Hanselmann
  # Format row data
3440 ee3aedff Michael Hanselmann
  for row in rows:
3441 ee3aedff Michael Hanselmann
    assert len(row) == len(columns)
3442 ee3aedff Michael Hanselmann
3443 ee3aedff Michael Hanselmann
    formatted = [col.format(value) for value, col in zip(row, columns)]
3444 ee3aedff Michael Hanselmann
3445 ee3aedff Michael Hanselmann
    if separator is None:
3446 ee3aedff Michael Hanselmann
      # Update column widths
3447 ee3aedff Michael Hanselmann
      for idx, (oldwidth, value) in enumerate(zip(colwidth, formatted)):
3448 ee3aedff Michael Hanselmann
        # Modifying a list's items while iterating is fine
3449 ee3aedff Michael Hanselmann
        colwidth[idx] = max(oldwidth, len(value))
3450 ee3aedff Michael Hanselmann
3451 ee3aedff Michael Hanselmann
    data.append(formatted)
3452 ee3aedff Michael Hanselmann
3453 ee3aedff Michael Hanselmann
  if separator is not None:
3454 ee3aedff Michael Hanselmann
    # Return early if a separator is used
3455 ee3aedff Michael Hanselmann
    return [separator.join(row) for row in data]
3456 ee3aedff Michael Hanselmann
3457 ee3aedff Michael Hanselmann
  if columns and not columns[-1].align_right:
3458 ee3aedff Michael Hanselmann
    # Avoid unnecessary spaces at end of line
3459 ee3aedff Michael Hanselmann
    colwidth[-1] = 0
3460 ee3aedff Michael Hanselmann
3461 ee3aedff Michael Hanselmann
  # Build format string
3462 ee3aedff Michael Hanselmann
  fmt = " ".join([_GetColFormatString(width, col.align_right)
3463 ee3aedff Michael Hanselmann
                  for col, width in zip(columns, colwidth)])
3464 ee3aedff Michael Hanselmann
3465 ee3aedff Michael Hanselmann
  return [fmt % tuple(row) for row in data]
3466 ee3aedff Michael Hanselmann
3467 ee3aedff Michael Hanselmann
3468 3386e7a9 Iustin Pop
def FormatTimestamp(ts):
3469 3386e7a9 Iustin Pop
  """Formats a given timestamp.
3470 3386e7a9 Iustin Pop

3471 3386e7a9 Iustin Pop
  @type ts: timestamp
3472 3386e7a9 Iustin Pop
  @param ts: a timeval-type timestamp, a tuple of seconds and microseconds
3473 3386e7a9 Iustin Pop

3474 3386e7a9 Iustin Pop
  @rtype: string
3475 5fcc718f Iustin Pop
  @return: a string with the formatted timestamp
3476 3386e7a9 Iustin Pop

3477 3386e7a9 Iustin Pop
  """
3478 e687ec01 Michael Hanselmann
  if not isinstance(ts, (tuple, list)) or len(ts) != 2:
3479 d0c8c01d Iustin Pop
    return "?"
3480 26a72a48 Michael Hanselmann
3481 26a72a48 Michael Hanselmann
  (sec, usecs) = ts
3482 26a72a48 Michael Hanselmann
  return utils.FormatTime(sec, usecs=usecs)
3483 2241e2b9 Iustin Pop
3484 2241e2b9 Iustin Pop
3485 2241e2b9 Iustin Pop
def ParseTimespec(value):
3486 2241e2b9 Iustin Pop
  """Parse a time specification.
3487 2241e2b9 Iustin Pop

3488 2241e2b9 Iustin Pop
  The following suffixed will be recognized:
3489 2241e2b9 Iustin Pop

3490 2241e2b9 Iustin Pop
    - s: seconds
3491 2241e2b9 Iustin Pop
    - m: minutes
3492 2241e2b9 Iustin Pop
    - h: hours
3493 2241e2b9 Iustin Pop
    - d: day
3494 2241e2b9 Iustin Pop
    - w: weeks
3495 2241e2b9 Iustin Pop

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

3498 2241e2b9 Iustin Pop
  """
3499 2241e2b9 Iustin Pop
  value = str(value)
3500 2241e2b9 Iustin Pop
  if not value:
3501 2cfbc784 Iustin Pop
    raise errors.OpPrereqError("Empty time specification passed",
3502 2cfbc784 Iustin Pop
                               errors.ECODE_INVAL)
3503 2241e2b9 Iustin Pop
  suffix_map = {
3504 d0c8c01d Iustin Pop
    "s": 1,
3505 d0c8c01d Iustin Pop
    "m": 60,
3506 d0c8c01d Iustin Pop
    "h": 3600,
3507 d0c8c01d Iustin Pop
    "d": 86400,
3508 d0c8c01d Iustin Pop
    "w": 604800,
3509 2241e2b9 Iustin Pop
    }
3510 2241e2b9 Iustin Pop
  if value[-1] not in suffix_map:
3511 2241e2b9 Iustin Pop
    try:
3512 2241e2b9 Iustin Pop
      value = int(value)
3513 691744c4 Iustin Pop
    except (TypeError, ValueError):
3514 2cfbc784 Iustin Pop
      raise errors.OpPrereqError("Invalid time specification '%s'" % value,
3515 2cfbc784 Iustin Pop
                                 errors.ECODE_INVAL)
3516 2241e2b9 Iustin Pop
  else:
3517 2241e2b9 Iustin Pop
    multiplier = suffix_map[value[-1]]
3518 2241e2b9 Iustin Pop
    value = value[:-1]
3519 2241e2b9 Iustin Pop
    if not value: # no data left after stripping the suffix
3520 2241e2b9 Iustin Pop
      raise errors.OpPrereqError("Invalid time specification (only"
3521 2cfbc784 Iustin Pop
                                 " suffix passed)", errors.ECODE_INVAL)
3522 2241e2b9 Iustin Pop
    try:
3523 2241e2b9 Iustin Pop
      value = int(value) * multiplier
3524 691744c4 Iustin Pop
    except (TypeError, ValueError):
3525 2cfbc784 Iustin Pop
      raise errors.OpPrereqError("Invalid time specification '%s'" % value,
3526 2cfbc784 Iustin Pop
                                 errors.ECODE_INVAL)
3527 2241e2b9 Iustin Pop
  return value
3528 46fbdd04 Iustin Pop
3529 46fbdd04 Iustin Pop
3530 e9e26bb3 Iustin Pop
def GetOnlineNodes(nodes, cl=None, nowarn=False, secondary_ips=False,
3531 05484a24 Michael Hanselmann
                   filter_master=False, nodegroup=None):
3532 4040a784 Iustin Pop
  """Returns the names of online nodes.
3533 4040a784 Iustin Pop

3534 4040a784 Iustin Pop
  This function will also log a warning on stderr with the names of
3535 4040a784 Iustin Pop
  the online nodes.
3536 4040a784 Iustin Pop

3537 4040a784 Iustin Pop
  @param nodes: if not empty, use only this subset of nodes (minus the
3538 4040a784 Iustin Pop
      offline ones)
3539 4040a784 Iustin Pop
  @param cl: if not None, luxi client to use
3540 4040a784 Iustin Pop
  @type nowarn: boolean
3541 4040a784 Iustin Pop
  @param nowarn: by default, this function will output a note with the
3542 4040a784 Iustin Pop
      offline nodes that are skipped; if this parameter is True the
3543 4040a784 Iustin Pop
      note is not displayed
3544 e9e26bb3 Iustin Pop
  @type secondary_ips: boolean
3545 e9e26bb3 Iustin Pop
  @param secondary_ips: if True, return the secondary IPs instead of the
3546 e9e26bb3 Iustin Pop
      names, useful for doing network traffic over the replication interface
3547 e9e26bb3 Iustin Pop
      (if any)
3548 e9e26bb3 Iustin Pop
  @type filter_master: boolean
3549 e9e26bb3 Iustin Pop
  @param filter_master: if True, do not return the master node in the list
3550 e9e26bb3 Iustin Pop
      (useful in coordination with secondary_ips where we cannot check our
3551 e9e26bb3 Iustin Pop
      node name against the list)
3552 05484a24 Michael Hanselmann
  @type nodegroup: string
3553 05484a24 Michael Hanselmann
  @param nodegroup: If set, only return nodes in this node group
3554 4040a784 Iustin Pop

3555 4040a784 Iustin Pop
  """
3556 4040a784 Iustin Pop
  if cl is None:
3557 bc57fa8d Helga Velroyen
    cl = GetClient(query=True)
3558 4040a784 Iustin Pop
3559 2e5c33db Iustin Pop
  qfilter = []
3560 05484a24 Michael Hanselmann
3561 05484a24 Michael Hanselmann
  if nodes:
3562 2e5c33db Iustin Pop
    qfilter.append(qlang.MakeSimpleFilter("name", nodes))
3563 05484a24 Michael Hanselmann
3564 05484a24 Michael Hanselmann
  if nodegroup is not None:
3565 2e5c33db Iustin Pop
    qfilter.append([qlang.OP_OR, [qlang.OP_EQUAL, "group", nodegroup],
3566 05484a24 Michael Hanselmann
                                 [qlang.OP_EQUAL, "group.uuid", nodegroup]])
3567 e9e26bb3 Iustin Pop
3568 e9e26bb3 Iustin Pop
  if filter_master:
3569 2e5c33db Iustin Pop
    qfilter.append([qlang.OP_NOT, [qlang.OP_TRUE, "master"]])
3570 05484a24 Michael Hanselmann
3571 2e5c33db Iustin Pop
  if qfilter:
3572 2e5c33db Iustin Pop
    if len(qfilter) > 1:
3573 2e5c33db Iustin Pop
      final_filter = [qlang.OP_AND] + qfilter
3574 05484a24 Michael Hanselmann
    else:
3575 2e5c33db Iustin Pop
      assert len(qfilter) == 1
3576 2e5c33db Iustin Pop
      final_filter = qfilter[0]
3577 e9e26bb3 Iustin Pop
  else:
3578 05484a24 Michael Hanselmann
    final_filter = None
3579 05484a24 Michael Hanselmann
3580 05484a24 Michael Hanselmann
  result = cl.Query(constants.QR_NODE, ["name", "offline", "sip"], final_filter)
3581 05484a24 Michael Hanselmann
3582 05484a24 Michael Hanselmann
  def _IsOffline(row):
3583 05484a24 Michael Hanselmann
    (_, (_, offline), _) = row
3584 05484a24 Michael Hanselmann
    return offline
3585 05484a24 Michael Hanselmann
3586 05484a24 Michael Hanselmann
  def _GetName(row):
3587 05484a24 Michael Hanselmann
    ((_, name), _, _) = row
3588 05484a24 Michael Hanselmann
    return name
3589 05484a24 Michael Hanselmann
3590 05484a24 Michael Hanselmann
  def _GetSip(row):
3591 05484a24 Michael Hanselmann
    (_, _, (_, sip)) = row
3592 05484a24 Michael Hanselmann
    return sip
3593 05484a24 Michael Hanselmann
3594 05484a24 Michael Hanselmann
  (offline, online) = compat.partition(result.data, _IsOffline)
3595 e9e26bb3 Iustin Pop
3596 4040a784 Iustin Pop
  if offline and not nowarn:
3597 05484a24 Michael Hanselmann
    ToStderr("Note: skipping offline node(s): %s" %
3598 05484a24 Michael Hanselmann
             utils.CommaJoin(map(_GetName, offline)))
3599 05484a24 Michael Hanselmann
3600 05484a24 Michael Hanselmann
  if secondary_ips:
3601 05484a24 Michael Hanselmann
    fn = _GetSip
3602 05484a24 Michael Hanselmann
  else:
3603 05484a24 Michael Hanselmann
    fn = _GetName
3604 05484a24 Michael Hanselmann
3605 05484a24 Michael Hanselmann
  return map(fn, online)
3606 4040a784 Iustin Pop
3607 4040a784 Iustin Pop
3608 651ce6a3 Petr Pudlak
def GetNodesSshPorts(nodes, cl):
3609 651ce6a3 Petr Pudlak
  """Retrieves SSH ports of given nodes.
3610 651ce6a3 Petr Pudlak

3611 651ce6a3 Petr Pudlak
  @param nodes: the names of nodes
3612 651ce6a3 Petr Pudlak
  @type nodes: a list of strings
3613 651ce6a3 Petr Pudlak
  @param cl: a client to use for the query
3614 651ce6a3 Petr Pudlak
  @type cl: L{Client}
3615 651ce6a3 Petr Pudlak
  @return: the list of SSH ports corresponding to the nodes
3616 651ce6a3 Petr Pudlak
  @rtype: a list of tuples
3617 651ce6a3 Petr Pudlak
  """
3618 651ce6a3 Petr Pudlak
  return map(lambda t: t[0],
3619 651ce6a3 Petr Pudlak
             cl.QueryNodes(names=nodes,
3620 651ce6a3 Petr Pudlak
                           fields=["ndp/ssh_port"],
3621 651ce6a3 Petr Pudlak
                           use_locking=False))
3622 651ce6a3 Petr Pudlak
3623 651ce6a3 Petr Pudlak
3624 46fbdd04 Iustin Pop
def _ToStream(stream, txt, *args):
3625 46fbdd04 Iustin Pop
  """Write a message to a stream, bypassing the logging system
3626 46fbdd04 Iustin Pop

3627 46fbdd04 Iustin Pop
  @type stream: file object
3628 46fbdd04 Iustin Pop
  @param stream: the file to which we should write
3629 46fbdd04 Iustin Pop
  @type txt: str
3630 46fbdd04 Iustin Pop
  @param txt: the message
3631 46fbdd04 Iustin Pop

3632 46fbdd04 Iustin Pop
  """
3633 225e2544 Iustin Pop
  try:
3634 225e2544 Iustin Pop
    if args:
3635 225e2544 Iustin Pop
      args = tuple(args)
3636 225e2544 Iustin Pop
      stream.write(txt % args)
3637 225e2544 Iustin Pop
    else:
3638 225e2544 Iustin Pop
      stream.write(txt)
3639 d0c8c01d Iustin Pop
    stream.write("\n")
3640 225e2544 Iustin Pop
    stream.flush()
3641 225e2544 Iustin Pop
  except IOError, err:
3642 225e2544 Iustin Pop
    if err.errno == errno.EPIPE:
3643 225e2544 Iustin Pop
      # our terminal went away, we'll exit
3644 225e2544 Iustin Pop
      sys.exit(constants.EXIT_FAILURE)
3645 225e2544 Iustin Pop
    else:
3646 225e2544 Iustin Pop
      raise
3647 46fbdd04 Iustin Pop
3648 46fbdd04 Iustin Pop
3649 46fbdd04 Iustin Pop
def ToStdout(txt, *args):
3650 46fbdd04 Iustin Pop
  """Write a message to stdout only, bypassing the logging system
3651 46fbdd04 Iustin Pop

3652 46fbdd04 Iustin Pop
  This is just a wrapper over _ToStream.
3653 46fbdd04 Iustin Pop

3654 46fbdd04 Iustin Pop
  @type txt: str
3655 46fbdd04 Iustin Pop
  @param txt: the message
3656 46fbdd04 Iustin Pop

3657 46fbdd04 Iustin Pop
  """
3658 46fbdd04 Iustin Pop
  _ToStream(sys.stdout, txt, *args)
3659 46fbdd04 Iustin Pop
3660 46fbdd04 Iustin Pop
3661 46fbdd04 Iustin Pop
def ToStderr(txt, *args):
3662 46fbdd04 Iustin Pop
  """Write a message to stderr only, bypassing the logging system
3663 46fbdd04 Iustin Pop

3664 46fbdd04 Iustin Pop
  This is just a wrapper over _ToStream.
3665 46fbdd04 Iustin Pop

3666 46fbdd04 Iustin Pop
  @type txt: str
3667 46fbdd04 Iustin Pop
  @param txt: the message
3668 46fbdd04 Iustin Pop

3669 46fbdd04 Iustin Pop
  """
3670 46fbdd04 Iustin Pop
  _ToStream(sys.stderr, txt, *args)
3671 479636a3 Iustin Pop
3672 479636a3 Iustin Pop
3673 479636a3 Iustin Pop
class JobExecutor(object):
3674 479636a3 Iustin Pop
  """Class which manages the submission and execution of multiple jobs.
3675 479636a3 Iustin Pop

3676 479636a3 Iustin Pop
  Note that instances of this class should not be reused between
3677 479636a3 Iustin Pop
  GetResults() calls.
3678 479636a3 Iustin Pop

3679 479636a3 Iustin Pop
  """
3680 919ca415 Iustin Pop
  def __init__(self, cl=None, verbose=True, opts=None, feedback_fn=None):
3681 479636a3 Iustin Pop
    self.queue = []
3682 479636a3 Iustin Pop
    if cl is None:
3683 479636a3 Iustin Pop
      cl = GetClient()
3684 479636a3 Iustin Pop
    self.cl = cl
3685 479636a3 Iustin Pop
    self.verbose = verbose
3686 23b4b983 Iustin Pop
    self.jobs = []
3687 cff5fa7f Iustin Pop
    self.opts = opts
3688 919ca415 Iustin Pop
    self.feedback_fn = feedback_fn
3689 60452edf Michael Hanselmann
    self._counter = itertools.count()
3690 479636a3 Iustin Pop
3691 8d99a8bf Michael Hanselmann
  @staticmethod
3692 8d99a8bf Michael Hanselmann
  def _IfName(name, fmt):
3693 8d99a8bf Michael Hanselmann
    """Helper function for formatting name.
3694 8d99a8bf Michael Hanselmann

3695 8d99a8bf Michael Hanselmann
    """
3696 8d99a8bf Michael Hanselmann
    if name:
3697 8d99a8bf Michael Hanselmann
      return fmt % name
3698 8d99a8bf Michael Hanselmann
3699 8d99a8bf Michael Hanselmann
    return ""
3700 8d99a8bf Michael Hanselmann
3701 479636a3 Iustin Pop
  def QueueJob(self, name, *ops):
3702 23b4b983 Iustin Pop
    """Record a job for later submit.
3703 479636a3 Iustin Pop

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

3707 479636a3 Iustin Pop
    """
3708 cff5fa7f Iustin Pop
    SetGenericOpcodeOpts(ops, self.opts)
3709 60452edf Michael Hanselmann
    self.queue.append((self._counter.next(), name, ops))
3710 23b4b983 Iustin Pop
3711 8d99a8bf Michael Hanselmann
  def AddJobId(self, name, status, job_id):
3712 8d99a8bf Michael Hanselmann
    """Adds a job ID to the internal queue.
3713 8d99a8bf Michael Hanselmann

3714 8d99a8bf Michael Hanselmann
    """
3715 8d99a8bf Michael Hanselmann
    self.jobs.append((self._counter.next(), status, job_id, name))
3716 8d99a8bf Michael Hanselmann
3717 66ecc479 Guido Trotter
  def SubmitPending(self, each=False):
3718 23b4b983 Iustin Pop
    """Submit all pending jobs.
3719 23b4b983 Iustin Pop

3720 23b4b983 Iustin Pop
    """
3721 66ecc479 Guido Trotter
    if each:
3722 66ecc479 Guido Trotter
      results = []
3723 60452edf Michael Hanselmann
      for (_, _, ops) in self.queue:
3724 66ecc479 Guido Trotter
        # SubmitJob will remove the success status, but raise an exception if
3725 66ecc479 Guido Trotter
        # the submission fails, so we'll notice that anyway.
3726 519fafa1 Andrea Spadaccini
        results.append([True, self.cl.SubmitJob(ops)[0]])
3727 66ecc479 Guido Trotter
    else:
3728 60452edf Michael Hanselmann
      results = self.cl.SubmitManyJobs([ops for (_, _, ops) in self.queue])
3729 60452edf Michael Hanselmann
    for ((status, data), (idx, name, _)) in zip(results, self.queue):
3730 5299e61f Iustin Pop
      self.jobs.append((idx, status, data, name))
3731 5299e61f Iustin Pop
3732 5299e61f Iustin Pop
  def _ChooseJob(self):
3733 5299e61f Iustin Pop
    """Choose a non-waiting/queued job to poll next.
3734 5299e61f Iustin Pop

3735 5299e61f Iustin Pop
    """
3736 5299e61f Iustin Pop
    assert self.jobs, "_ChooseJob called with empty job list"
3737 5299e61f Iustin Pop
3738 11705e3d Iustin Pop
    result = self.cl.QueryJobs([i[2] for i in self.jobs[:_CHOOSE_BATCH]],
3739 11705e3d Iustin Pop
                               ["status"])
3740 5299e61f Iustin Pop
    assert result
3741 5299e61f Iustin Pop
3742 5299e61f Iustin Pop
    for job_data, status in zip(self.jobs, result):
3743 91c622a8 Iustin Pop
      if (isinstance(status, list) and status and
3744 91c622a8 Iustin Pop
          status[0] in (constants.JOB_STATUS_QUEUED,
3745 47099cd1 Michael Hanselmann
                        constants.JOB_STATUS_WAITING,
3746 91c622a8 Iustin Pop
                        constants.JOB_STATUS_CANCELING)):
3747 91c622a8 Iustin Pop
        # job is still present and waiting
3748 5299e61f Iustin Pop
        continue
3749 91c622a8 Iustin Pop
      # good candidate found (either running job or lost job)
3750 5299e61f Iustin Pop
      self.jobs.remove(job_data)
3751 5299e61f Iustin Pop
      return job_data
3752 5299e61f Iustin Pop
3753 5299e61f Iustin Pop
    # no job found
3754 5299e61f Iustin Pop
    return self.jobs.pop(0)
3755 479636a3 Iustin Pop
3756 479636a3 Iustin Pop
  def GetResults(self):
3757 479636a3 Iustin Pop
    """Wait for and return the results of all jobs.
3758 479636a3 Iustin Pop

3759 479636a3 Iustin Pop
    @rtype: list
3760 479636a3 Iustin Pop
    @return: list of tuples (success, job results), in the same order
3761 479636a3 Iustin Pop
        as the submitted jobs; if a job has failed, instead of the result
3762 479636a3 Iustin Pop
        there will be the error message
3763 479636a3 Iustin Pop

3764 479636a3 Iustin Pop
    """
3765 23b4b983 Iustin Pop
    if not self.jobs:
3766 23b4b983 Iustin Pop
      self.SubmitPending()
3767 479636a3 Iustin Pop
    results = []
3768 479636a3 Iustin Pop
    if self.verbose:
3769 5299e61f Iustin Pop
      ok_jobs = [row[2] for row in self.jobs if row[1]]
3770 23b4b983 Iustin Pop
      if ok_jobs:
3771 4474f112 Iustin Pop
        ToStdout("Submitted jobs %s", utils.CommaJoin(ok_jobs))
3772 5299e61f Iustin Pop
3773 5299e61f Iustin Pop
    # first, remove any non-submitted jobs
3774 cea881e5 Michael Hanselmann
    self.jobs, failures = compat.partition(self.jobs, lambda x: x[1])
3775 5299e61f Iustin Pop
    for idx, _, jid, name in failures:
3776 4474f112 Iustin Pop
      ToStderr("Failed to submit job%s: %s", self._IfName(name, " for %s"), jid)
3777 c63355f2 Iustin Pop
      results.append((idx, False, jid))
3778 5299e61f Iustin Pop
3779 5299e61f Iustin Pop
    while self.jobs:
3780 5299e61f Iustin Pop
      (idx, _, jid, name) = self._ChooseJob()
3781 4474f112 Iustin Pop
      ToStdout("Waiting for job %s%s ...", jid, self._IfName(name, " for %s"))
3782 479636a3 Iustin Pop
      try:
3783 919ca415 Iustin Pop
        job_result = PollJob(jid, cl=self.cl, feedback_fn=self.feedback_fn)
3784 479636a3 Iustin Pop
        success = True
3785 91c622a8 Iustin Pop
      except errors.JobLost, err:
3786 91c622a8 Iustin Pop
        _, job_result = FormatError(err)
3787 4474f112 Iustin Pop
        ToStderr("Job %s%s has been archived, cannot check its result",
3788 4474f112 Iustin Pop
                 jid, self._IfName(name, " for %s"))
3789 91c622a8 Iustin Pop
        success = False
3790 9ba38706 Petr Pudlak
      except (errors.GenericError, rpcerr.ProtocolError), err:
3791 479636a3 Iustin Pop
        _, job_result = FormatError(err)
3792 479636a3 Iustin Pop
        success = False
3793 479636a3 Iustin Pop
        # the error message will always be shown, verbose or not
3794 4474f112 Iustin Pop
        ToStderr("Job %s%s has failed: %s",
3795 4474f112 Iustin Pop
                 jid, self._IfName(name, " for %s"), job_result)
3796 479636a3 Iustin Pop
3797 5299e61f Iustin Pop
      results.append((idx, success, job_result))
3798 5299e61f Iustin Pop
3799 5299e61f Iustin Pop
    # sort based on the index, then drop it
3800 5299e61f Iustin Pop
    results.sort()
3801 5299e61f Iustin Pop
    results = [i[1:] for i in results]
3802 5299e61f Iustin Pop
3803 479636a3 Iustin Pop
    return results
3804 479636a3 Iustin Pop
3805 479636a3 Iustin Pop
  def WaitOrShow(self, wait):
3806 479636a3 Iustin Pop
    """Wait for job results or only print the job IDs.
3807 479636a3 Iustin Pop

3808 479636a3 Iustin Pop
    @type wait: boolean
3809 479636a3 Iustin Pop
    @param wait: whether to wait or not
3810 479636a3 Iustin Pop

3811 479636a3 Iustin Pop
    """
3812 479636a3 Iustin Pop
    if wait:
3813 479636a3 Iustin Pop
      return self.GetResults()
3814 479636a3 Iustin Pop
    else:
3815 23b4b983 Iustin Pop
      if not self.jobs:
3816 23b4b983 Iustin Pop
        self.SubmitPending()
3817 71834b2a Guido Trotter
      for _, status, result, name in self.jobs:
3818 23b4b983 Iustin Pop
        if status:
3819 4474f112 Iustin Pop
          ToStdout("%s: %s", result, name)
3820 23b4b983 Iustin Pop
        else:
3821 4474f112 Iustin Pop
          ToStderr("Failure for %s: %s", name, result)
3822 53a8a54d Iustin Pop
      return [row[1:3] for row in self.jobs]
3823 acd19189 René Nussbaumer
3824 acd19189 René Nussbaumer
3825 4d99964c Bernardo Dal Seno
def FormatParamsDictInfo(param_dict, actual):
3826 4d99964c Bernardo Dal Seno
  """Formats a parameter dictionary.
3827 4d99964c Bernardo Dal Seno

3828 4d99964c Bernardo Dal Seno
  @type param_dict: dict
3829 4d99964c Bernardo Dal Seno
  @param param_dict: the own parameters
3830 4d99964c Bernardo Dal Seno
  @type actual: dict
3831 4d99964c Bernardo Dal Seno
  @param actual: the current parameter set (including defaults)
3832 4d99964c Bernardo Dal Seno
  @rtype: dict
3833 4d99964c Bernardo Dal Seno
  @return: dictionary where the value of each parameter is either a fully
3834 4d99964c Bernardo Dal Seno
      formatted string or a dictionary containing formatted strings
3835 4d99964c Bernardo Dal Seno

3836 4d99964c Bernardo Dal Seno
  """
3837 4d99964c Bernardo Dal Seno
  ret = {}
3838 4d99964c Bernardo Dal Seno
  for (key, data) in actual.items():
3839 4d99964c Bernardo Dal Seno
    if isinstance(data, dict) and data:
3840 4d99964c Bernardo Dal Seno
      ret[key] = FormatParamsDictInfo(param_dict.get(key, {}), data)
3841 4d99964c Bernardo Dal Seno
    else:
3842 4d99964c Bernardo Dal Seno
      ret[key] = str(param_dict.get(key, "default (%s)" % data))
3843 4d99964c Bernardo Dal Seno
  return ret
3844 4d99964c Bernardo Dal Seno
3845 4d99964c Bernardo Dal Seno
3846 d00884a2 Bernardo Dal Seno
def _FormatListInfoDefault(data, def_data):
3847 d00884a2 Bernardo Dal Seno
  if data is not None:
3848 d00884a2 Bernardo Dal Seno
    ret = utils.CommaJoin(data)
3849 d00884a2 Bernardo Dal Seno
  else:
3850 d00884a2 Bernardo Dal Seno
    ret = "default (%s)" % utils.CommaJoin(def_data)
3851 d00884a2 Bernardo Dal Seno
  return ret
3852 d00884a2 Bernardo Dal Seno
3853 d00884a2 Bernardo Dal Seno
3854 d00884a2 Bernardo Dal Seno
def FormatPolicyInfo(custom_ipolicy, eff_ipolicy, iscluster):
3855 d00884a2 Bernardo Dal Seno
  """Formats an instance policy.
3856 d00884a2 Bernardo Dal Seno

3857 d00884a2 Bernardo Dal Seno
  @type custom_ipolicy: dict
3858 d00884a2 Bernardo Dal Seno
  @param custom_ipolicy: own policy
3859 d00884a2 Bernardo Dal Seno
  @type eff_ipolicy: dict
3860 d00884a2 Bernardo Dal Seno
  @param eff_ipolicy: effective policy (including defaults); ignored for
3861 d00884a2 Bernardo Dal Seno
      cluster
3862 d00884a2 Bernardo Dal Seno
  @type iscluster: bool
3863 d00884a2 Bernardo Dal Seno
  @param iscluster: the policy is at cluster level
3864 d00884a2 Bernardo Dal Seno
  @rtype: list of pairs
3865 d00884a2 Bernardo Dal Seno
  @return: formatted data, suitable for L{PrintGenericInfo}
3866 d00884a2 Bernardo Dal Seno

3867 d00884a2 Bernardo Dal Seno
  """
3868 d00884a2 Bernardo Dal Seno
  if iscluster:
3869 d00884a2 Bernardo Dal Seno
    eff_ipolicy = custom_ipolicy
3870 d00884a2 Bernardo Dal Seno
3871 41044e04 Bernardo Dal Seno
  minmax_out = []
3872 41044e04 Bernardo Dal Seno
  custom_minmax = custom_ipolicy.get(constants.ISPECS_MINMAX)
3873 41044e04 Bernardo Dal Seno
  if custom_minmax:
3874 41044e04 Bernardo Dal Seno
    for (k, minmax) in enumerate(custom_minmax):
3875 41044e04 Bernardo Dal Seno
      minmax_out.append([
3876 41044e04 Bernardo Dal Seno
        ("%s/%s" % (key, k),
3877 41044e04 Bernardo Dal Seno
         FormatParamsDictInfo(minmax[key], minmax[key]))
3878 41044e04 Bernardo Dal Seno
        for key in constants.ISPECS_MINMAX_KEYS
3879 41044e04 Bernardo Dal Seno
        ])
3880 41044e04 Bernardo Dal Seno
  else:
3881 41044e04 Bernardo Dal Seno
    for (k, minmax) in enumerate(eff_ipolicy[constants.ISPECS_MINMAX]):
3882 41044e04 Bernardo Dal Seno
      minmax_out.append([
3883 41044e04 Bernardo Dal Seno
        ("%s/%s" % (key, k),
3884 41044e04 Bernardo Dal Seno
         FormatParamsDictInfo({}, minmax[key]))
3885 41044e04 Bernardo Dal Seno
        for key in constants.ISPECS_MINMAX_KEYS
3886 41044e04 Bernardo Dal Seno
        ])
3887 41044e04 Bernardo Dal Seno
  ret = [("bounds specs", minmax_out)]
3888 41044e04 Bernardo Dal Seno
3889 d00884a2 Bernardo Dal Seno
  if iscluster:
3890 d00884a2 Bernardo Dal Seno
    stdspecs = custom_ipolicy[constants.ISPECS_STD]
3891 d00884a2 Bernardo Dal Seno
    ret.append(
3892 d00884a2 Bernardo Dal Seno
      (constants.ISPECS_STD,
3893 d00884a2 Bernardo Dal Seno
       FormatParamsDictInfo(stdspecs, stdspecs))
3894 d00884a2 Bernardo Dal Seno
      )
3895 d00884a2 Bernardo Dal Seno
3896 d00884a2 Bernardo Dal Seno
  ret.append(
3897 9db0b351 Bernardo Dal Seno
    ("allowed disk templates",
3898 d00884a2 Bernardo Dal Seno
     _FormatListInfoDefault(custom_ipolicy.get(constants.IPOLICY_DTS),
3899 d00884a2 Bernardo Dal Seno
                            eff_ipolicy[constants.IPOLICY_DTS]))
3900 d00884a2 Bernardo Dal Seno
    )
3901 d00884a2 Bernardo Dal Seno
  ret.extend([
3902 d00884a2 Bernardo Dal Seno
    (key, str(custom_ipolicy.get(key, "default (%s)" % eff_ipolicy[key])))
3903 d00884a2 Bernardo Dal Seno
    for key in constants.IPOLICY_PARAMETERS
3904 d00884a2 Bernardo Dal Seno
    ])
3905 d00884a2 Bernardo Dal Seno
  return ret
3906 d00884a2 Bernardo Dal Seno
3907 d00884a2 Bernardo Dal Seno
3908 ea9d3b40 Bernardo Dal Seno
def _PrintSpecsParameters(buf, specs):
3909 ea9d3b40 Bernardo Dal Seno
  values = ("%s=%s" % (par, val) for (par, val) in sorted(specs.items()))
3910 ea9d3b40 Bernardo Dal Seno
  buf.write(",".join(values))
3911 ea9d3b40 Bernardo Dal Seno
3912 ea9d3b40 Bernardo Dal Seno
3913 ea9d3b40 Bernardo Dal Seno
def PrintIPolicyCommand(buf, ipolicy, isgroup):
3914 ea9d3b40 Bernardo Dal Seno
  """Print the command option used to generate the given instance policy.
3915 ea9d3b40 Bernardo Dal Seno

3916 ea9d3b40 Bernardo Dal Seno
  Currently only the parts dealing with specs are supported.
3917 ea9d3b40 Bernardo Dal Seno

3918 ea9d3b40 Bernardo Dal Seno
  @type buf: StringIO
3919 ea9d3b40 Bernardo Dal Seno
  @param buf: stream to write into
3920 ea9d3b40 Bernardo Dal Seno
  @type ipolicy: dict
3921 ea9d3b40 Bernardo Dal Seno
  @param ipolicy: instance policy
3922 ea9d3b40 Bernardo Dal Seno
  @type isgroup: bool
3923 ea9d3b40 Bernardo Dal Seno
  @param isgroup: whether the policy is at group level
3924 ea9d3b40 Bernardo Dal Seno

3925 ea9d3b40 Bernardo Dal Seno
  """
3926 ea9d3b40 Bernardo Dal Seno
  if not isgroup:
3927 ea9d3b40 Bernardo Dal Seno
    stdspecs = ipolicy.get("std")
3928 ea9d3b40 Bernardo Dal Seno
    if stdspecs:
3929 ea9d3b40 Bernardo Dal Seno
      buf.write(" %s " % IPOLICY_STD_SPECS_STR)
3930 ea9d3b40 Bernardo Dal Seno
      _PrintSpecsParameters(buf, stdspecs)
3931 ef99e3e8 Bernardo Dal Seno
  minmaxes = ipolicy.get("minmax", [])
3932 ef99e3e8 Bernardo Dal Seno
  first = True
3933 ef99e3e8 Bernardo Dal Seno
  for minmax in minmaxes:
3934 ef99e3e8 Bernardo Dal Seno
    minspecs = minmax.get("min")
3935 ef99e3e8 Bernardo Dal Seno
    maxspecs = minmax.get("max")
3936 ea9d3b40 Bernardo Dal Seno
    if minspecs and maxspecs:
3937 ef99e3e8 Bernardo Dal Seno
      if first:
3938 ef99e3e8 Bernardo Dal Seno
        buf.write(" %s " % IPOLICY_BOUNDS_SPECS_STR)
3939 ef99e3e8 Bernardo Dal Seno
        first = False
3940 ef99e3e8 Bernardo Dal Seno
      else:
3941 ef99e3e8 Bernardo Dal Seno
        buf.write("//")
3942 ea9d3b40 Bernardo Dal Seno
      buf.write("min:")
3943 ea9d3b40 Bernardo Dal Seno
      _PrintSpecsParameters(buf, minspecs)
3944 ea9d3b40 Bernardo Dal Seno
      buf.write("/max:")
3945 ea9d3b40 Bernardo Dal Seno
      _PrintSpecsParameters(buf, maxspecs)
3946 ea9d3b40 Bernardo Dal Seno
3947 ea9d3b40 Bernardo Dal Seno
3948 25bd815c René Nussbaumer
def ConfirmOperation(names, list_type, text, extra=""):
3949 25bd815c René Nussbaumer
  """Ask the user to confirm an operation on a list of list_type.
3950 25bd815c René Nussbaumer

3951 25bd815c René Nussbaumer
  This function is used to request confirmation for doing an operation
3952 25bd815c René Nussbaumer
  on a given list of list_type.
3953 25bd815c René Nussbaumer

3954 25bd815c René Nussbaumer
  @type names: list
3955 25bd815c René Nussbaumer
  @param names: the list of names that we display when
3956 25bd815c René Nussbaumer
      we ask for confirmation
3957 25bd815c René Nussbaumer
  @type list_type: str
3958 25bd815c René Nussbaumer
  @param list_type: Human readable name for elements in the list (e.g. nodes)
3959 25bd815c René Nussbaumer
  @type text: str
3960 25bd815c René Nussbaumer
  @param text: the operation that the user should confirm
3961 25bd815c René Nussbaumer
  @rtype: boolean
3962 25bd815c René Nussbaumer
  @return: True or False depending on user's confirmation.
3963 25bd815c René Nussbaumer

3964 25bd815c René Nussbaumer
  """
3965 25bd815c René Nussbaumer
  count = len(names)
3966 25bd815c René Nussbaumer
  msg = ("The %s will operate on %d %s.\n%s"
3967 25bd815c René Nussbaumer
         "Do you want to continue?" % (text, count, list_type, extra))
3968 25bd815c René Nussbaumer
  affected = (("\nAffected %s:\n" % list_type) +
3969 25bd815c René Nussbaumer
              "\n".join(["  %s" % name for name in names]))
3970 25bd815c René Nussbaumer
3971 25bd815c René Nussbaumer
  choices = [("y", True, "Yes, execute the %s" % text),
3972 25bd815c René Nussbaumer
             ("n", False, "No, abort the %s" % text)]
3973 25bd815c René Nussbaumer
3974 25bd815c René Nussbaumer
  if count > 20:
3975 25bd815c René Nussbaumer
    choices.insert(1, ("v", "v", "View the list of affected %s" % list_type))
3976 25bd815c René Nussbaumer
    question = msg
3977 25bd815c René Nussbaumer
  else:
3978 25bd815c René Nussbaumer
    question = msg + affected
3979 25bd815c René Nussbaumer
3980 25bd815c René Nussbaumer
  choice = AskUser(question, choices)
3981 25bd815c René Nussbaumer
  if choice == "v":
3982 25bd815c René Nussbaumer
    choices.pop(1)
3983 25bd815c René Nussbaumer
    choice = AskUser(msg + affected, choices)
3984 25bd815c René Nussbaumer
  return choice
3985 703fa9ab Iustin Pop
3986 703fa9ab Iustin Pop
3987 cd415612 René Nussbaumer
def _MaybeParseUnit(elements):
3988 cd415612 René Nussbaumer
  """Parses and returns an array of potential values with units.
3989 cd415612 René Nussbaumer

3990 cd415612 René Nussbaumer
  """
3991 ef40c537 René Nussbaumer
  parsed = {}
3992 ef40c537 René Nussbaumer
  for k, v in elements.items():
3993 ef40c537 René Nussbaumer
    if v == constants.VALUE_DEFAULT:
3994 ef40c537 René Nussbaumer
      parsed[k] = v
3995 cd415612 René Nussbaumer
    else:
3996 ef40c537 René Nussbaumer
      parsed[k] = utils.ParseUnit(v)
3997 cd415612 René Nussbaumer
  return parsed
3998 cd415612 René Nussbaumer
3999 cd415612 René Nussbaumer
4000 d2d3935a Bernardo Dal Seno
def _InitISpecsFromSplitOpts(ipolicy, ispecs_mem_size, ispecs_cpu_count,
4001 d2d3935a Bernardo Dal Seno
                             ispecs_disk_count, ispecs_disk_size,
4002 919db916 Bernardo Dal Seno
                             ispecs_nic_count, group_ipolicy, fill_all):
4003 d67e0a94 Iustin Pop
  try:
4004 d67e0a94 Iustin Pop
    if ispecs_mem_size:
4005 cd415612 René Nussbaumer
      ispecs_mem_size = _MaybeParseUnit(ispecs_mem_size)
4006 d67e0a94 Iustin Pop
    if ispecs_disk_size:
4007 cd415612 René Nussbaumer
      ispecs_disk_size = _MaybeParseUnit(ispecs_disk_size)
4008 d67e0a94 Iustin Pop
  except (TypeError, ValueError, errors.UnitParseError), err:
4009 d67e0a94 Iustin Pop
    raise errors.OpPrereqError("Invalid disk (%s) or memory (%s) size"
4010 d67e0a94 Iustin Pop
                               " in policy: %s" %
4011 d67e0a94 Iustin Pop
                               (ispecs_disk_size, ispecs_mem_size, err),
4012 d67e0a94 Iustin Pop
                               errors.ECODE_INVAL)
4013 d67e0a94 Iustin Pop
4014 703fa9ab Iustin Pop
  # prepare ipolicy dict
4015 d948c101 Bernardo Dal Seno
  ispecs_transposed = {
4016 703fa9ab Iustin Pop
    constants.ISPEC_MEM_SIZE: ispecs_mem_size,
4017 703fa9ab Iustin Pop
    constants.ISPEC_CPU_COUNT: ispecs_cpu_count,
4018 703fa9ab Iustin Pop
    constants.ISPEC_DISK_COUNT: ispecs_disk_count,
4019 703fa9ab Iustin Pop
    constants.ISPEC_DISK_SIZE: ispecs_disk_size,
4020 703fa9ab Iustin Pop
    constants.ISPEC_NIC_COUNT: ispecs_nic_count,
4021 703fa9ab Iustin Pop
    }
4022 703fa9ab Iustin Pop
4023 703fa9ab Iustin Pop
  # first, check that the values given are correct
4024 703fa9ab Iustin Pop
  if group_ipolicy:
4025 703fa9ab Iustin Pop
    forced_type = TISPECS_GROUP_TYPES
4026 703fa9ab Iustin Pop
  else:
4027 703fa9ab Iustin Pop
    forced_type = TISPECS_CLUSTER_TYPES
4028 d948c101 Bernardo Dal Seno
  for specs in ispecs_transposed.values():
4029 d2d3935a Bernardo Dal Seno
    assert type(specs) is dict
4030 919db916 Bernardo Dal Seno
    utils.ForceDictType(specs, forced_type)
4031 703fa9ab Iustin Pop
4032 703fa9ab Iustin Pop
  # then transpose
4033 da5f09ef Bernardo Dal Seno
  ispecs = {
4034 da5f09ef Bernardo Dal Seno
    constants.ISPECS_MIN: {},
4035 da5f09ef Bernardo Dal Seno
    constants.ISPECS_MAX: {},
4036 da5f09ef Bernardo Dal Seno
    constants.ISPECS_STD: {},
4037 da5f09ef Bernardo Dal Seno
    }
4038 d948c101 Bernardo Dal Seno
  for (name, specs) in ispecs_transposed.iteritems():
4039 703fa9ab Iustin Pop
    assert name in constants.ISPECS_PARAMETERS
4040 703fa9ab Iustin Pop
    for key, val in specs.items(): # {min: .. ,max: .., std: ..}
4041 da5f09ef Bernardo Dal Seno
      assert key in ispecs
4042 da5f09ef Bernardo Dal Seno
      ispecs[key][name] = val
4043 41044e04 Bernardo Dal Seno
  minmax_out = {}
4044 da5f09ef Bernardo Dal Seno
  for key in constants.ISPECS_MINMAX_KEYS:
4045 919db916 Bernardo Dal Seno
    if fill_all:
4046 41044e04 Bernardo Dal Seno
      minmax_out[key] = \
4047 919db916 Bernardo Dal Seno
        objects.FillDict(constants.ISPECS_MINMAX_DEFAULTS[key], ispecs[key])
4048 919db916 Bernardo Dal Seno
    else:
4049 41044e04 Bernardo Dal Seno
      minmax_out[key] = ispecs[key]
4050 41044e04 Bernardo Dal Seno
  ipolicy[constants.ISPECS_MINMAX] = [minmax_out]
4051 919db916 Bernardo Dal Seno
  if fill_all:
4052 919db916 Bernardo Dal Seno
    ipolicy[constants.ISPECS_STD] = \
4053 919db916 Bernardo Dal Seno
        objects.FillDict(constants.IPOLICY_DEFAULTS[constants.ISPECS_STD],
4054 919db916 Bernardo Dal Seno
                         ispecs[constants.ISPECS_STD])
4055 919db916 Bernardo Dal Seno
  else:
4056 919db916 Bernardo Dal Seno
    ipolicy[constants.ISPECS_STD] = ispecs[constants.ISPECS_STD]
4057 d948c101 Bernardo Dal Seno
4058 d948c101 Bernardo Dal Seno
4059 d2d3935a Bernardo Dal Seno
def _ParseSpecUnit(spec, keyname):
4060 d2d3935a Bernardo Dal Seno
  ret = spec.copy()
4061 d2d3935a Bernardo Dal Seno
  for k in [constants.ISPEC_DISK_SIZE, constants.ISPEC_MEM_SIZE]:
4062 919db916 Bernardo Dal Seno
    if k in ret:
4063 d2d3935a Bernardo Dal Seno
      try:
4064 d2d3935a Bernardo Dal Seno
        ret[k] = utils.ParseUnit(ret[k])
4065 d2d3935a Bernardo Dal Seno
      except (TypeError, ValueError, errors.UnitParseError), err:
4066 d2d3935a Bernardo Dal Seno
        raise errors.OpPrereqError(("Invalid parameter %s (%s) in %s instance"
4067 d2d3935a Bernardo Dal Seno
                                    " specs: %s" % (k, ret[k], keyname, err)),
4068 d2d3935a Bernardo Dal Seno
                                   errors.ECODE_INVAL)
4069 d2d3935a Bernardo Dal Seno
  return ret
4070 d2d3935a Bernardo Dal Seno
4071 d2d3935a Bernardo Dal Seno
4072 919db916 Bernardo Dal Seno
def _ParseISpec(spec, keyname, required):
4073 d2d3935a Bernardo Dal Seno
  ret = _ParseSpecUnit(spec, keyname)
4074 919db916 Bernardo Dal Seno
  utils.ForceDictType(ret, constants.ISPECS_PARAMETER_TYPES)
4075 919db916 Bernardo Dal Seno
  missing = constants.ISPECS_PARAMETERS - frozenset(ret.keys())
4076 919db916 Bernardo Dal Seno
  if required and missing:
4077 919db916 Bernardo Dal Seno
    raise errors.OpPrereqError("Missing parameters in ipolicy spec %s: %s" %
4078 919db916 Bernardo Dal Seno
                               (keyname, utils.CommaJoin(missing)),
4079 919db916 Bernardo Dal Seno
                               errors.ECODE_INVAL)
4080 919db916 Bernardo Dal Seno
  return ret
4081 919db916 Bernardo Dal Seno
4082 919db916 Bernardo Dal Seno
4083 919db916 Bernardo Dal Seno
def _GetISpecsInAllowedValues(minmax_ispecs, allowed_values):
4084 919db916 Bernardo Dal Seno
  ret = None
4085 ef99e3e8 Bernardo Dal Seno
  if (minmax_ispecs and allowed_values and len(minmax_ispecs) == 1 and
4086 ef99e3e8 Bernardo Dal Seno
      len(minmax_ispecs[0]) == 1):
4087 ef99e3e8 Bernardo Dal Seno
    for (key, spec) in minmax_ispecs[0].items():
4088 919db916 Bernardo Dal Seno
      # This loop is executed exactly once
4089 919db916 Bernardo Dal Seno
      if key in allowed_values and not spec:
4090 919db916 Bernardo Dal Seno
        ret = key
4091 d2d3935a Bernardo Dal Seno
  return ret
4092 d2d3935a Bernardo Dal Seno
4093 d2d3935a Bernardo Dal Seno
4094 d2d3935a Bernardo Dal Seno
def _InitISpecsFromFullOpts(ipolicy_out, minmax_ispecs, std_ispecs,
4095 d2d3935a Bernardo Dal Seno
                            group_ipolicy, allowed_values):
4096 919db916 Bernardo Dal Seno
  found_allowed = _GetISpecsInAllowedValues(minmax_ispecs, allowed_values)
4097 919db916 Bernardo Dal Seno
  if found_allowed is not None:
4098 919db916 Bernardo Dal Seno
    ipolicy_out[constants.ISPECS_MINMAX] = found_allowed
4099 919db916 Bernardo Dal Seno
  elif minmax_ispecs is not None:
4100 ef99e3e8 Bernardo Dal Seno
    minmax_out = []
4101 ef99e3e8 Bernardo Dal Seno
    for mmpair in minmax_ispecs:
4102 ef99e3e8 Bernardo Dal Seno
      mmpair_out = {}
4103 ef99e3e8 Bernardo Dal Seno
      for (key, spec) in mmpair.items():
4104 ef99e3e8 Bernardo Dal Seno
        if key not in constants.ISPECS_MINMAX_KEYS:
4105 ef99e3e8 Bernardo Dal Seno
          msg = "Invalid key in bounds instance specifications: %s" % key
4106 ef99e3e8 Bernardo Dal Seno
          raise errors.OpPrereqError(msg, errors.ECODE_INVAL)
4107 ef99e3e8 Bernardo Dal Seno
        mmpair_out[key] = _ParseISpec(spec, key, True)
4108 ef99e3e8 Bernardo Dal Seno
      minmax_out.append(mmpair_out)
4109 ef99e3e8 Bernardo Dal Seno
    ipolicy_out[constants.ISPECS_MINMAX] = minmax_out
4110 d2d3935a Bernardo Dal Seno
  if std_ispecs is not None:
4111 d2d3935a Bernardo Dal Seno
    assert not group_ipolicy # This is not an option for gnt-group
4112 919db916 Bernardo Dal Seno
    ipolicy_out[constants.ISPECS_STD] = _ParseISpec(std_ispecs, "std", False)
4113 d2d3935a Bernardo Dal Seno
4114 d2d3935a Bernardo Dal Seno
4115 d948c101 Bernardo Dal Seno
def CreateIPolicyFromOpts(ispecs_mem_size=None,
4116 d948c101 Bernardo Dal Seno
                          ispecs_cpu_count=None,
4117 d948c101 Bernardo Dal Seno
                          ispecs_disk_count=None,
4118 d948c101 Bernardo Dal Seno
                          ispecs_disk_size=None,
4119 d948c101 Bernardo Dal Seno
                          ispecs_nic_count=None,
4120 d2d3935a Bernardo Dal Seno
                          minmax_ispecs=None,
4121 d2d3935a Bernardo Dal Seno
                          std_ispecs=None,
4122 d948c101 Bernardo Dal Seno
                          ipolicy_disk_templates=None,
4123 d948c101 Bernardo Dal Seno
                          ipolicy_vcpu_ratio=None,
4124 d948c101 Bernardo Dal Seno
                          ipolicy_spindle_ratio=None,
4125 d948c101 Bernardo Dal Seno
                          group_ipolicy=False,
4126 d948c101 Bernardo Dal Seno
                          allowed_values=None,
4127 d948c101 Bernardo Dal Seno
                          fill_all=False):
4128 d948c101 Bernardo Dal Seno
  """Creation of instance policy based on command line options.
4129 d948c101 Bernardo Dal Seno

4130 d948c101 Bernardo Dal Seno
  @param fill_all: whether for cluster policies we should ensure that
4131 d948c101 Bernardo Dal Seno
    all values are filled
4132 d948c101 Bernardo Dal Seno

4133 d948c101 Bernardo Dal Seno
  """
4134 919db916 Bernardo Dal Seno
  assert not (fill_all and allowed_values)
4135 919db916 Bernardo Dal Seno
4136 919db916 Bernardo Dal Seno
  split_specs = (ispecs_mem_size or ispecs_cpu_count or ispecs_disk_count or
4137 919db916 Bernardo Dal Seno
                 ispecs_disk_size or ispecs_nic_count)
4138 919db916 Bernardo Dal Seno
  if (split_specs and (minmax_ispecs is not None or std_ispecs is not None)):
4139 d2d3935a Bernardo Dal Seno
    raise errors.OpPrereqError("A --specs-xxx option cannot be specified"
4140 d2d3935a Bernardo Dal Seno
                               " together with any --ipolicy-xxx-specs option",
4141 d2d3935a Bernardo Dal Seno
                               errors.ECODE_INVAL)
4142 d948c101 Bernardo Dal Seno
4143 d948c101 Bernardo Dal Seno
  ipolicy_out = objects.MakeEmptyIPolicy()
4144 919db916 Bernardo Dal Seno
  if split_specs:
4145 919db916 Bernardo Dal Seno
    assert fill_all
4146 d2d3935a Bernardo Dal Seno
    _InitISpecsFromSplitOpts(ipolicy_out, ispecs_mem_size, ispecs_cpu_count,
4147 d2d3935a Bernardo Dal Seno
                             ispecs_disk_count, ispecs_disk_size,
4148 919db916 Bernardo Dal Seno
                             ispecs_nic_count, group_ipolicy, fill_all)
4149 919db916 Bernardo Dal Seno
  elif (minmax_ispecs is not None or std_ispecs is not None):
4150 d2d3935a Bernardo Dal Seno
    _InitISpecsFromFullOpts(ipolicy_out, minmax_ispecs, std_ispecs,
4151 d2d3935a Bernardo Dal Seno
                            group_ipolicy, allowed_values)
4152 703fa9ab Iustin Pop
4153 703fa9ab Iustin Pop
  if ipolicy_disk_templates is not None:
4154 f824ae42 Bernardo Dal Seno
    if allowed_values and ipolicy_disk_templates in allowed_values:
4155 f824ae42 Bernardo Dal Seno
      ipolicy_out[constants.IPOLICY_DTS] = ipolicy_disk_templates
4156 f824ae42 Bernardo Dal Seno
    else:
4157 f824ae42 Bernardo Dal Seno
      ipolicy_out[constants.IPOLICY_DTS] = list(ipolicy_disk_templates)
4158 703fa9ab Iustin Pop
  if ipolicy_vcpu_ratio is not None:
4159 703fa9ab Iustin Pop
    ipolicy_out[constants.IPOLICY_VCPU_RATIO] = ipolicy_vcpu_ratio
4160 ad5cc6bd René Nussbaumer
  if ipolicy_spindle_ratio is not None:
4161 ad5cc6bd René Nussbaumer
    ipolicy_out[constants.IPOLICY_SPINDLE_RATIO] = ipolicy_spindle_ratio
4162 703fa9ab Iustin Pop
4163 703fa9ab Iustin Pop
  assert not (frozenset(ipolicy_out.keys()) - constants.IPOLICY_ALL_KEYS)
4164 703fa9ab Iustin Pop
4165 eeaa5f6c Bernardo Dal Seno
  if not group_ipolicy and fill_all:
4166 eeaa5f6c Bernardo Dal Seno
    ipolicy_out = objects.FillIPolicy(constants.IPOLICY_DEFAULTS, ipolicy_out)
4167 eeaa5f6c Bernardo Dal Seno
4168 703fa9ab Iustin Pop
  return ipolicy_out
4169 4d99964c Bernardo Dal Seno
4170 4d99964c Bernardo Dal Seno
4171 4d99964c Bernardo Dal Seno
def _SerializeGenericInfo(buf, data, level, afterkey=False):
4172 4d99964c Bernardo Dal Seno
  """Formatting core of L{PrintGenericInfo}.
4173 4d99964c Bernardo Dal Seno

4174 4d99964c Bernardo Dal Seno
  @param buf: (string) stream to accumulate the result into
4175 4d99964c Bernardo Dal Seno
  @param data: data to format
4176 4d99964c Bernardo Dal Seno
  @type level: int
4177 4d99964c Bernardo Dal Seno
  @param level: depth in the data hierarchy, used for indenting
4178 4d99964c Bernardo Dal Seno
  @type afterkey: bool
4179 4d99964c Bernardo Dal Seno
  @param afterkey: True when we are in the middle of a line after a key (used
4180 4d99964c Bernardo Dal Seno
      to properly add newlines or indentation)
4181 4d99964c Bernardo Dal Seno

4182 4d99964c Bernardo Dal Seno
  """
4183 4d99964c Bernardo Dal Seno
  baseind = "  "
4184 4d99964c Bernardo Dal Seno
  if isinstance(data, dict):
4185 4d99964c Bernardo Dal Seno
    if not data:
4186 4d99964c Bernardo Dal Seno
      buf.write("\n")
4187 4d99964c Bernardo Dal Seno
    else:
4188 4d99964c Bernardo Dal Seno
      if afterkey:
4189 4d99964c Bernardo Dal Seno
        buf.write("\n")
4190 4d99964c Bernardo Dal Seno
        doindent = True
4191 4d99964c Bernardo Dal Seno
      else:
4192 4d99964c Bernardo Dal Seno
        doindent = False
4193 4d99964c Bernardo Dal Seno
      for key in sorted(data):
4194 4d99964c Bernardo Dal Seno
        if doindent:
4195 4d99964c Bernardo Dal Seno
          buf.write(baseind * level)
4196 4d99964c Bernardo Dal Seno
        else:
4197 4d99964c Bernardo Dal Seno
          doindent = True
4198 4d99964c Bernardo Dal Seno
        buf.write(key)
4199 4d99964c Bernardo Dal Seno
        buf.write(": ")
4200 4d99964c Bernardo Dal Seno
        _SerializeGenericInfo(buf, data[key], level + 1, afterkey=True)
4201 4d99964c Bernardo Dal Seno
  elif isinstance(data, list) and len(data) > 0 and isinstance(data[0], tuple):
4202 4d99964c Bernardo Dal Seno
    # list of tuples (an ordered dictionary)
4203 4d99964c Bernardo Dal Seno
    if afterkey:
4204 4d99964c Bernardo Dal Seno
      buf.write("\n")
4205 4d99964c Bernardo Dal Seno
      doindent = True
4206 4d99964c Bernardo Dal Seno
    else:
4207 4d99964c Bernardo Dal Seno
      doindent = False
4208 4d99964c Bernardo Dal Seno
    for (key, val) in data:
4209 4d99964c Bernardo Dal Seno
      if doindent:
4210 4d99964c Bernardo Dal Seno
        buf.write(baseind * level)
4211 4d99964c Bernardo Dal Seno
      else:
4212 4d99964c Bernardo Dal Seno
        doindent = True
4213 4d99964c Bernardo Dal Seno
      buf.write(key)
4214 4d99964c Bernardo Dal Seno
      buf.write(": ")
4215 4d99964c Bernardo Dal Seno
      _SerializeGenericInfo(buf, val, level + 1, afterkey=True)
4216 4d99964c Bernardo Dal Seno
  elif isinstance(data, list):
4217 4d99964c Bernardo Dal Seno
    if not data:
4218 4d99964c Bernardo Dal Seno
      buf.write("\n")
4219 4d99964c Bernardo Dal Seno
    else:
4220 4d99964c Bernardo Dal Seno
      if afterkey:
4221 4d99964c Bernardo Dal Seno
        buf.write("\n")
4222 4d99964c Bernardo Dal Seno
        doindent = True
4223 4d99964c Bernardo Dal Seno
      else:
4224 4d99964c Bernardo Dal Seno
        doindent = False
4225 4d99964c Bernardo Dal Seno
      for item in data:
4226 4d99964c Bernardo Dal Seno
        if doindent:
4227 4d99964c Bernardo Dal Seno
          buf.write(baseind * level)
4228 4d99964c Bernardo Dal Seno
        else:
4229 4d99964c Bernardo Dal Seno
          doindent = True
4230 4d99964c Bernardo Dal Seno
        buf.write("-")
4231 4d99964c Bernardo Dal Seno
        buf.write(baseind[1:])
4232 4d99964c Bernardo Dal Seno
        _SerializeGenericInfo(buf, item, level + 1)
4233 4d99964c Bernardo Dal Seno
  else:
4234 4d99964c Bernardo Dal Seno
    # This branch should be only taken for strings, but it's practically
4235 4d99964c Bernardo Dal Seno
    # impossible to guarantee that no other types are produced somewhere
4236 4d99964c Bernardo Dal Seno
    buf.write(str(data))
4237 4d99964c Bernardo Dal Seno
    buf.write("\n")
4238 4d99964c Bernardo Dal Seno
4239 4d99964c Bernardo Dal Seno
4240 4d99964c Bernardo Dal Seno
def PrintGenericInfo(data):
4241 4d99964c Bernardo Dal Seno
  """Print information formatted according to the hierarchy.
4242 4d99964c Bernardo Dal Seno

4243 4d99964c Bernardo Dal Seno
  The output is a valid YAML string.
4244 4d99964c Bernardo Dal Seno

4245 4d99964c Bernardo Dal Seno
  @param data: the data to print. It's a hierarchical structure whose elements
4246 4d99964c Bernardo Dal Seno
      can be:
4247 4d99964c Bernardo Dal Seno
        - dictionaries, where keys are strings and values are of any of the
4248 4d99964c Bernardo Dal Seno
          types listed here
4249 4d99964c Bernardo Dal Seno
        - lists of pairs (key, value), where key is a string and value is of
4250 4d99964c Bernardo Dal Seno
          any of the types listed here; it's a way to encode ordered
4251 4d99964c Bernardo Dal Seno
          dictionaries
4252 4d99964c Bernardo Dal Seno
        - lists of any of the types listed here
4253 4d99964c Bernardo Dal Seno
        - strings
4254 4d99964c Bernardo Dal Seno

4255 4d99964c Bernardo Dal Seno
  """
4256 4d99964c Bernardo Dal Seno
  buf = StringIO()
4257 4d99964c Bernardo Dal Seno
  _SerializeGenericInfo(buf, data, 0)
4258 4d99964c Bernardo Dal Seno
  ToStdout(buf.getvalue().rstrip("\n"))