Statistics
| Branch: | Tag: | Revision:

root / qa / qa_utils.py @ 96a12113

History | View | Annotate | Download (13.4 kB)

1 c68d1f43 Michael Hanselmann
#
2 c68d1f43 Michael Hanselmann
#
3 c68d1f43 Michael Hanselmann
4 f7e6f3c8 Iustin Pop
# Copyright (C) 2007, 2011 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 f7e6f3c8 Iustin Pop
import tempfile
32 cec9845c Michael Hanselmann
33 cec9845c Michael Hanselmann
from ganeti import utils
34 288d6440 Michael Hanselmann
from ganeti import compat
35 2214cf14 Michael Hanselmann
from ganeti import constants
36 cec9845c Michael Hanselmann
37 cec9845c Michael Hanselmann
import qa_config
38 cec9845c Michael Hanselmann
import qa_error
39 cec9845c Michael Hanselmann
40 cec9845c Michael Hanselmann
41 23269c5b Michael Hanselmann
_INFO_SEQ = None
42 23269c5b Michael Hanselmann
_WARNING_SEQ = None
43 23269c5b Michael Hanselmann
_ERROR_SEQ = None
44 23269c5b Michael Hanselmann
_RESET_SEQ = None
45 23269c5b Michael Hanselmann
46 f7e6f3c8 Iustin Pop
_MULTIPLEXERS = {}
47 f7e6f3c8 Iustin Pop
48 23269c5b Michael Hanselmann
49 23269c5b Michael Hanselmann
def _SetupColours():
50 23269c5b Michael Hanselmann
  """Initializes the colour constants.
51 23269c5b Michael Hanselmann

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

83 eaef8a05 Michael Hanselmann
  """
84 eaef8a05 Michael Hanselmann
  if item not in sequence:
85 eaef8a05 Michael Hanselmann
    raise qa_error.Error('%r not in %r' % (item, sequence))
86 eaef8a05 Michael Hanselmann
87 eaef8a05 Michael Hanselmann
88 79eac09b Michael Hanselmann
def AssertNotIn(item, sequence):
89 79eac09b Michael Hanselmann
  """Raises an error when item is in sequence.
90 79eac09b Michael Hanselmann

91 79eac09b Michael Hanselmann
  """
92 79eac09b Michael Hanselmann
  if item in sequence:
93 79eac09b Michael Hanselmann
    raise qa_error.Error('%r in %r' % (item, sequence))
94 79eac09b Michael Hanselmann
95 79eac09b Michael Hanselmann
96 e8ae0c20 Michael Hanselmann
def AssertEqual(first, second):
97 cec9845c Michael Hanselmann
  """Raises an error when values aren't equal.
98 cec9845c Michael Hanselmann

99 cec9845c Michael Hanselmann
  """
100 cec9845c Michael Hanselmann
  if not first == second:
101 e8ae0c20 Michael Hanselmann
    raise qa_error.Error('%r == %r' % (first, second))
102 e8ae0c20 Michael Hanselmann
103 e8ae0c20 Michael Hanselmann
104 e8ae0c20 Michael Hanselmann
def AssertNotEqual(first, second):
105 e8ae0c20 Michael Hanselmann
  """Raises an error when values are equal.
106 e8ae0c20 Michael Hanselmann

107 e8ae0c20 Michael Hanselmann
  """
108 e8ae0c20 Michael Hanselmann
  if not first != second:
109 e8ae0c20 Michael Hanselmann
    raise qa_error.Error('%r != %r' % (first, second))
110 cec9845c Michael Hanselmann
111 cec9845c Michael Hanselmann
112 e6ce18ac René Nussbaumer
def AssertMatch(string, pattern):
113 e6ce18ac René Nussbaumer
  """Raises an error when string doesn't match regexp pattern.
114 e6ce18ac René Nussbaumer

115 e6ce18ac René Nussbaumer
  """
116 e6ce18ac René Nussbaumer
  if not re.match(pattern, string):
117 e6ce18ac René Nussbaumer
    raise qa_error.Error("%r doesn't match /%r/" % (string, pattern))
