Statistics
| Branch: | Tag: | Revision:

root / qa / qa_utils.py @ 016acd85

History | View | Annotate | Download (10.6 kB)

1 c68d1f43 Michael Hanselmann
#
2 c68d1f43 Michael Hanselmann
#
3 c68d1f43 Michael Hanselmann
4 cec9845c Michael Hanselmann
# Copyright (C) 2007 Google Inc.
5 cec9845c Michael Hanselmann
#
6 cec9845c Michael Hanselmann
# This program is free software; you can redistribute it and/or modify
7 cec9845c Michael Hanselmann
# it under the terms of the GNU General Public License as published by
8 cec9845c Michael Hanselmann
# the Free Software Foundation; either version 2 of the License, or
9 cec9845c Michael Hanselmann
# (at your option) any later version.
10 cec9845c Michael Hanselmann
#
11 cec9845c Michael Hanselmann
# This program is distributed in the hope that it will be useful, but
12 cec9845c Michael Hanselmann
# WITHOUT ANY WARRANTY; without even the implied warranty of
13 cec9845c Michael Hanselmann
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 cec9845c Michael Hanselmann
# General Public License for more details.
15 cec9845c Michael Hanselmann
#
16 cec9845c Michael Hanselmann
# You should have received a copy of the GNU General Public License
17 cec9845c Michael Hanselmann
# along with this program; if not, write to the Free Software
18 cec9845c Michael Hanselmann
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 cec9845c Michael Hanselmann
# 02110-1301, USA.
20 cec9845c Michael Hanselmann
21 cec9845c Michael Hanselmann
22 cec9845c Michael Hanselmann
"""Utilities for QA tests.
23 cec9845c Michael Hanselmann

24 cec9845c Michael Hanselmann
"""
25 cec9845c Michael Hanselmann
26 cec9845c Michael Hanselmann
import os
27 e6ce18ac René Nussbaumer
import re
28 23269c5b Michael Hanselmann
import sys
29 cec9845c Michael Hanselmann
import subprocess
30 288d6440 Michael Hanselmann
import random
31 cec9845c Michael Hanselmann
32 cec9845c Michael Hanselmann
from ganeti import utils
33 288d6440 Michael Hanselmann
from ganeti import compat
34 2214cf14 Michael Hanselmann
from ganeti import constants
35 cec9845c Michael Hanselmann
36 cec9845c Michael Hanselmann
import qa_config
37 cec9845c Michael Hanselmann
import qa_error
38 cec9845c Michael Hanselmann
39 cec9845c Michael Hanselmann
40 23269c5b Michael Hanselmann
_INFO_SEQ = None
41 23269c5b Michael Hanselmann
_WARNING_SEQ = None
42 23269c5b Michael Hanselmann
_ERROR_SEQ = None
43 23269c5b Michael Hanselmann
_RESET_SEQ = None
44 23269c5b Michael Hanselmann
45 23269c5b Michael Hanselmann
46 23269c5b Michael Hanselmann
def _SetupColours():
47 23269c5b Michael Hanselmann
  """Initializes the colour constants.
48 23269c5b Michael Hanselmann

49 23269c5b Michael Hanselmann
  """
50 23269c5b Michael Hanselmann
  global _INFO_SEQ, _WARNING_SEQ, _ERROR_SEQ, _RESET_SEQ
51 23269c5b Michael Hanselmann
52 dfe11bad Michael Hanselmann
  # Don't use colours if stdout isn't a terminal
53 dfe11bad Michael Hanselmann
  if not sys.stdout.isatty():
54 dfe11bad Michael Hanselmann
    return
55 dfe11bad Michael Hanselmann
56 23269c5b Michael Hanselmann
  try:
57 23269c5b Michael Hanselmann
    import curses
58 23269c5b Michael Hanselmann
  except ImportError:
59 23269c5b Michael Hanselmann
    # Don't use colours if curses module can't be imported
60 23269c5b Michael Hanselmann
    return
61 23269c5b Michael Hanselmann
62 23269c5b Michael Hanselmann
  curses.setupterm()
63 23269c5b Michael Hanselmann
64 23269c5b Michael Hanselmann
  _RESET_SEQ = curses.tigetstr("op")
65 23269c5b Michael Hanselmann
66 23269c5b Michael Hanselmann
  setaf = curses.tigetstr("setaf")
