Revision 47988778

b/lib/cli.py
37 37
                      Option, OptionValueError, SUPPRESS_HELP)
38 38

  
39 39
__all__ = ["DEBUG_OPT", "NOHDR_OPT", "SEP_OPT", "GenericMain", "SubmitOpCode",
40
           "cli_option", "GenerateTable",
40
           "cli_option", "GenerateTable", "AskUser",
41 41
           "ARGS_NONE", "ARGS_FIXED", "ARGS_ATLEAST", "ARGS_ANY", "ARGS_ONE",
42 42
           "USEUNITS_OPT", "FIELDS_OPT", "FORCE_OPT"]
43 43

  
......
170 170
  return func, options, args
171 171

  
172 172

  
173
def _AskUser(text):
174
  """Ask the user a yes/no question.
173
def AskUser(text, choices=None):
174
  """Ask the user a question.
175 175

  
176 176
  Args:
177
    questionstring - the question to ask.
177
    text - the question to ask.
178 178

  
179
  Returns:
180
    True or False depending on answer (No for False is default).
179
    choices - list with elements tuples (input_char, return_value,
180
    description); if not given, it will default to: [('y', True,
181
    'Perform the operation'), ('n', False, 'Do no do the operation')];
182
    note that the '?' char is reserved for help
183

  
184
  Returns: one of the return values from the choices list; if input is
185
  not possible (i.e. not running with a tty, we return the last entry
186
  from the list
181 187

  
182 188
  """
189
  if choices is None:
190
    choices = [('y', True, 'Perform the operation'),
191
               ('n', False, 'Do not perform the operation')]
192
  if not choices or not isinstance(choices, list):
193
    raise errors.ProgrammerError("Invalid choiches argument to AskUser")
194
  for entry in choices:
195
    if not isinstance(entry, tuple) or len(entry) < 3 or entry[0] == '?':
196
      raise errors.ProgrammerError("Invalid choiches element to AskUser")
197

  
198
  answer = choices[-1][1]
199
  new_text = []
200
  for line in text.splitlines():
201
    new_text.append(textwrap.fill(line, 70, replace_whitespace=False))
202
  text = "\n".join(new_text)
183 203
  try:
184 204
    f = file("/dev/tty", "r+")
185 205
  except IOError:
186
    return False
187
  answer = False
206
    return answer
188 207
  try:
189
    f.write(textwrap.fill(text))
190
    f.write('\n')
191
    f.write("y/[n]: ")
192
    line = f.readline(16).strip().lower()
193
    answer = line in ('y', 'yes')
208
    chars = [entry[0] for entry in choices]
209
    chars[-1] = "[%s]" % chars[-1]
210
    chars.append('?')
211
    maps = dict([(entry[0], entry[1]) for entry in choices])
212
    while True:
213
      f.write(text)
214
      f.write('\n')
215
      f.write("/".join(chars))
216
      f.write(": ")
217
      line = f.readline(2).strip().lower()
218
      if line in maps:
219
        answer = maps[line]
220
        break
221
      elif line == '?':
222
        for entry in choices:
223
          f.write(" %s - %s\n" % (entry[0], entry[2]))
224
        f.write("\n")
225
        continue
194 226
  finally:
195 227
    f.close()
196 228
  return answer
......
231 263
  if func is None: # parse error
232 264
    return 1
233 265

  
234
  options._ask_user = _AskUser
235

  
236 266
  logger.SetupLogging(debug=options.debug, program=binary)
237 267

  
238 268
  try:
b/scripts/gnt-cluster
78 78
                " over the network to the cluster name, the operation is very"
79 79
                " dangerous as the IP address will be removed from the node"
80 80
                " and the change may not go through. Continue?") % name
81
    if not opts._ask_user(usertext):
81
    if not AskUser(usertext):
82 82
      return 1
83 83

  
84 84
  op = opcodes.OpRenameCluster(name=name)
b/scripts/gnt-instance
207 207
  if not opts.force:
208 208
    usertext = ("This will reinstall the instance %s and remove "
209 209
                "all data. Continue?") % instance_name
210
    if not opts._ask_user(usertext):
210
    if not AskUser(usertext):
211 211
      return 1
212 212

  
213 213
  op = opcodes.OpReinstallInstance(instance_name=instance_name,
......
232 232
    usertext = ("This will remove the volumes of the instance %s"
233 233
                " (including mirrors), thus removing all the data"
234 234
                " of the instance. Continue?") % instance_name
235
    if not opts._ask_user(usertext):
235
    if not AskUser(usertext):
236 236
      return 1
237 237

  
238 238
  op = opcodes.OpRemoveInstance(instance_name=instance_name)
......
394 394
    usertext = ("Failover will happen to image %s."
395 395
                " This requires a shutdown of the instance. Continue?" %
396 396
                (instance_name,))
397
    if not opts._ask_user(usertext):
397
    if not AskUser(usertext):
398 398
      return 1
399 399

  
400 400
  op = opcodes.OpFailoverInstance(instance_name=instance_name,

Also available in: Unified diff