118 e6ce18ac René Nussbaumer
119 e6ce18ac René Nussbaumer
120 2f4b4f78 Iustin Pop
def AssertCommand(cmd, fail=False, node=None):
121 2f4b4f78 Iustin Pop
  """Checks that a remote command succeeds.
122 2f4b4f78 Iustin Pop

123 2f4b4f78 Iustin Pop
  @param cmd: either a string (the command to execute) or a list (to
124 2f4b4f78 Iustin Pop
      be converted using L{utils.ShellQuoteArgs} into a string)
125 2f4b4f78 Iustin Pop
  @type fail: boolean
126 2f4b4f78 Iustin Pop
  @param fail: if the command is expected to fail instead of succeeding
127 2f4b4f78 Iustin Pop
  @param node: if passed, it should be the node on which the command
128 2f4b4f78 Iustin Pop
      should be executed, instead of the master node (can be either a
129 2f4b4f78 Iustin Pop
      dict or a string)
130 2f4b4f78 Iustin Pop

131 2f4b4f78 Iustin Pop
  """
132 2f4b4f78 Iustin Pop
  if node is None:
133 2f4b4f78 Iustin Pop
    node = qa_config.GetMasterNode()
134 2f4b4f78 Iustin Pop
135 2f4b4f78 Iustin Pop
  if isinstance(node, basestring):
136 2f4b4f78 Iustin Pop
    nodename = node
137 2f4b4f78 Iustin Pop
  else:
138 2f4b4f78 Iustin Pop
    nodename = node["primary"]
139 2f4b4f78 Iustin Pop
140 2f4b4f78 Iustin Pop
  if isinstance(cmd, basestring):
141 2f4b4f78 Iustin Pop
    cmdstr = cmd
142 2f4b4f78 Iustin Pop
  else:
143 2f4b4f78 Iustin Pop
    cmdstr = utils.ShellQuoteArgs(cmd)
144 2f4b4f78 Iustin Pop
145 2f4b4f78 Iustin Pop
  rcode = StartSSH(nodename, cmdstr).wait()
146 2f4b4f78 Iustin Pop
147 2f4b4f78 Iustin Pop
  if fail:
148 2f4b4f78 Iustin Pop
    if rcode == 0:
149 2f4b4f78 Iustin Pop
      raise qa_error.Error("Command '%s' on node %s was expected to fail but"
150 2f4b4f78 Iustin Pop
                           " didn't" % (cmdstr, nodename))
151 2f4b4f78 Iustin Pop
  else:
152 2f4b4f78 Iustin Pop
    if rcode != 0:
153 2f4b4f78 Iustin Pop
      raise qa_error.Error("Command '%s' on node %s failed, exit code %s" %
154 2f4b4f78 Iustin Pop
                           (cmdstr, nodename, rcode))
155 2f4b4f78 Iustin Pop
156 2214cf14 Michael Hanselmann
  return rcode
157 2214cf14 Michael Hanselmann
158 2f4b4f78 Iustin Pop
159 50265802 René Nussbaumer
def GetSSHCommand(node, cmd, strict=True, opts=None, tty=True):
160 cec9845c Michael Hanselmann
  """Builds SSH command to be executed.
161 cec9845c Michael Hanselmann

162 0a05f959 Adeodato Simo
  @type node: string
163 0a05f959 Adeodato Simo
  @param node: node the command should run on
164 0a05f959 Adeodato Simo
  @type cmd: string
165 f7e6f3c8 Iustin Pop
  @param cmd: command to be executed in the node; if None or empty
166 f7e6f3c8 Iustin Pop
      string, no command will be executed
167 0a05f959 Adeodato Simo
  @type strict: boolean
168 0a05f959 Adeodato Simo
  @param strict: whether to enable strict host key checking
169 f7e6f3c8 Iustin Pop
  @type opts: list
170 f7e6f3c8 Iustin Pop
  @param opts: list of additional options
171 50265802 René Nussbaumer
  @type tty: Bool
172 50265802 René Nussbaumer
  @param tty: If we should use tty
173 c68d1f43 Michael Hanselmann

174 cec9845c Michael Hanselmann
  """
175 50265802 René Nussbaumer
  args = ["ssh", "-oEscapeChar=none", "-oBatchMode=yes", "-l", "root"]
176 50265802 René Nussbaumer
177 50265802 René Nussbaumer
  if tty:
178 50265802 René Nussbaumer
    args.append("-t")