67 23269c5b Michael Hanselmann
  _INFO_SEQ = curses.tparm(setaf, curses.COLOR_GREEN)
68 23269c5b Michael Hanselmann
  _WARNING_SEQ = curses.tparm(setaf, curses.COLOR_YELLOW)
69 23269c5b Michael Hanselmann
  _ERROR_SEQ = curses.tparm(setaf, curses.COLOR_RED)
70 23269c5b Michael Hanselmann
71 23269c5b Michael Hanselmann
72 23269c5b Michael Hanselmann
_SetupColours()
73 23269c5b Michael Hanselmann
74 23269c5b Michael Hanselmann
75 eaef8a05 Michael Hanselmann
def AssertIn(item, sequence):
76 eaef8a05 Michael Hanselmann
  """Raises an error when item is not in sequence.
77 eaef8a05 Michael Hanselmann

78 eaef8a05 Michael Hanselmann
  """
79 eaef8a05 Michael Hanselmann
  if item not in sequence:
80 eaef8a05 Michael Hanselmann
    raise qa_error.Error('%r not in %r' % (item, sequence))
81 eaef8a05 Michael Hanselmann
82 eaef8a05 Michael Hanselmann
83 e8ae0c20 Michael Hanselmann
def AssertEqual(first, second):
84 cec9845c Michael Hanselmann
  """Raises an error when values aren't equal.
85 cec9845c Michael Hanselmann

86 cec9845c Michael Hanselmann
  """
87 cec9845c Michael Hanselmann
  if not first == second:
88 e8ae0c20 Michael Hanselmann
    raise qa_error.Error('%r == %r' % (first, second))
89 e8ae0c20 Michael Hanselmann
90 e8ae0c20 Michael Hanselmann
91 e8ae0c20 Michael Hanselmann
def AssertNotEqual(first, second):
92 e8ae0c20 Michael Hanselmann
  """Raises an error when values are equal.
93 e8ae0c20 Michael Hanselmann

94 e8ae0c20 Michael Hanselmann
  """
95 e8ae0c20 Michael Hanselmann
  if not first != second:
96 e8ae0c20 Michael Hanselmann
    raise qa_error.Error('%r != %r' % (first, second))
97 cec9845c Michael Hanselmann
98 cec9845c Michael Hanselmann
99 e6ce18ac René Nussbaumer
def AssertMatch(string, pattern):
100 e6ce18ac René Nussbaumer
  """Raises an error when string doesn't match regexp pattern.
101 e6ce18ac René Nussbaumer

102 e6ce18ac René Nussbaumer
  """
103 e6ce18ac René Nussbaumer
  if not re.match(pattern, string):
104 e6ce18ac René Nussbaumer
    raise qa_error.Error("%r doesn't match /%r/" % (string, pattern))
105 e6ce18ac René Nussbaumer
106 e6ce18ac René Nussbaumer
107 2f4b4f78 Iustin Pop
def AssertCommand(cmd, fail=False, node=None):
108 2f4b4f78 Iustin Pop
  """Checks that a remote command succeeds.
109 2f4b4f78 Iustin Pop

110 2f4b4f78 Iustin Pop
  @param cmd: either a string (the command to execute) or a list (to
111 2f4b4f78 Iustin Pop
      be converted using L{utils.ShellQuoteArgs} into a string)
112 2f4b4f78 Iustin Pop
  @type fail: boolean
113 2f4b4f78 Iustin Pop
  @param fail: if the command is expected to fail instead of succeeding
114 2f4b4f78 Iustin Pop
  @param node: if passed, it should be the node on which the command
115 2f4b4f78 Iustin Pop
      should be executed, instead of the master node (can be either a
116 2f4b4f78 Iustin Pop
      dict or a string)
117 2f4b4f78 Iustin Pop

118 2f4b4f78 Iustin Pop
  """
119 2f4b4f78 Iustin Pop
  if node is None:
120 2f4b4f78 Iustin Pop
    node = qa_config.GetMasterNode()
121 2f4b4f78 Iustin Pop
122 2f4b4f78 Iustin Pop
  if isinstance(node, basestring):
123 2f4b4f78 Iustin Pop
    nodename = node
124 2f4b4f78 Iustin Pop
  else:
125 2f4b4f78 Iustin Pop
    nodename = node["primary"]