179 cec9845c Michael Hanselmann
180 cec9845c Michael Hanselmann
  if strict:
181 cec9845c Michael Hanselmann
    tmp = 'yes'
182 cec9845c Michael Hanselmann
  else:
183 cec9845c Michael Hanselmann
    tmp = 'no'
184 cec9845c Michael Hanselmann
  args.append('-oStrictHostKeyChecking=%s' % tmp)
185 cec9845c Michael Hanselmann
  args.append('-oClearAllForwardings=yes')
186 cec9845c Michael Hanselmann
  args.append('-oForwardAgent=yes')
187 f7e6f3c8 Iustin Pop
  if opts:
188 f7e6f3c8 Iustin Pop
    args.extend(opts)
189 f7e6f3c8 Iustin Pop
  if node in _MULTIPLEXERS:
190 f7e6f3c8 Iustin Pop
    spath = _MULTIPLEXERS[node][0]
191 f7e6f3c8 Iustin Pop
    args.append('-oControlPath=%s' % spath)
192 f7e6f3c8 Iustin Pop
    args.append('-oControlMaster=no')
193 cec9845c Michael Hanselmann
  args.append(node)
194 f7e6f3c8 Iustin Pop
  if cmd:
195 f7e6f3c8 Iustin Pop
    args.append(cmd)
196 cec9845c Michael Hanselmann
197 cec9845c Michael Hanselmann
  return args
198 cec9845c Michael Hanselmann
199 cec9845c Michael Hanselmann
200 5d831182 Michael Hanselmann
def StartLocalCommand(cmd, **kwargs):
201 5d831182 Michael Hanselmann
  """Starts a local command.
202 5d831182 Michael Hanselmann

203 5d831182 Michael Hanselmann
  """
204 5d831182 Michael Hanselmann
  print "Command: %s" % utils.ShellQuoteArgs(cmd)
205 5d831182 Michael Hanselmann
  return subprocess.Popen(cmd, shell=False, **kwargs)
206 5d831182 Michael Hanselmann
207 5d831182 Michael Hanselmann
208 cec9845c Michael Hanselmann
def StartSSH(node, cmd, strict=True):
209 cec9845c Michael Hanselmann
  """Starts SSH.
210 cec9845c Michael Hanselmann

211 cec9845c Michael Hanselmann
  """
212 5d831182 Michael Hanselmann
  return StartLocalCommand(GetSSHCommand(node, cmd, strict=strict))
213 4b62db14 Michael Hanselmann
214 4b62db14 Michael Hanselmann
215 f7e6f3c8 Iustin Pop
def StartMultiplexer(node):
216 f7e6f3c8 Iustin Pop
  """Starts a multiplexer command.
217 f7e6f3c8 Iustin Pop

218 f7e6f3c8 Iustin Pop
  @param node: the node for which to open the multiplexer
219 f7e6f3c8 Iustin Pop

220 f7e6f3c8 Iustin Pop
  """
221 f7e6f3c8 Iustin Pop
  if node in _MULTIPLEXERS:
222 f7e6f3c8 Iustin Pop
    return
223 f7e6f3c8 Iustin Pop
224 f7e6f3c8 Iustin Pop
  # Note: yes, we only need mktemp, since we'll remove the file anyway
225 f7e6f3c8 Iustin Pop
  sname = tempfile.mktemp(prefix="ganeti-qa-multiplexer.")
226 f7e6f3c8 Iustin Pop
  utils.RemoveFile(sname)
227 f7e6f3c8 Iustin Pop
  opts = ["-N", "-oControlPath=%s" % sname, "-oControlMaster=yes"]
228 f7e6f3c8 Iustin Pop
  print "Created socket at %s" % sname
229 f7e6f3c8 Iustin Pop
  child = StartLocalCommand(GetSSHCommand(node, None, opts=opts))
230 f7e6f3c8 Iustin Pop
  _MULTIPLEXERS[node] = (sname, child)
231 f7e6f3c8 Iustin Pop
232 f7e6f3c8 Iustin Pop
233 f7e6f3c8 Iustin Pop
def CloseMultiplexers():
234 f7e6f3c8 Iustin Pop
  """Closes all current multiplexers and cleans up.
235 f7e6f3c8 Iustin Pop

236 f7e6f3c8 Iustin Pop
  """
237 f7e6f3c8 Iustin Pop
  for node in _MULTIPLEXERS.keys():
238 f7e6f3c8 Iustin Pop
    (sname, child) = _MULTIPLEXERS.pop(node)
239 f7e6f3c8 Iustin Pop
    utils.KillProcess(child.pid, timeout=10, waitpid=True)
240 f7e6f3c8 Iustin Pop
    utils.RemoveFile(sname)
241 f7e6f3c8 Iustin Pop
242 f7e6f3c8 Iustin Pop
243 50265802 René Nussbaumer
def GetCommandOutput(node, cmd, tty=True):
244 4b62db14 Michael Hanselmann
  """Returns the output of a command executed on the given node.
245 4b62db14 Michael Hanselmann

246 4b62db14 Michael Hanselmann
  """
247 50265802 René Nussbaumer
  p = StartLocalCommand(GetSSHCommand(node, cmd, tty=tty),
248 50265802 René Nussbaumer
                        stdout=subprocess.PIPE)
249 4b62db14 Michael Hanselmann
  AssertEqual(p.wait(), 0)
250 4b62db14 Michael Hanselmann
  return p.stdout.read()
251 cec9845c Michael Hanselmann
252 cec9845c Michael Hanselmann
253 cec9845c Michael Hanselmann
def UploadFile(node, src):
254 cec9845c Michael Hanselmann
  """Uploads a file to a node and returns the filename.
255 cec9845c Michael Hanselmann

256 cec9845c Michael Hanselmann
  Caller needs to remove the returned file on the node when it's not needed
257 cec9845c Michael Hanselmann
  anymore.
258 49d50e52 Michael Hanselmann

259 cec9845c Michael Hanselmann
  """
260 cec9845c Michael Hanselmann
  # Make sure nobody else has access to it while preserving local permissions
261 cec9845c Michael Hanselmann
  mode = os.stat(src).st_mode & 0700
262 cec9845c Michael Hanselmann
263 cec9845c Michael Hanselmann
  cmd = ('tmp=$(tempfile --mode %o --prefix gnt) && '
264 cec9845c Michael Hanselmann
         '[[ -f "${tmp}" ]] && '
265 cec9845c Michael Hanselmann
         'cat > "${tmp}" && '
266 cec9845c Michael Hanselmann
         'echo "${tmp}"') % mode
267 cec9845c Michael Hanselmann
268 cec9845c Michael Hanselmann
  f = open(src, 'r')
269 cec9845c Michael Hanselmann
  try:
270 cec9845c Michael Hanselmann
    p = subprocess.Popen(GetSSHCommand(node, cmd), shell=False, stdin=f,
271 cec9845c Michael Hanselmann
                         stdout=subprocess.PIPE)
272 cec9845c Michael Hanselmann
    AssertEqual(p.wait(), 0)
273 cec9845c Michael Hanselmann
274 cec9845c Michael Hanselmann
    # Return temporary filename
275 cec9845c Michael Hanselmann
    return p.stdout.read().strip()
276 cec9845c Michael Hanselmann
  finally:
277 cec9845c Michael Hanselmann
    f.close()
278 5d640672 Michael Hanselmann
279 5d640672 Michael Hanselmann
280 b9955569 René Nussbaumer
def UploadData(node, data, mode=0600, filename=None):
281 b9955569 René Nussbaumer
  """Uploads data to a node and returns the filename.
282 b9955569 René Nussbaumer

283 b9955569 René Nussbaumer
  Caller needs to remove the returned file on the node when it's not needed
284 b9955569 René Nussbaumer
  anymore.
285 b9955569 René Nussbaumer

286 b9955569 René Nussbaumer
  """
287 b9955569 René Nussbaumer
  if filename:
288 b9955569 René Nussbaumer
    tmp = "tmp=%s" % utils.ShellQuote(filename)
289 b9955569 René Nussbaumer
  else:
290 b9955569 René Nussbaumer
    tmp = "tmp=$(tempfile --mode %o --prefix gnt)" % mode
291 b9955569 René Nussbaumer
  cmd = ("%s && "
292 b9955569 René Nussbaumer
         "[[ -f \"${tmp}\" ]] && "
293 b9955569 René Nussbaumer
         "cat > \"${tmp}\" && "
294 b9955569 René Nussbaumer
         "echo \"${tmp}\"") % tmp