126 2f4b4f78 Iustin Pop
127 2f4b4f78 Iustin Pop
  if isinstance(cmd, basestring):
128 2f4b4f78 Iustin Pop
    cmdstr = cmd
129 2f4b4f78 Iustin Pop
  else:
130 2f4b4f78 Iustin Pop
    cmdstr = utils.ShellQuoteArgs(cmd)
131 2f4b4f78 Iustin Pop
132 2f4b4f78 Iustin Pop
  rcode = StartSSH(nodename, cmdstr).wait()
133 2f4b4f78 Iustin Pop
134 2f4b4f78 Iustin Pop
  if fail:
135 2f4b4f78 Iustin Pop
    if rcode == 0:
136 2f4b4f78 Iustin Pop
      raise qa_error.Error("Command '%s' on node %s was expected to fail but"
137 2f4b4f78 Iustin Pop
                           " didn't" % (cmdstr, nodename))
138 2f4b4f78 Iustin Pop
  else:
139 2f4b4f78 Iustin Pop
    if rcode != 0:
140 2f4b4f78 Iustin Pop
      raise qa_error.Error("Command '%s' on node %s failed, exit code %s" %
141 2f4b4f78 Iustin Pop
                           (cmdstr, nodename, rcode))
142 2f4b4f78 Iustin Pop
143 2214cf14 Michael Hanselmann
  return rcode
144 2214cf14 Michael Hanselmann
145 2f4b4f78 Iustin Pop
146 cec9845c Michael Hanselmann
def GetSSHCommand(node, cmd, strict=True):
147 cec9845c Michael Hanselmann
  """Builds SSH command to be executed.
148 cec9845c Michael Hanselmann

149 c68d1f43 Michael Hanselmann
  Args:
150 c68d1f43 Michael Hanselmann
  - node: Node the command should run on
151 c68d1f43 Michael Hanselmann
  - cmd: Command to be executed as a list with all parameters
152 c68d1f43 Michael Hanselmann
  - strict: Whether to enable strict host key checking
153 c68d1f43 Michael Hanselmann

154 cec9845c Michael Hanselmann
  """
155 305cb9bb Michael Hanselmann
  args = [ 'ssh', '-oEscapeChar=none', '-oBatchMode=yes', '-l', 'root', '-t' ]
156 cec9845c Michael Hanselmann
157 cec9845c Michael Hanselmann
  if strict:
158 cec9845c Michael Hanselmann
    tmp = 'yes'
159 cec9845c Michael Hanselmann
  else:
160 cec9845c Michael Hanselmann
    tmp = 'no'
161 cec9845c Michael Hanselmann
  args.append('-oStrictHostKeyChecking=%s' % tmp)
162 cec9845c Michael Hanselmann
  args.append('-oClearAllForwardings=yes')
163 cec9845c Michael Hanselmann
  args.append('-oForwardAgent=yes')
164 cec9845c Michael Hanselmann
  args.append(node)
165 26a61f87 Michael Hanselmann
  args.append(cmd)
166 cec9845c Michael Hanselmann
167 cec9845c Michael Hanselmann
  return args
168 cec9845c Michael Hanselmann
169 cec9845c Michael Hanselmann
170 5d831182 Michael Hanselmann
def StartLocalCommand(cmd, **kwargs):
171 5d831182 Michael Hanselmann
  """Starts a local command.
172 5d831182 Michael Hanselmann

173 5d831182 Michael Hanselmann
  """
174 5d831182 Michael Hanselmann
  print "Command: %s" % utils.ShellQuoteArgs(cmd)
175 5d831182 Michael Hanselmann
  return subprocess.Popen(cmd, shell=False, **kwargs)
176 5d831182 Michael Hanselmann
177 5d831182 Michael Hanselmann
178 cec9845c Michael Hanselmann
def StartSSH(node, cmd, strict=True):
179 cec9845c Michael Hanselmann
  """Starts SSH.
180 cec9845c Michael Hanselmann

181 cec9845c Michael Hanselmann
  """
182 5d831182 Michael Hanselmann
  return StartLocalCommand(GetSSHCommand(node, cmd, strict=strict))
183 4b62db14 Michael Hanselmann
184 4b62db14 Michael Hanselmann
185 4b62db14 Michael Hanselmann
def GetCommandOutput(node, cmd):
186 4b62db14 Michael Hanselmann
  """Returns the output of a command executed on the given node.
187 4b62db14 Michael Hanselmann

188 4b62db14 Michael Hanselmann
  """
189 5d831182 Michael Hanselmann
  p = StartLocalCommand(GetSSHCommand(node, cmd), stdout=subprocess.PIPE)
190 4b62db14 Michael Hanselmann
  AssertEqual(p.wait(), 0)
191 4b62db14 Michael Hanselmann
  return p.stdout.read()
192 cec9845c Michael Hanselmann
193 cec9845c Michael Hanselmann
194 cec9845c Michael Hanselmann
def UploadFile(node, src):
195 cec9845c Michael Hanselmann
  """Uploads a file to a node and returns the filename.
196 cec9845c Michael Hanselmann

197 cec9845c Michael Hanselmann
  Caller needs to remove the returned file on the node when it's not needed
198 cec9845c Michael Hanselmann
  anymore.
199 49d50e52 Michael Hanselmann

200 cec9845c Michael Hanselmann
  """
201 cec9845c Michael Hanselmann
  # Make sure nobody else has access to it while preserving local permissions
202 cec9845c Michael Hanselmann
  mode = os.stat(src).st_mode & 0700
203 cec9845c Michael Hanselmann
204 cec9845c Michael Hanselmann
  cmd = ('tmp=$(tempfile --mode %o --prefix gnt) && '
205 cec9845c Michael Hanselmann
         '[[ -f "${tmp}" ]] && '
206 cec9845c Michael Hanselmann
         'cat > "${tmp}" && '
207 cec9845c Michael Hanselmann
         'echo "${tmp}"') % mode
208 cec9845c Michael Hanselmann
209 cec9845c Michael Hanselmann
  f = open(src, 'r')
210 cec9845c Michael Hanselmann
  try:
211 cec9845c Michael Hanselmann
    p = subprocess.Popen(GetSSHCommand(node, cmd), shell=False, stdin=f,
212 cec9845c Michael Hanselmann
                         stdout=subprocess.PIPE)
213 cec9845c Michael Hanselmann
    AssertEqual(p.wait(), 0)
214 cec9845c Michael Hanselmann
215 cec9845c Michael Hanselmann
    # Return temporary filename
216 cec9845c Michael Hanselmann
    return p.stdout.read().strip()
217 cec9845c Michael Hanselmann
  finally:
218 cec9845c Michael Hanselmann
    f.close()
219 5d640672 Michael Hanselmann
220 5d640672 Michael Hanselmann
221 b9955569 René Nussbaumer
def UploadData(node, data, mode=0600, filename=None):
222 b9955569 René Nussbaumer
  """Uploads data to a node and returns the filename.
223 b9955569 René Nussbaumer

224 b9955569 René Nussbaumer
  Caller needs to remove the returned file on the node when it's not needed
225 b9955569 René Nussbaumer
  anymore.
226 b9955569 René Nussbaumer

227 b9955569 René Nussbaumer
  """
228 b9955569 René Nussbaumer
  if filename:
229 b9955569 René Nussbaumer
    tmp = "tmp=%s" % utils.ShellQuote(filename)
230 b9955569 René Nussbaumer
  else:
231 b9955569 René Nussbaumer
    tmp = "tmp=$(tempfile --mode %o --prefix gnt)" % mode
232 b9955569 René Nussbaumer
  cmd = ("%s && "
233 b9955569 René Nussbaumer
         "[[ -f \"${tmp}\" ]] && "
234 b9955569 René Nussbaumer
         "cat > \"${tmp}\" && "
235 b9955569 René Nussbaumer
         "echo \"${tmp}\"") % tmp
236 b9955569 René Nussbaumer
237 b9955569 René Nussbaumer
  p = subprocess.Popen(GetSSHCommand(node, cmd), shell=False,
238 b9955569 René Nussbaumer
                       stdin=subprocess.PIPE, stdout=subprocess.PIPE)
239 b9955569 René Nussbaumer
  p.stdin.write(data)
240 b9955569 René Nussbaumer
  p.stdin.close()
241 b9955569 René Nussbaumer
  AssertEqual(p.wait(), 0)
242 b9955569 René Nussbaumer
243 b9955569 René Nussbaumer
  # Return temporary filename
244 b9955569 René Nussbaumer
  return p.stdout.read().strip()