295 b9955569 René Nussbaumer
296 b9955569 René Nussbaumer
  p = subprocess.Popen(GetSSHCommand(node, cmd), shell=False,
297 b9955569 René Nussbaumer
                       stdin=subprocess.PIPE, stdout=subprocess.PIPE)
298 b9955569 René Nussbaumer
  p.stdin.write(data)
299 b9955569 René Nussbaumer
  p.stdin.close()
300 b9955569 René Nussbaumer
  AssertEqual(p.wait(), 0)
301 b9955569 René Nussbaumer
302 b9955569 René Nussbaumer
  # Return temporary filename
303 b9955569 René Nussbaumer
  return p.stdout.read().strip()
304 b9955569 René Nussbaumer
305 b9955569 René Nussbaumer
306 49d50e52 Michael Hanselmann
def BackupFile(node, path):
307 49d50e52 Michael Hanselmann
  """Creates a backup of a file on the node and returns the filename.
308 49d50e52 Michael Hanselmann

309 49d50e52 Michael Hanselmann
  Caller needs to remove the returned file on the node when it's not needed
310 49d50e52 Michael Hanselmann
  anymore.
311 49d50e52 Michael Hanselmann

312 49d50e52 Michael Hanselmann
  """
313 49d50e52 Michael Hanselmann
  cmd = ("tmp=$(tempfile --prefix .gnt --directory=$(dirname %s)) && "
314 49d50e52 Michael Hanselmann
         "[[ -f \"$tmp\" ]] && "
315 49d50e52 Michael Hanselmann
         "cp %s $tmp && "
316 49d50e52 Michael Hanselmann
         "echo $tmp") % (utils.ShellQuote(path), utils.ShellQuote(path))
317 49d50e52 Michael Hanselmann
318 49d50e52 Michael Hanselmann
  # Return temporary filename
319 49d50e52 Michael Hanselmann
  return GetCommandOutput(node, cmd).strip()
320 49d50e52 Michael Hanselmann
321 49d50e52 Michael Hanselmann
322 4b62db14 Michael Hanselmann
def _ResolveName(cmd, key):
323 4b62db14 Michael Hanselmann
  """Helper function.
324 4b62db14 Michael Hanselmann

325 4b62db14 Michael Hanselmann
  """
326 4b62db14 Michael Hanselmann
  master = qa_config.GetMasterNode()
327 4b62db14 Michael Hanselmann
328 4b62db14 Michael Hanselmann
  output = GetCommandOutput(master['primary'], utils.ShellQuoteArgs(cmd))
329 4b62db14 Michael Hanselmann
  for line in output.splitlines():
330 4b62db14 Michael Hanselmann
    (lkey, lvalue) = line.split(':', 1)
331 4b62db14 Michael Hanselmann
    if lkey == key:
332 4b62db14 Michael Hanselmann
      return lvalue.lstrip()
333 4b62db14 Michael Hanselmann
  raise KeyError("Key not found")
334 4b62db14 Michael Hanselmann
335 4b62db14 Michael Hanselmann
336 5d640672 Michael Hanselmann
def ResolveInstanceName(instance):
337 5d640672 Michael Hanselmann
  """Gets the full name of an instance.
338 5d640672 Michael Hanselmann

339 46f9a948 Michael Hanselmann
  @type instance: string
340 46f9a948 Michael Hanselmann
  @param instance: Instance name
341 46f9a948 Michael Hanselmann

342 5d640672 Michael Hanselmann
  """
343 46f9a948 Michael Hanselmann
  return _ResolveName(['gnt-instance', 'info', instance],
344 4b62db14 Michael Hanselmann
                      'Instance name')
345 4b62db14 Michael Hanselmann
346 4b62db14 Michael Hanselmann
347 4b62db14 Michael Hanselmann
def ResolveNodeName(node):
348 4b62db14 Michael Hanselmann
  """Gets the full name of a node.
349 4b62db14 Michael Hanselmann

350 4b62db14 Michael Hanselmann
  """
351 4b62db14 Michael Hanselmann
  return _ResolveName(['gnt-node', 'info', node['primary']],
352 4b62db14 Michael Hanselmann
                      'Node name')