245 b9955569 René Nussbaumer
246 b9955569 René Nussbaumer
247 49d50e52 Michael Hanselmann
def BackupFile(node, path):
248 49d50e52 Michael Hanselmann
  """Creates a backup of a file on the node and returns the filename.
249 49d50e52 Michael Hanselmann

250 49d50e52 Michael Hanselmann
  Caller needs to remove the returned file on the node when it's not needed
251 49d50e52 Michael Hanselmann
  anymore.
252 49d50e52 Michael Hanselmann

253 49d50e52 Michael Hanselmann
  """
254 49d50e52 Michael Hanselmann
  cmd = ("tmp=$(tempfile --prefix .gnt --directory=$(dirname %s)) && "
255 49d50e52 Michael Hanselmann
         "[[ -f \"$tmp\" ]] && "
256 49d50e52 Michael Hanselmann
         "cp %s $tmp && "
257 49d50e52 Michael Hanselmann
         "echo $tmp") % (utils.ShellQuote(path), utils.ShellQuote(path))
258 49d50e52 Michael Hanselmann
259 49d50e52 Michael Hanselmann
  # Return temporary filename
260 49d50e52 Michael Hanselmann
  return GetCommandOutput(node, cmd).strip()
261 49d50e52 Michael Hanselmann
262 49d50e52 Michael Hanselmann
263 4b62db14 Michael Hanselmann
def _ResolveName(cmd, key):
264 4b62db14 Michael Hanselmann
  """Helper function.
265 4b62db14 Michael Hanselmann

266 4b62db14 Michael Hanselmann
  """
267 4b62db14 Michael Hanselmann
  master = qa_config.GetMasterNode()
268 4b62db14 Michael Hanselmann
269 4b62db14 Michael Hanselmann
  output = GetCommandOutput(master['primary'], utils.ShellQuoteArgs(cmd))
270 4b62db14 Michael Hanselmann
  for line in output.splitlines():
271 4b62db14 Michael Hanselmann
    (lkey, lvalue) = line.split(':', 1)
272 4b62db14 Michael Hanselmann
    if lkey == key:
273 4b62db14 Michael Hanselmann
      return lvalue.lstrip()
274 4b62db14 Michael Hanselmann
  raise KeyError("Key not found")
275 4b62db14 Michael Hanselmann
276 4b62db14 Michael Hanselmann
277 5d640672 Michael Hanselmann
def ResolveInstanceName(instance):
278 5d640672 Michael Hanselmann
  """Gets the full name of an instance.
279 5d640672 Michael Hanselmann

280 46f9a948 Michael Hanselmann
  @type instance: string
281 46f9a948 Michael Hanselmann
  @param instance: Instance name
282 46f9a948 Michael Hanselmann

283 5d640672 Michael Hanselmann
  """
284 46f9a948 Michael Hanselmann
  return _ResolveName(['gnt-instance', 'info', instance],
285 4b62db14 Michael Hanselmann
                      'Instance name')
286 4b62db14 Michael Hanselmann
287 4b62db14 Michael Hanselmann
288 4b62db14 Michael Hanselmann
def ResolveNodeName(node):
289 4b62db14 Michael Hanselmann
  """Gets the full name of a node.
290 4b62db14 Michael Hanselmann

291 4b62db14 Michael Hanselmann
  """
292 4b62db14 Michael Hanselmann
  return _ResolveName(['gnt-node', 'info', node['primary']],
293 4b62db14 Michael Hanselmann
                      'Node name')
294 4b62db14 Michael Hanselmann
295 4b62db14 Michael Hanselmann
296 4b62db14 Michael Hanselmann
def GetNodeInstances(node, secondaries=False):
297 4b62db14 Michael Hanselmann
  """Gets a list of instances on a node.
298 4b62db14 Michael Hanselmann

299 4b62db14 Michael Hanselmann
  """
300 5d640672 Michael Hanselmann
  master = qa_config.GetMasterNode()
301 4b62db14 Michael Hanselmann
  node_name = ResolveNodeName(node)
302 5d640672 Michael Hanselmann
303 4b62db14 Michael Hanselmann
  # Get list of all instances
304 4b62db14 Michael Hanselmann
  cmd = ['gnt-instance', 'list', '--separator=:', '--no-headers',
305 4b62db14 Michael Hanselmann
         '--output=name,pnode,snodes']