353 4b62db14 Michael Hanselmann
354 4b62db14 Michael Hanselmann
355 4b62db14 Michael Hanselmann
def GetNodeInstances(node, secondaries=False):
356 4b62db14 Michael Hanselmann
  """Gets a list of instances on a node.
357 4b62db14 Michael Hanselmann

358 4b62db14 Michael Hanselmann
  """
359 5d640672 Michael Hanselmann
  master = qa_config.GetMasterNode()
360 4b62db14 Michael Hanselmann
  node_name = ResolveNodeName(node)
361 5d640672 Michael Hanselmann
362 4b62db14 Michael Hanselmann
  # Get list of all instances
363 4b62db14 Michael Hanselmann
  cmd = ['gnt-instance', 'list', '--separator=:', '--no-headers',
364 4b62db14 Michael Hanselmann
         '--output=name,pnode,snodes']
365 4b62db14 Michael Hanselmann
  output = GetCommandOutput(master['primary'], utils.ShellQuoteArgs(cmd))
366 4b62db14 Michael Hanselmann
367 4b62db14 Michael Hanselmann
  instances = []
368 4b62db14 Michael Hanselmann
  for line in output.splitlines():
369 4b62db14 Michael Hanselmann
    (name, pnode, snodes) = line.split(':', 2)
370 4b62db14 Michael Hanselmann
    if ((not secondaries and pnode == node_name) or
371 4b62db14 Michael Hanselmann
        (secondaries and node_name in snodes.split(','))):
372 4b62db14 Michael Hanselmann
      instances.append(name)
373 5d640672 Michael Hanselmann
374 4b62db14 Michael Hanselmann
  return instances
375 23269c5b Michael Hanselmann
376 23269c5b Michael Hanselmann
377 288d6440 Michael Hanselmann
def _SelectQueryFields(rnd, fields):
378 288d6440 Michael Hanselmann
  """Generates a list of fields for query tests.
379 288d6440 Michael Hanselmann

380 288d6440 Michael Hanselmann
  """
381 288d6440 Michael Hanselmann
  # Create copy for shuffling
382 288d6440 Michael Hanselmann
  fields = list(fields)
383 288d6440 Michael Hanselmann
  rnd.shuffle(fields)
384 288d6440 Michael Hanselmann
385 288d6440 Michael Hanselmann
  # Check all fields
386 288d6440 Michael Hanselmann
  yield fields
387 288d6440 Michael Hanselmann
  yield sorted(fields)
388 288d6440 Michael Hanselmann
389 288d6440 Michael Hanselmann
  # Duplicate fields
390 288d6440 Michael Hanselmann
  yield fields + fields
391 288d6440 Michael Hanselmann
392 288d6440 Michael Hanselmann
  # Check small groups of fields
393 288d6440 Michael Hanselmann
  while fields:
394 288d6440 Michael Hanselmann
    yield [fields.pop() for _ in range(rnd.randint(2, 10)) if fields]
395 288d6440 Michael Hanselmann
396 288d6440 Michael Hanselmann
397 288d6440 Michael Hanselmann
def _List(listcmd, fields, names):
398 288d6440 Michael Hanselmann
  """Runs a list command.
399 288d6440 Michael Hanselmann

400 288d6440 Michael Hanselmann
  """
401 288d6440 Michael Hanselmann
  master = qa_config.GetMasterNode()
402 288d6440 Michael Hanselmann
403 288d6440 Michael Hanselmann
  cmd = [listcmd, "list", "--separator=|", "--no-header",
404 288d6440 Michael Hanselmann
         "--output", ",".join(fields)]
405 288d6440 Michael Hanselmann
406 288d6440 Michael Hanselmann
  if names:
407 288d6440 Michael Hanselmann
    cmd.extend(names)
408 288d6440 Michael Hanselmann
409 288d6440 Michael Hanselmann
  return GetCommandOutput(master["primary"],
410 288d6440 Michael Hanselmann
                          utils.ShellQuoteArgs(cmd)).splitlines()
411 288d6440 Michael Hanselmann
412 288d6440 Michael Hanselmann
413 288d6440 Michael Hanselmann
def GenericQueryTest(cmd, fields):
414 288d6440 Michael Hanselmann
  """Runs a number of tests on query commands.
415 288d6440 Michael Hanselmann

416 288d6440 Michael Hanselmann
  @param cmd: Command name
417 288d6440 Michael Hanselmann
  @param fields: List of field names
418 288d6440 Michael Hanselmann

419 288d6440 Michael Hanselmann
  """