306 4b62db14 Michael Hanselmann
  output = GetCommandOutput(master['primary'], utils.ShellQuoteArgs(cmd))
307 4b62db14 Michael Hanselmann
308 4b62db14 Michael Hanselmann
  instances = []
309 4b62db14 Michael Hanselmann
  for line in output.splitlines():
310 4b62db14 Michael Hanselmann
    (name, pnode, snodes) = line.split(':', 2)
311 4b62db14 Michael Hanselmann
    if ((not secondaries and pnode == node_name) or
312 4b62db14 Michael Hanselmann
        (secondaries and node_name in snodes.split(','))):
313 4b62db14 Michael Hanselmann
      instances.append(name)
314 5d640672 Michael Hanselmann
315 4b62db14 Michael Hanselmann
  return instances
316 23269c5b Michael Hanselmann
317 23269c5b Michael Hanselmann
318 288d6440 Michael Hanselmann
def _SelectQueryFields(rnd, fields):
319 288d6440 Michael Hanselmann
  """Generates a list of fields for query tests.
320 288d6440 Michael Hanselmann

321 288d6440 Michael Hanselmann
  """
322 288d6440 Michael Hanselmann
  # Create copy for shuffling
323 288d6440 Michael Hanselmann
  fields = list(fields)
324 288d6440 Michael Hanselmann
  rnd.shuffle(fields)
325 288d6440 Michael Hanselmann
326 288d6440 Michael Hanselmann
  # Check all fields
327 288d6440 Michael Hanselmann
  yield fields
328 288d6440 Michael Hanselmann
  yield sorted(fields)
329 288d6440 Michael Hanselmann
330 288d6440 Michael Hanselmann
  # Duplicate fields
331 288d6440 Michael Hanselmann
  yield fields + fields
332 288d6440 Michael Hanselmann
333 288d6440 Michael Hanselmann
  # Check small groups of fields
334 288d6440 Michael Hanselmann
  while fields:
335 288d6440 Michael Hanselmann
    yield [fields.pop() for _ in range(rnd.randint(2, 10)) if fields]
336 288d6440 Michael Hanselmann
337 288d6440 Michael Hanselmann
338 288d6440 Michael Hanselmann
def _List(listcmd, fields, names):
339 288d6440 Michael Hanselmann
  """Runs a list command.
340 288d6440 Michael Hanselmann

341 288d6440 Michael Hanselmann
  """
342 288d6440 Michael Hanselmann
  master = qa_config.GetMasterNode()
343 288d6440 Michael Hanselmann
344 288d6440 Michael Hanselmann
  cmd = [listcmd, "list", "--separator=|", "--no-header",
345 288d6440 Michael Hanselmann
         "--output", ",".join(fields)]
346 288d6440 Michael Hanselmann
347 288d6440 Michael Hanselmann
  if names:
348 288d6440 Michael Hanselmann
    cmd.extend(names)
349 288d6440 Michael Hanselmann
350 288d6440 Michael Hanselmann
  return GetCommandOutput(master["primary"],
351 288d6440 Michael Hanselmann
                          utils.ShellQuoteArgs(cmd)).splitlines()
352 288d6440 Michael Hanselmann
353 288d6440 Michael Hanselmann
354 288d6440 Michael Hanselmann
def GenericQueryTest(cmd, fields):
355 288d6440 Michael Hanselmann
  """Runs a number of tests on query commands.
356 288d6440 Michael Hanselmann

357 288d6440 Michael Hanselmann
  @param cmd: Command name
358 288d6440 Michael Hanselmann
  @param fields: List of field names
359 288d6440 Michael Hanselmann

360 288d6440 Michael Hanselmann
  """
361 288d6440 Michael Hanselmann
  rnd = random.Random(hash(cmd))
362 288d6440 Michael Hanselmann
363 288d6440 Michael Hanselmann
  randfields = list(fields)
364 288d6440 Michael Hanselmann
  rnd.shuffle(fields)
365 288d6440 Michael Hanselmann
366 288d6440 Michael Hanselmann
  # Test a number of field combinations
367 288d6440 Michael Hanselmann
  for testfields in _SelectQueryFields(rnd, fields):
368 288d6440 Michael Hanselmann
    AssertCommand([cmd, "list", "--output", ",".join(testfields)])