420 288d6440 Michael Hanselmann
  rnd = random.Random(hash(cmd))
421 288d6440 Michael Hanselmann
422 3582eef6 Iustin Pop
  fields = list(fields)
423 288d6440 Michael Hanselmann
  rnd.shuffle(fields)
424 288d6440 Michael Hanselmann
425 288d6440 Michael Hanselmann
  # Test a number of field combinations
426 288d6440 Michael Hanselmann
  for testfields in _SelectQueryFields(rnd, fields):
427 288d6440 Michael Hanselmann
    AssertCommand([cmd, "list", "--output", ",".join(testfields)])
428 288d6440 Michael Hanselmann
429 288d6440 Michael Hanselmann
  namelist_fn = compat.partial(_List, cmd, ["name"])
430 288d6440 Michael Hanselmann
431 288d6440 Michael Hanselmann
  # When no names were requested, the list must be sorted
432 288d6440 Michael Hanselmann
  names = namelist_fn(None)
433 288d6440 Michael Hanselmann
  AssertEqual(names, utils.NiceSort(names))
434 288d6440 Michael Hanselmann
435 288d6440 Michael Hanselmann
  # When requesting specific names, the order must be kept
436 288d6440 Michael Hanselmann
  revnames = list(reversed(names))
437 288d6440 Michael Hanselmann
  AssertEqual(namelist_fn(revnames), revnames)
438 288d6440 Michael Hanselmann
439 288d6440 Michael Hanselmann
  randnames = list(names)
440 288d6440 Michael Hanselmann
  rnd.shuffle(randnames)
441 288d6440 Michael Hanselmann
  AssertEqual(namelist_fn(randnames), randnames)
442 288d6440 Michael Hanselmann
443 2214cf14 Michael Hanselmann
  # Listing unknown items must fail
444 2214cf14 Michael Hanselmann
  AssertCommand([cmd, "list", "this.name.certainly.does.not.exist"], fail=True)
445 2214cf14 Michael Hanselmann
446 2214cf14 Michael Hanselmann
  # Check exit code for listing unknown field
447 2214cf14 Michael Hanselmann
  AssertEqual(AssertCommand([cmd, "list", "--output=field/does/not/exist"],
448 2214cf14 Michael Hanselmann
                            fail=True),
449 2214cf14 Michael Hanselmann
              constants.EXIT_UNKNOWN_FIELD)
450 2214cf14 Michael Hanselmann
451 2214cf14 Michael Hanselmann
452 2214cf14 Michael Hanselmann
def GenericQueryFieldsTest(cmd, fields):
453 2214cf14 Michael Hanselmann
  master = qa_config.GetMasterNode()
454 2214cf14 Michael Hanselmann
455 2214cf14 Michael Hanselmann
  # Listing fields
456 2214cf14 Michael Hanselmann
  AssertCommand([cmd, "list-fields"])
457 2214cf14 Michael Hanselmann
  AssertCommand([cmd, "list-fields"] + fields)
458 2214cf14 Michael Hanselmann
459 2214cf14 Michael Hanselmann
  # Check listed fields (all, must be sorted)
460 2214cf14 Michael Hanselmann
  realcmd = [cmd, "list-fields", "--separator=|", "--no-headers"]
461 2214cf14 Michael Hanselmann
  output = GetCommandOutput(master["primary"],
462 2214cf14 Michael Hanselmann
                            utils.ShellQuoteArgs(realcmd)).splitlines()
463 2214cf14 Michael Hanselmann
  AssertEqual([line.split("|", 1)[0] for line in output],
464 c694367b Michael Hanselmann
              utils.NiceSort(fields))
465 2214cf14 Michael Hanselmann
466 2214cf14 Michael Hanselmann
  # Check exit code for listing unknown field
467 2214cf14 Michael Hanselmann
  AssertEqual(AssertCommand([cmd, "list-fields", "field/does/not/exist"],
468 2214cf14 Michael Hanselmann
                            fail=True),
469 2214cf14 Michael Hanselmann
              constants.EXIT_UNKNOWN_FIELD)
470 2214cf14 Michael Hanselmann
471 288d6440 Michael Hanselmann
472 dfe11bad Michael Hanselmann
def _FormatWithColor(text, seq):
473 dfe11bad Michael Hanselmann
  if not seq:
474 dfe11bad Michael Hanselmann
    return text
475 dfe11bad Michael Hanselmann
  return "%s%s%s" % (seq, text, _RESET_SEQ)
476 23269c5b Michael Hanselmann
477 23269c5b Michael Hanselmann
478 dfe11bad Michael Hanselmann
FormatWarning = lambda text: _FormatWithColor(text, _WARNING_SEQ)
479 dfe11bad Michael Hanselmann
FormatError = lambda text: _FormatWithColor(text, _ERROR_SEQ)
480 dfe11bad Michael Hanselmann
FormatInfo = lambda text: _FormatWithColor(text, _INFO_SEQ)
481 31fe5102 René Nussbaumer
482 31fe5102 René Nussbaumer
483 31fe5102 René Nussbaumer
def AddToEtcHosts(hostnames):
484 31fe5102 René Nussbaumer
  """Adds hostnames to /etc/hosts.
485 31fe5102 René Nussbaumer

486 31fe5102 René Nussbaumer
  @param hostnames: List of hostnames first used A records, all other CNAMEs
487 31fe5102 René Nussbaumer

488 31fe5102 René Nussbaumer
  """
489 31fe5102 René Nussbaumer
  master = qa_config.GetMasterNode()
490 31fe5102 René Nussbaumer
  tmp_hosts = UploadData(master["primary"], "", mode=0644)
491 31fe5102 René Nussbaumer
492 31fe5102 René Nussbaumer
  quoted_tmp_hosts = utils.ShellQuote(tmp_hosts)
493 31fe5102 René Nussbaumer
  data = []
494 31fe5102 René Nussbaumer
  for localhost in ("::1", "127.0.0.1"):
495 31fe5102 René Nussbaumer
    data.append("%s %s" % (localhost, " ".join(hostnames)))
496 31fe5102 René Nussbaumer
497 31fe5102 René Nussbaumer
  try:
498 31fe5102 René Nussbaumer
    AssertCommand(("cat /etc/hosts > %s && echo -e '%s' >> %s && mv %s"
499 31fe5102 René Nussbaumer
                   " /etc/hosts") % (quoted_tmp_hosts, "\\n".join(data),
500 31fe5102 René Nussbaumer
                                     quoted_tmp_hosts, quoted_tmp_hosts))
501 31fe5102 René Nussbaumer
  except qa_error.Error:
502 31fe5102 René Nussbaumer
    AssertCommand(["rm", tmp_hosts])
503 31fe5102 René Nussbaumer
504 31fe5102 René Nussbaumer
505 31fe5102 René Nussbaumer
def RemoveFromEtcHosts(hostnames):
506 31fe5102 René Nussbaumer
  """Remove hostnames from /etc/hosts.
507 31fe5102 René Nussbaumer

508 31fe5102 René Nussbaumer
  @param hostnames: List of hostnames first used A records, all other CNAMEs
509 31fe5102 René Nussbaumer

510 31fe5102 René Nussbaumer
  """
511 31fe5102 René Nussbaumer
  master = qa_config.GetMasterNode()
512 31fe5102 René Nussbaumer
  tmp_hosts = UploadData(master["primary"], "", mode=0644)
513 31fe5102 René Nussbaumer
  quoted_tmp_hosts = utils.ShellQuote(tmp_hosts)
514 31fe5102 René Nussbaumer
515 31fe5102 René Nussbaumer
  sed_data = " ".join(hostnames)
516 31fe5102 René Nussbaumer
  try:
517 31fe5102 René Nussbaumer
    AssertCommand(("sed -e '/^\(::1\|127\.0\.0\.1\)\s\+%s/d' /etc/hosts > %s"
518 31fe5102 René Nussbaumer
                   " && mv %s /etc/hosts") % (sed_data, quoted_tmp_hosts,
519 31fe5102 René Nussbaumer
                                              quoted_tmp_hosts))
520 31fe5102 René Nussbaumer
  except qa_error.Error:
521 31fe5102 René Nussbaumer
    AssertCommand(["rm", tmp_hosts])