369 288d6440 Michael Hanselmann
370 288d6440 Michael Hanselmann
  namelist_fn = compat.partial(_List, cmd, ["name"])
371 288d6440 Michael Hanselmann
372 288d6440 Michael Hanselmann
  # When no names were requested, the list must be sorted
373 288d6440 Michael Hanselmann
  names = namelist_fn(None)
374 288d6440 Michael Hanselmann
  AssertEqual(names, utils.NiceSort(names))
375 288d6440 Michael Hanselmann
376 288d6440 Michael Hanselmann
  # When requesting specific names, the order must be kept
377 288d6440 Michael Hanselmann
  revnames = list(reversed(names))
378 288d6440 Michael Hanselmann
  AssertEqual(namelist_fn(revnames), revnames)
379 288d6440 Michael Hanselmann
380 288d6440 Michael Hanselmann
  randnames = list(names)
381 288d6440 Michael Hanselmann
  rnd.shuffle(randnames)
382 288d6440 Michael Hanselmann
  AssertEqual(namelist_fn(randnames), randnames)
383 288d6440 Michael Hanselmann
384 2214cf14 Michael Hanselmann
  # Listing unknown items must fail
385 2214cf14 Michael Hanselmann
  AssertCommand([cmd, "list", "this.name.certainly.does.not.exist"], fail=True)
386 2214cf14 Michael Hanselmann
387 2214cf14 Michael Hanselmann
  # Check exit code for listing unknown field
388 2214cf14 Michael Hanselmann
  AssertEqual(AssertCommand([cmd, "list", "--output=field/does/not/exist"],
389 2214cf14 Michael Hanselmann
                            fail=True),
390 2214cf14 Michael Hanselmann
              constants.EXIT_UNKNOWN_FIELD)
391 2214cf14 Michael Hanselmann
392 2214cf14 Michael Hanselmann
393 2214cf14 Michael Hanselmann
def GenericQueryFieldsTest(cmd, fields):
394 2214cf14 Michael Hanselmann
  master = qa_config.GetMasterNode()
395 2214cf14 Michael Hanselmann
396 2214cf14 Michael Hanselmann
  # Listing fields
397 2214cf14 Michael Hanselmann
  AssertCommand([cmd, "list-fields"])
398 2214cf14 Michael Hanselmann
  AssertCommand([cmd, "list-fields"] + fields)
399 2214cf14 Michael Hanselmann
400 2214cf14 Michael Hanselmann
  # Check listed fields (all, must be sorted)
401 2214cf14 Michael Hanselmann
  realcmd = [cmd, "list-fields", "--separator=|", "--no-headers"]
402 2214cf14 Michael Hanselmann
  output = GetCommandOutput(master["primary"],
403 2214cf14 Michael Hanselmann
                            utils.ShellQuoteArgs(realcmd)).splitlines()
404 2214cf14 Michael Hanselmann
  AssertEqual([line.split("|", 1)[0] for line in output],
405 c694367b Michael Hanselmann
              utils.NiceSort(fields))
406 2214cf14 Michael Hanselmann
407 2214cf14 Michael Hanselmann
  # Check exit code for listing unknown field
408 2214cf14 Michael Hanselmann
  AssertEqual(AssertCommand([cmd, "list-fields", "field/does/not/exist"],
409 2214cf14 Michael Hanselmann
                            fail=True),
410 2214cf14 Michael Hanselmann
              constants.EXIT_UNKNOWN_FIELD)
411 2214cf14 Michael Hanselmann
412 288d6440 Michael Hanselmann
413 dfe11bad Michael Hanselmann
def _FormatWithColor(text, seq):
414 dfe11bad Michael Hanselmann
  if not seq:
415 dfe11bad Michael Hanselmann
    return text
416 dfe11bad Michael Hanselmann
  return "%s%s%s" % (seq, text, _RESET_SEQ)
417 23269c5b Michael Hanselmann
418 23269c5b Michael Hanselmann
419 dfe11bad Michael Hanselmann
FormatWarning = lambda text: _FormatWithColor(text, _WARNING_SEQ)
420 dfe11bad Michael Hanselmann
FormatError = lambda text: _FormatWithColor(text, _ERROR_SEQ)
421 dfe11bad Michael Hanselmann
FormatInfo = lambda text: _FormatWithColor(text, _INFO_SEQ)