Statistics
| Branch: | Tag: | Revision:

root / qa / qa_cluster.py @ 33c730a2

History | View | Annotate | Download (28.4 kB)

1 c68d1f43 Michael Hanselmann
#
2 c68d1f43 Michael Hanselmann
#
3 c68d1f43 Michael Hanselmann
4 587f8ff6 Bernardo Dal Seno
# Copyright (C) 2007, 2010, 2011, 2012, 2013 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
"""Cluster related QA tests.
23 cec9845c Michael Hanselmann

24 cec9845c Michael Hanselmann
"""
25 cec9845c Michael Hanselmann
26 587f8ff6 Bernardo Dal Seno
import re
27 cec9845c Michael Hanselmann
import tempfile
28 49ceab21 Michael Hanselmann
import os.path
29 cec9845c Michael Hanselmann
30 6d4a1656 Michael Hanselmann
from ganeti import constants
31 66d1f035 René Nussbaumer
from ganeti import compat
32 cec9845c Michael Hanselmann
from ganeti import utils
33 304d9f02 Michael Hanselmann
from ganeti import pathutils
34 cec9845c Michael Hanselmann
35 cec9845c Michael Hanselmann
import qa_config
36 cec9845c Michael Hanselmann
import qa_utils
37 cec9845c Michael Hanselmann
import qa_error
38 cec9845c Michael Hanselmann
39 66d1f035 René Nussbaumer
from qa_utils import AssertEqual, AssertCommand, GetCommandOutput
40 cec9845c Michael Hanselmann
41 cec9845c Michael Hanselmann
42 23610ff8 Bernardo Dal Seno
# Prefix for LVM volumes created by QA code during tests
43 23610ff8 Bernardo Dal Seno
_QA_LV_PREFIX = "qa-"
44 23610ff8 Bernardo Dal Seno
45 c2a0947d Iustin Pop
#: cluster verify command
46 c2a0947d Iustin Pop
_CLUSTER_VERIFY = ["gnt-cluster", "verify"]
47 c2a0947d Iustin Pop
48 21bf2e2e Andrea Spadaccini
49 830da270 Michael Hanselmann
def _RemoveFileFromAllNodes(filename):
50 830da270 Michael Hanselmann
  """Removes a file from all nodes.
51 830da270 Michael Hanselmann

52 830da270 Michael Hanselmann
  """
53 2f4b4f78 Iustin Pop
  for node in qa_config.get("nodes"):
54 2f4b4f78 Iustin Pop
    AssertCommand(["rm", "-f", filename], node=node)
55 830da270 Michael Hanselmann
56 830da270 Michael Hanselmann
57 830da270 Michael Hanselmann
def _CheckFileOnAllNodes(filename, content):
58 830da270 Michael Hanselmann
  """Verifies the content of the given file on all nodes.
59 830da270 Michael Hanselmann

60 830da270 Michael Hanselmann
  """
61 830da270 Michael Hanselmann
  cmd = utils.ShellQuoteArgs(["cat", filename])
62 2f4b4f78 Iustin Pop
  for node in qa_config.get("nodes"):
63 aecba21e Michael Hanselmann
    AssertEqual(qa_utils.GetCommandOutput(node.primary, cmd), content)
64 830da270 Michael Hanselmann
65 830da270 Michael Hanselmann
66 17cfeee9 Bernardo Dal Seno
# "gnt-cluster info" fields
67 17cfeee9 Bernardo Dal Seno
_CIFIELD_RE = re.compile(r"^[-\s]*(?P<field>[^\s:]+):\s*(?P<value>\S.*)$")
68 17cfeee9 Bernardo Dal Seno
69 17cfeee9 Bernardo Dal Seno
70 17cfeee9 Bernardo Dal Seno
def _GetBoolClusterField(field):
71 17cfeee9 Bernardo Dal Seno
  """Get the Boolean value of a cluster field.
72 17cfeee9 Bernardo Dal Seno

73 17cfeee9 Bernardo Dal Seno
  This function currently assumes that the field name is unique in the cluster
74 17cfeee9 Bernardo Dal Seno
  configuration. An assertion checks this assumption.
75 17cfeee9 Bernardo Dal Seno

76 17cfeee9 Bernardo Dal Seno
  @type field: string
77 17cfeee9 Bernardo Dal Seno
  @param field: Name of the field
78 17cfeee9 Bernardo Dal Seno
  @rtype: bool
79 17cfeee9 Bernardo Dal Seno
  @return: The effective value of the field
80 17cfeee9 Bernardo Dal Seno

81 17cfeee9 Bernardo Dal Seno
  """
82 17cfeee9 Bernardo Dal Seno
  master = qa_config.GetMasterNode()
83 17cfeee9 Bernardo Dal Seno
  infocmd = "gnt-cluster info"
84 aecba21e Michael Hanselmann
  info_out = qa_utils.GetCommandOutput(master.primary, infocmd)
85 17cfeee9 Bernardo Dal Seno
  ret = None
86 17cfeee9 Bernardo Dal Seno
  for l in info_out.splitlines():
87 17cfeee9 Bernardo Dal Seno
    m = _CIFIELD_RE.match(l)
88 17cfeee9 Bernardo Dal Seno
    # FIXME: There should be a way to specify a field through a hierarchy
89 17cfeee9 Bernardo Dal Seno
    if m and m.group("field") == field:
90 17cfeee9 Bernardo Dal Seno
      # Make sure that ignoring the hierarchy doesn't cause a double match
91 17cfeee9 Bernardo Dal Seno
      assert ret is None
92 17cfeee9 Bernardo Dal Seno
      ret = (m.group("value").lower() == "true")
93 17cfeee9 Bernardo Dal Seno
  if ret is not None:
94 17cfeee9 Bernardo Dal Seno
    return ret
95 17cfeee9 Bernardo Dal Seno
  raise qa_error.Error("Field not found in cluster configuration: %s" % field)
96 17cfeee9 Bernardo Dal Seno
97 17cfeee9 Bernardo Dal Seno
98 587f8ff6 Bernardo Dal Seno
# Cluster-verify errors (date, "ERROR", then error code)
99 ab4832d1 Bernardo Dal Seno
_CVERROR_RE = re.compile(r"^[\w\s:]+\s+- (ERROR|WARNING):([A-Z0-9_-]+):")
100 587f8ff6 Bernardo Dal Seno
101 587f8ff6 Bernardo Dal Seno
102 587f8ff6 Bernardo Dal Seno
def _GetCVErrorCodes(cvout):
103 ab4832d1 Bernardo Dal Seno
  errs = set()
104 ab4832d1 Bernardo Dal Seno
  warns = set()
105 587f8ff6 Bernardo Dal Seno
  for l in cvout.splitlines():
106 587f8ff6 Bernardo Dal Seno
    m = _CVERROR_RE.match(l)
107 587f8ff6 Bernardo Dal Seno
    if m:
108 ab4832d1 Bernardo Dal Seno
      etype = m.group(1)
109 ab4832d1 Bernardo Dal Seno
      ecode = m.group(2)
110 ab4832d1 Bernardo Dal Seno
      if etype == "ERROR":
111 ab4832d1 Bernardo Dal Seno
        errs.add(ecode)
112 ab4832d1 Bernardo Dal Seno
      elif etype == "WARNING":
113 ab4832d1 Bernardo Dal Seno
        warns.add(ecode)
114 ab4832d1 Bernardo Dal Seno
  return (errs, warns)
115 587f8ff6 Bernardo Dal Seno
116 587f8ff6 Bernardo Dal Seno
117 ab4832d1 Bernardo Dal Seno
def _CheckVerifyErrors(actual, expected, etype):
118 ab4832d1 Bernardo Dal Seno
  exp_codes = compat.UniqueFrozenset(e for (_, e, _) in expected)
119 ab4832d1 Bernardo Dal Seno
  if not actual.issuperset(exp_codes):
120 ab4832d1 Bernardo Dal Seno
    missing = exp_codes.difference(actual)
121 ab4832d1 Bernardo Dal Seno
    raise qa_error.Error("Cluster-verify didn't return these expected"
122 ab4832d1 Bernardo Dal Seno
                         " %ss: %s" % (etype, utils.CommaJoin(missing)))
123 ab4832d1 Bernardo Dal Seno
124 ab4832d1 Bernardo Dal Seno
125 ab4832d1 Bernardo Dal Seno
def AssertClusterVerify(fail=False, errors=None, warnings=None):
126 587f8ff6 Bernardo Dal Seno
  """Run cluster-verify and check the result
127 587f8ff6 Bernardo Dal Seno

128 587f8ff6 Bernardo Dal Seno
  @type fail: bool
129 587f8ff6 Bernardo Dal Seno
  @param fail: if cluster-verify is expected to fail instead of succeeding
130 587f8ff6 Bernardo Dal Seno
  @type errors: list of tuples
131 587f8ff6 Bernardo Dal Seno
  @param errors: List of CV_XXX errors that are expected; if specified, all the
132 587f8ff6 Bernardo Dal Seno
      errors listed must appear in cluster-verify output. A non-empty value
133 587f8ff6 Bernardo Dal Seno
      implies C{fail=True}.
134 ab4832d1 Bernardo Dal Seno
  @type warnings: list of tuples
135 ab4832d1 Bernardo Dal Seno
  @param warnings: Same as C{errors} but for warnings.
136 587f8ff6 Bernardo Dal Seno

137 587f8ff6 Bernardo Dal Seno
  """
138 587f8ff6 Bernardo Dal Seno
  cvcmd = "gnt-cluster verify"
139 587f8ff6 Bernardo Dal Seno
  mnode = qa_config.GetMasterNode()
140 ab4832d1 Bernardo Dal Seno
  if errors or warnings:
141 aecba21e Michael Hanselmann
    cvout = GetCommandOutput(mnode.primary, cvcmd + " --error-codes",
142 ab4832d1 Bernardo Dal Seno
                             fail=(fail or errors))
143 ab4832d1 Bernardo Dal Seno
    (act_errs, act_warns) = _GetCVErrorCodes(cvout)
144 ab4832d1 Bernardo Dal Seno
    if errors:
145 ab4832d1 Bernardo Dal Seno
      _CheckVerifyErrors(act_errs, errors, "error")
146 ab4832d1 Bernardo Dal Seno
    if warnings:
147 ab4832d1 Bernardo Dal Seno
      _CheckVerifyErrors(act_warns, warnings, "warning")
148 587f8ff6 Bernardo Dal Seno
  else:
149 587f8ff6 Bernardo Dal Seno
    AssertCommand(cvcmd, fail=fail, node=mnode)
150 587f8ff6 Bernardo Dal Seno
151 587f8ff6 Bernardo Dal Seno
152 92cb4940 Andrea Spadaccini
# data for testing failures due to bad keys/values for disk parameters
153 92cb4940 Andrea Spadaccini
_FAIL_PARAMS = ["nonexistent:resync-rate=1",
154 92cb4940 Andrea Spadaccini
                "drbd:nonexistent=1",
155 92cb4940 Andrea Spadaccini
                "drbd:resync-rate=invalid",
156 92cb4940 Andrea Spadaccini
                ]
157 92cb4940 Andrea Spadaccini
158 92cb4940 Andrea Spadaccini
159 92cb4940 Andrea Spadaccini
def TestClusterInitDisk():
160 92cb4940 Andrea Spadaccini
  """gnt-cluster init -D"""
161 92cb4940 Andrea Spadaccini
  name = qa_config.get("name")
162 92cb4940 Andrea Spadaccini
  for param in _FAIL_PARAMS:
163 92cb4940 Andrea Spadaccini
    AssertCommand(["gnt-cluster", "init", "-D", param, name], fail=True)
164 92cb4940 Andrea Spadaccini
165 92cb4940 Andrea Spadaccini
166 725ec2f1 René Nussbaumer
def TestClusterInit(rapi_user, rapi_secret):
167 cec9845c Michael Hanselmann
  """gnt-cluster init"""
168 cec9845c Michael Hanselmann
  master = qa_config.GetMasterNode()
169 cec9845c Michael Hanselmann
170 734fd6b4 Michael Hanselmann
  rapi_users_path = qa_utils.MakeNodePath(master, pathutils.RAPI_USERS_FILE)
171 734fd6b4 Michael Hanselmann
  rapi_dir = os.path.dirname(rapi_users_path)
172 49ceab21 Michael Hanselmann
173 725ec2f1 René Nussbaumer
  # First create the RAPI credentials
174 a62d1901 Michael Hanselmann
  fh = tempfile.NamedTemporaryFile()
175 a62d1901 Michael Hanselmann
  try:
176 a62d1901 Michael Hanselmann
    fh.write("%s %s write\n" % (rapi_user, rapi_secret))
177 a62d1901 Michael Hanselmann
    fh.flush()
178 a62d1901 Michael Hanselmann
179 aecba21e Michael Hanselmann
    tmpru = qa_utils.UploadFile(master.primary, fh.name)
180 a62d1901 Michael Hanselmann
    try:
181 49ceab21 Michael Hanselmann
      AssertCommand(["mkdir", "-p", rapi_dir])
182 734fd6b4 Michael Hanselmann
      AssertCommand(["mv", tmpru, rapi_users_path])
183 a62d1901 Michael Hanselmann
    finally:
184 2f4b4f78 Iustin Pop
      AssertCommand(["rm", "-f", tmpru])
185 a62d1901 Michael Hanselmann
  finally:
186 a62d1901 Michael Hanselmann
    fh.close()
187 a62d1901 Michael Hanselmann
188 a62d1901 Michael Hanselmann
  # Initialize cluster
189 e7b6183b Michael Hanselmann
  cmd = [
190 e7b6183b Michael Hanselmann
    "gnt-cluster", "init",
191 e7b6183b Michael Hanselmann
    "--primary-ip-version=%d" % qa_config.get("primary_ip_version", 4),
192 59c1d41e Michael Hanselmann
    "--enabled-hypervisors=%s" % ",".join(qa_config.GetEnabledHypervisors()),
193 e7b6183b Michael Hanselmann
    ]
194 20286f7c René Nussbaumer
195 20286f7c René Nussbaumer
  for spec_type in ("mem-size", "disk-size", "disk-count", "cpu-count",
196 20286f7c René Nussbaumer
                    "nic-count"):
197 20286f7c René Nussbaumer
    for spec_val in ("min", "max", "std"):
198 20286f7c René Nussbaumer
      spec = qa_config.get("ispec_%s_%s" %
199 3601d488 Michael Hanselmann
                           (spec_type.replace("-", "_"), spec_val), None)
200 00650761 Michael Hanselmann
      if spec is not None:
201 20286f7c René Nussbaumer
        cmd.append("--specs-%s=%s=%d" % (spec_type, spec_val, spec))
202 9486f6ae Manuel Franceschini
203 aecba21e Michael Hanselmann
  if master.secondary:
204 aecba21e Michael Hanselmann
    cmd.append("--secondary-ip=%s" % master.secondary)
205 cec9845c Michael Hanselmann
206 23610ff8 Bernardo Dal Seno
  vgname = qa_config.get("vg-name", None)
207 23610ff8 Bernardo Dal Seno
  if vgname:
208 23610ff8 Bernardo Dal Seno
    cmd.append("--vg-name=%s" % vgname)
209 23610ff8 Bernardo Dal Seno
210 3601d488 Michael Hanselmann
  master_netdev = qa_config.get("master-netdev", None)
211 3601d488 Michael Hanselmann
  if master_netdev:
212 3601d488 Michael Hanselmann
    cmd.append("--master-netdev=%s" % master_netdev)
213 3601d488 Michael Hanselmann
214 3601d488 Michael Hanselmann
  nicparams = qa_config.get("default-nicparams", None)
215 3601d488 Michael Hanselmann
  if nicparams:
216 3601d488 Michael Hanselmann
    cmd.append("--nic-parameters=%s" %
217 3601d488 Michael Hanselmann
               ",".join(utils.FormatKeyValue(nicparams)))
218 cec9845c Michael Hanselmann
219 6a0f22e1 Bernardo Dal Seno
  # Cluster value of the exclusive-storage node parameter
220 6a0f22e1 Bernardo Dal Seno
  e_s = qa_config.get("exclusive-storage")
221 6a0f22e1 Bernardo Dal Seno
  if e_s is not None:
222 6a0f22e1 Bernardo Dal Seno
    cmd.extend(["--node-parameters", "exclusive_storage=%s" % e_s])
223 6a0f22e1 Bernardo Dal Seno
  else:
224 6a0f22e1 Bernardo Dal Seno
    e_s = False
225 6a0f22e1 Bernardo Dal Seno
  qa_config.SetExclusiveStorage(e_s)
226 6a0f22e1 Bernardo Dal Seno
227 becf9d5c Michael Hanselmann
  extra_args = qa_config.get("cluster-init-args")
228 becf9d5c Michael Hanselmann
  if extra_args:
229 becf9d5c Michael Hanselmann
    cmd.extend(extra_args)
230 becf9d5c Michael Hanselmann
231 13d2e231 Andrea Spadaccini
  cmd.append(qa_config.get("name"))
232 becf9d5c Michael Hanselmann
233 2f4b4f78 Iustin Pop
  AssertCommand(cmd)
234 cec9845c Michael Hanselmann
235 5abecc1c Iustin Pop
  cmd = ["gnt-cluster", "modify"]
236 13d2e231 Andrea Spadaccini
237 5abecc1c Iustin Pop
  # hypervisor parameter modifications
238 5abecc1c Iustin Pop
  hvp = qa_config.get("hypervisor-parameters", {})
239 5abecc1c Iustin Pop
  for k, v in hvp.items():
240 5abecc1c Iustin Pop
    cmd.extend(["-H", "%s:%s" % (k, v)])
241 5abecc1c Iustin Pop
  # backend parameter modifications
242 5abecc1c Iustin Pop
  bep = qa_config.get("backend-parameters", "")
243 5abecc1c Iustin Pop
  if bep:
244 5abecc1c Iustin Pop
    cmd.extend(["-B", bep])
245 5abecc1c Iustin Pop
246 5abecc1c Iustin Pop
  if len(cmd) > 2:
247 5abecc1c Iustin Pop
    AssertCommand(cmd)
248 5abecc1c Iustin Pop
249 5abecc1c Iustin Pop
  # OS parameters
250 5abecc1c Iustin Pop
  osp = qa_config.get("os-parameters", {})
251 5abecc1c Iustin Pop
  for k, v in osp.items():
252 5abecc1c Iustin Pop
    AssertCommand(["gnt-os", "modify", "-O", v, k])
253 5abecc1c Iustin Pop
254 5abecc1c Iustin Pop
  # OS hypervisor parameters
255 5abecc1c Iustin Pop
  os_hvp = qa_config.get("os-hvp", {})
256 5abecc1c Iustin Pop
  for os_name in os_hvp:
257 5abecc1c Iustin Pop
    for hv, hvp in os_hvp[os_name].items():
258 5abecc1c Iustin Pop
      AssertCommand(["gnt-os", "modify", "-H", "%s:%s" % (hv, hvp), os_name])
259 5abecc1c Iustin Pop
260 cec9845c Michael Hanselmann
261 caea3b32 Iustin Pop
def TestClusterRename():
262 caea3b32 Iustin Pop
  """gnt-cluster rename"""
263 d0c8c01d Iustin Pop
  cmd = ["gnt-cluster", "rename", "-f"]
264 caea3b32 Iustin Pop
265 d0c8c01d Iustin Pop
  original_name = qa_config.get("name")
266 d0c8c01d Iustin Pop
  rename_target = qa_config.get("rename", None)
267 caea3b32 Iustin Pop
  if rename_target is None:
268 caea3b32 Iustin Pop
    print qa_utils.FormatError('"rename" entry is missing')
269 caea3b32 Iustin Pop
    return
270 caea3b32 Iustin Pop
271 2f4b4f78 Iustin Pop
  for data in [
272 2f4b4f78 Iustin Pop
    cmd + [rename_target],
273 c2a0947d Iustin Pop
    _CLUSTER_VERIFY,
274 2f4b4f78 Iustin Pop
    cmd + [original_name],
275 c2a0947d Iustin Pop
    _CLUSTER_VERIFY,
276 2f4b4f78 Iustin Pop
    ]:
277 2f4b4f78 Iustin Pop
    AssertCommand(data)
278 caea3b32 Iustin Pop
279 caea3b32 Iustin Pop
280 69df9d2b Iustin Pop
def TestClusterOob():
281 69df9d2b Iustin Pop
  """out-of-band framework"""
282 f55312bd René Nussbaumer
  oob_path_exists = "/tmp/ganeti-qa-oob-does-exist-%s" % utils.NewUUID()
283 f55312bd René Nussbaumer
284 c2a0947d Iustin Pop
  AssertCommand(_CLUSTER_VERIFY)
285 f55312bd René Nussbaumer
  AssertCommand(["gnt-cluster", "modify", "--node-parameters",
286 f55312bd René Nussbaumer
                 "oob_program=/tmp/ganeti-qa-oob-does-not-exist-%s" %
287 f55312bd René Nussbaumer
                 utils.NewUUID()])
288 f55312bd René Nussbaumer
289 c2a0947d Iustin Pop
  AssertCommand(_CLUSTER_VERIFY, fail=True)
290 f55312bd René Nussbaumer
291 69df9d2b Iustin Pop
  AssertCommand(["touch", oob_path_exists])
292 69df9d2b Iustin Pop
  AssertCommand(["chmod", "0400", oob_path_exists])
293 69df9d2b Iustin Pop
  AssertCommand(["gnt-cluster", "copyfile", oob_path_exists])
294 f55312bd René Nussbaumer
295 f55312bd René Nussbaumer
  try:
296 f55312bd René Nussbaumer
    AssertCommand(["gnt-cluster", "modify", "--node-parameters",
297 f55312bd René Nussbaumer
                   "oob_program=%s" % oob_path_exists])
298 f55312bd René Nussbaumer
299 c2a0947d Iustin Pop
    AssertCommand(_CLUSTER_VERIFY, fail=True)
300 f55312bd René Nussbaumer
301 69df9d2b Iustin Pop
    AssertCommand(["chmod", "0500", oob_path_exists])
302 69df9d2b Iustin Pop
    AssertCommand(["gnt-cluster", "copyfile", oob_path_exists])
303 f55312bd René Nussbaumer
304 c2a0947d Iustin Pop
    AssertCommand(_CLUSTER_VERIFY)
305 f55312bd René Nussbaumer
  finally:
306 69df9d2b Iustin Pop
    AssertCommand(["gnt-cluster", "command", "rm", oob_path_exists])
307 f55312bd René Nussbaumer
308 f55312bd René Nussbaumer
  AssertCommand(["gnt-cluster", "modify", "--node-parameters",
309 f55312bd René Nussbaumer
                 "oob_program="])
310 69df9d2b Iustin Pop
311 69df9d2b Iustin Pop
312 66d1f035 René Nussbaumer
def TestClusterEpo():
313 66d1f035 René Nussbaumer
  """gnt-cluster epo"""
314 66d1f035 René Nussbaumer
  master = qa_config.GetMasterNode()
315 66d1f035 René Nussbaumer
316 66d1f035 René Nussbaumer
  # Assert that OOB is unavailable for all nodes
317 aecba21e Michael Hanselmann
  result_output = GetCommandOutput(master.primary,
318 58ea8d17 Michael Hanselmann
                                   "gnt-node list --verbose --no-headers -o"
319 66d1f035 René Nussbaumer
                                   " powered")
320 66d1f035 René Nussbaumer
  AssertEqual(compat.all(powered == "(unavail)"
321 66d1f035 René Nussbaumer
                         for powered in result_output.splitlines()), True)
322 66d1f035 René Nussbaumer
323 66d1f035 René Nussbaumer
  # Conflicting
324 66d1f035 René Nussbaumer
  AssertCommand(["gnt-cluster", "epo", "--groups", "--all"], fail=True)
325 66d1f035 René Nussbaumer
  # --all doesn't expect arguments
326 66d1f035 René Nussbaumer
  AssertCommand(["gnt-cluster", "epo", "--all", "some_arg"], fail=True)
327 66d1f035 René Nussbaumer
328 66d1f035 René Nussbaumer
  # Unless --all is given master is not allowed to be in the list
329 aecba21e Michael Hanselmann
  AssertCommand(["gnt-cluster", "epo", "-f", master.primary], fail=True)
330 66d1f035 René Nussbaumer
331 66d1f035 René Nussbaumer
  # This shouldn't fail
332 66d1f035 René Nussbaumer
  AssertCommand(["gnt-cluster", "epo", "-f", "--all"])
333 66d1f035 René Nussbaumer
334 66d1f035 René Nussbaumer
  # All instances should have been stopped now
335 aecba21e Michael Hanselmann
  result_output = GetCommandOutput(master.primary,
336 58ea8d17 Michael Hanselmann
                                   "gnt-instance list --no-headers -o status")
337 3e0ed18c René Nussbaumer
  # ERROR_down because the instance is stopped but not recorded as such
338 3e0ed18c René Nussbaumer
  AssertEqual(compat.all(status == "ERROR_down"
339 66d1f035 René Nussbaumer
                         for status in result_output.splitlines()), True)
340 66d1f035 René Nussbaumer
341 66d1f035 René Nussbaumer
  # Now start everything again
342 66d1f035 René Nussbaumer
  AssertCommand(["gnt-cluster", "epo", "--on", "-f", "--all"])
343 66d1f035 René Nussbaumer
344 66d1f035 René Nussbaumer
  # All instances should have been started now
345 aecba21e Michael Hanselmann
  result_output = GetCommandOutput(master.primary,
346 58ea8d17 Michael Hanselmann
                                   "gnt-instance list --no-headers -o status")
347 66d1f035 René Nussbaumer
  AssertEqual(compat.all(status == "running"
348 66d1f035 René Nussbaumer
                         for status in result_output.splitlines()), True)
349 66d1f035 René Nussbaumer
350 66d1f035 René Nussbaumer
351 69df9d2b Iustin Pop
def TestClusterVerify():
352 69df9d2b Iustin Pop
  """gnt-cluster verify"""
353 c2a0947d Iustin Pop
  AssertCommand(_CLUSTER_VERIFY)
354 c6953b6e Iustin Pop
  AssertCommand(["gnt-cluster", "verify-disks"])
355 cec9845c Michael Hanselmann
356 1377433b Michael Hanselmann
357 1377433b Michael Hanselmann
def TestJobqueue():
358 1377433b Michael Hanselmann
  """gnt-debug test-jobqueue"""
359 2f4b4f78 Iustin Pop
  AssertCommand(["gnt-debug", "test-jobqueue"])
360 1377433b Michael Hanselmann
361 1377433b Michael Hanselmann
362 5a85b99e Michael Hanselmann
def TestDelay(node):
363 5a85b99e Michael Hanselmann
  """gnt-debug delay"""
364 5a85b99e Michael Hanselmann
  AssertCommand(["gnt-debug", "delay", "1"])
365 5a85b99e Michael Hanselmann
  AssertCommand(["gnt-debug", "delay", "--no-master", "1"])
366 5a85b99e Michael Hanselmann
  AssertCommand(["gnt-debug", "delay", "--no-master",
367 aecba21e Michael Hanselmann
                 "-n", node.primary, "1"])
368 5a85b99e Michael Hanselmann
369 5a85b99e Michael Hanselmann
370 452913ed Iustin Pop
def TestClusterReservedLvs():
371 452913ed Iustin Pop
  """gnt-cluster reserved lvs"""
372 23610ff8 Bernardo Dal Seno
  vgname = qa_config.get("vg-name", constants.DEFAULT_VG)
373 23610ff8 Bernardo Dal Seno
  lvname = _QA_LV_PREFIX + "test"
374 23610ff8 Bernardo Dal Seno
  lvfullname = "/".join([vgname, lvname])
375 2f4b4f78 Iustin Pop
  for fail, cmd in [
376 c2a0947d Iustin Pop
    (False, _CLUSTER_VERIFY),
377 2f4b4f78 Iustin Pop
    (False, ["gnt-cluster", "modify", "--reserved-lvs", ""]),
378 23610ff8 Bernardo Dal Seno
    (False, ["lvcreate", "-L1G", "-n", lvname, vgname]),
379 21bf2e2e Andrea Spadaccini
    (True, _CLUSTER_VERIFY),
380 84d7e26b Dmitry Chernyak
    (False, ["gnt-cluster", "modify", "--reserved-lvs",
381 23610ff8 Bernardo Dal Seno
             "%s,.*/other-test" % lvfullname]),
382 c2a0947d Iustin Pop
    (False, _CLUSTER_VERIFY),
383 23610ff8 Bernardo Dal Seno
    (False, ["gnt-cluster", "modify", "--reserved-lvs",
384 23610ff8 Bernardo Dal Seno
             ".*/%s.*" % _QA_LV_PREFIX]),
385 c2a0947d Iustin Pop
    (False, _CLUSTER_VERIFY),
386 2f4b4f78 Iustin Pop
    (False, ["gnt-cluster", "modify", "--reserved-lvs", ""]),
387 21bf2e2e Andrea Spadaccini
    (True, _CLUSTER_VERIFY),
388 23610ff8 Bernardo Dal Seno
    (False, ["lvremove", "-f", lvfullname]),
389 c2a0947d Iustin Pop
    (False, _CLUSTER_VERIFY),
390 452913ed Iustin Pop
    ]:
391 2f4b4f78 Iustin Pop
    AssertCommand(cmd, fail=fail)
392 452913ed Iustin Pop
393 cec9845c Michael Hanselmann
394 1e7acc3b Iustin Pop
def TestClusterModifyEmpty():
395 1e7acc3b Iustin Pop
  """gnt-cluster modify"""
396 1e7acc3b Iustin Pop
  AssertCommand(["gnt-cluster", "modify"], fail=True)
397 1e7acc3b Iustin Pop
398 1e7acc3b Iustin Pop
399 92cb4940 Andrea Spadaccini
def TestClusterModifyDisk():
400 92cb4940 Andrea Spadaccini
  """gnt-cluster modify -D"""
401 92cb4940 Andrea Spadaccini
  for param in _FAIL_PARAMS:
402 92cb4940 Andrea Spadaccini
    AssertCommand(["gnt-cluster", "modify", "-D", param], fail=True)
403 92cb4940 Andrea Spadaccini
404 92cb4940 Andrea Spadaccini
405 9738ca94 Iustin Pop
def TestClusterModifyBe():
406 9738ca94 Iustin Pop
  """gnt-cluster modify -B"""
407 2f4b4f78 Iustin Pop
  for fail, cmd in [
408 8ccbbe4b Guido Trotter
    # max/min mem
409 8ccbbe4b Guido Trotter
    (False, ["gnt-cluster", "modify", "-B", "maxmem=256"]),
410 8ccbbe4b Guido Trotter
    (False, ["sh", "-c", "gnt-cluster info|grep '^ *maxmem: 256$'"]),
411 8ccbbe4b Guido Trotter
    (False, ["gnt-cluster", "modify", "-B", "minmem=256"]),
412 8ccbbe4b Guido Trotter
    (False, ["sh", "-c", "gnt-cluster info|grep '^ *minmem: 256$'"]),
413 8ccbbe4b Guido Trotter
    (True, ["gnt-cluster", "modify", "-B", "maxmem=a"]),
414 8ccbbe4b Guido Trotter
    (False, ["sh", "-c", "gnt-cluster info|grep '^ *maxmem: 256$'"]),
415 8ccbbe4b Guido Trotter
    (True, ["gnt-cluster", "modify", "-B", "minmem=a"]),
416 8ccbbe4b Guido Trotter
    (False, ["sh", "-c", "gnt-cluster info|grep '^ *minmem: 256$'"]),
417 8ccbbe4b Guido Trotter
    (False, ["gnt-cluster", "modify", "-B", "maxmem=128,minmem=128"]),
418 8ccbbe4b Guido Trotter
    (False, ["sh", "-c", "gnt-cluster info|grep '^ *maxmem: 128$'"]),
419 8ccbbe4b Guido Trotter
    (False, ["sh", "-c", "gnt-cluster info|grep '^ *minmem: 128$'"]),
420 9738ca94 Iustin Pop
    # vcpus
421 2f4b4f78 Iustin Pop
    (False, ["gnt-cluster", "modify", "-B", "vcpus=4"]),
422 2f4b4f78 Iustin Pop
    (False, ["sh", "-c", "gnt-cluster info|grep '^ *vcpus: 4$'"]),
423 21bf2e2e Andrea Spadaccini
    (True, ["gnt-cluster", "modify", "-B", "vcpus=a"]),
424 2f4b4f78 Iustin Pop
    (False, ["gnt-cluster", "modify", "-B", "vcpus=1"]),
425 2f4b4f78 Iustin Pop
    (False, ["sh", "-c", "gnt-cluster info|grep '^ *vcpus: 1$'"]),
426 9738ca94 Iustin Pop
    # auto_balance
427 2f4b4f78 Iustin Pop
    (False, ["gnt-cluster", "modify", "-B", "auto_balance=False"]),
428 2f4b4f78 Iustin Pop
    (False, ["sh", "-c", "gnt-cluster info|grep '^ *auto_balance: False$'"]),
429 21bf2e2e Andrea Spadaccini
    (True, ["gnt-cluster", "modify", "-B", "auto_balance=1"]),
430 2f4b4f78 Iustin Pop
    (False, ["gnt-cluster", "modify", "-B", "auto_balance=True"]),
431 2f4b4f78 Iustin Pop
    (False, ["sh", "-c", "gnt-cluster info|grep '^ *auto_balance: True$'"]),
432 9738ca94 Iustin Pop
    ]:
433 2f4b4f78 Iustin Pop
    AssertCommand(cmd, fail=fail)
434 9738ca94 Iustin Pop
435 5abecc1c Iustin Pop
  # redo the original-requested BE parameters, if any
436 5abecc1c Iustin Pop
  bep = qa_config.get("backend-parameters", "")
437 5abecc1c Iustin Pop
  if bep:
438 5abecc1c Iustin Pop
    AssertCommand(["gnt-cluster", "modify", "-B", bep])
439 9738ca94 Iustin Pop
440 21bf2e2e Andrea Spadaccini
441 b3f3aa3d Bernardo Dal Seno
_START_IPOLICY_RE = re.compile(r"^(\s*)Instance policy")
442 b3f3aa3d Bernardo Dal Seno
_START_ISPEC_RE = re.compile(r"^\s+-\s+(std|min|max)")
443 b3f3aa3d Bernardo Dal Seno
_VALUE_RE = r"([^\s:][^:]*):\s+(\S.*)$"
444 b3f3aa3d Bernardo Dal Seno
_IPOLICY_PARAM_RE = re.compile(r"^\s+-\s+" + _VALUE_RE)
445 b3f3aa3d Bernardo Dal Seno
_ISPEC_VALUE_RE = re.compile(r"^\s+" + _VALUE_RE)
446 b3f3aa3d Bernardo Dal Seno
447 b3f3aa3d Bernardo Dal Seno
448 b3f3aa3d Bernardo Dal Seno
def _GetClusterIPolicy():
449 b3f3aa3d Bernardo Dal Seno
  """Return the run-time values of the cluster-level instance policy.
450 b3f3aa3d Bernardo Dal Seno

451 b3f3aa3d Bernardo Dal Seno
  @rtype: tuple
452 b3f3aa3d Bernardo Dal Seno
  @return: (policy, specs), where:
453 b3f3aa3d Bernardo Dal Seno
      - policy is a dictionary of the policy values, instance specs excluded
454 b3f3aa3d Bernardo Dal Seno
      - specs is dict of dict, specs[par][key] is a spec value, where key is
455 b3f3aa3d Bernardo Dal Seno
        "min", "max", or "std"
456 b3f3aa3d Bernardo Dal Seno

457 b3f3aa3d Bernardo Dal Seno
  """
458 b3f3aa3d Bernardo Dal Seno
  mnode = qa_config.GetMasterNode()
459 46d21495 Bernardo Dal Seno
  info = GetCommandOutput(mnode.primary, "gnt-cluster info")
460 b3f3aa3d Bernardo Dal Seno
  inside_policy = False
461 b3f3aa3d Bernardo Dal Seno
  end_ispec_re = None
462 b3f3aa3d Bernardo Dal Seno
  curr_spec = ""
463 b3f3aa3d Bernardo Dal Seno
  specs = {}
464 b3f3aa3d Bernardo Dal Seno
  policy = {}
465 b3f3aa3d Bernardo Dal Seno
  for line in info.splitlines():
466 b3f3aa3d Bernardo Dal Seno
    if inside_policy:
467 b3f3aa3d Bernardo Dal Seno
      # The order of the matching is important, as some REs overlap
468 b3f3aa3d Bernardo Dal Seno
      m = _START_ISPEC_RE.match(line)
469 b3f3aa3d Bernardo Dal Seno
      if m:
470 b3f3aa3d Bernardo Dal Seno
        curr_spec = m.group(1)
471 b3f3aa3d Bernardo Dal Seno
        continue
472 b3f3aa3d Bernardo Dal Seno
      m = _IPOLICY_PARAM_RE.match(line)
473 b3f3aa3d Bernardo Dal Seno
      if m:
474 b3f3aa3d Bernardo Dal Seno
        policy[m.group(1)] = m.group(2).strip()
475 b3f3aa3d Bernardo Dal Seno
        continue
476 b3f3aa3d Bernardo Dal Seno
      m = _ISPEC_VALUE_RE.match(line)
477 b3f3aa3d Bernardo Dal Seno
      if m:
478 b3f3aa3d Bernardo Dal Seno
        assert curr_spec
479 b3f3aa3d Bernardo Dal Seno
        par = m.group(1)
480 b3f3aa3d Bernardo Dal Seno
        if par == "memory-size":
481 b3f3aa3d Bernardo Dal Seno
          par = "mem-size"
482 b3f3aa3d Bernardo Dal Seno
        d = specs.setdefault(par, {})
483 b3f3aa3d Bernardo Dal Seno
        d[curr_spec] = m.group(2).strip()
484 b3f3aa3d Bernardo Dal Seno
        continue
485 b3f3aa3d Bernardo Dal Seno
      assert end_ispec_re is not None
486 b3f3aa3d Bernardo Dal Seno
      if end_ispec_re.match(line):
487 b3f3aa3d Bernardo Dal Seno
        inside_policy = False
488 b3f3aa3d Bernardo Dal Seno
    else:
489 b3f3aa3d Bernardo Dal Seno
      m = _START_IPOLICY_RE.match(line)
490 b3f3aa3d Bernardo Dal Seno
      if m:
491 b3f3aa3d Bernardo Dal Seno
        inside_policy = True
492 b3f3aa3d Bernardo Dal Seno
        # We stop parsing when we find the same indentation level
493 b3f3aa3d Bernardo Dal Seno
        re_str = r"^\s{%s}\S" % len(m.group(1))
494 b3f3aa3d Bernardo Dal Seno
        end_ispec_re = re.compile(re_str)
495 b3f3aa3d Bernardo Dal Seno
  # Sanity checks
496 b3f3aa3d Bernardo Dal Seno
  assert len(specs) > 0
497 b3f3aa3d Bernardo Dal Seno
  good = ("min" in d and "std" in d and "max" in d for d in specs)
498 b3f3aa3d Bernardo Dal Seno
  assert good, "Missing item in specs: %s" % specs
499 b3f3aa3d Bernardo Dal Seno
  assert len(policy) > 0
500 b3f3aa3d Bernardo Dal Seno
  return (policy, specs)
501 b3f3aa3d Bernardo Dal Seno
502 b3f3aa3d Bernardo Dal Seno
503 b3f3aa3d Bernardo Dal Seno
def TestClusterModifyIPolicy():
504 b3f3aa3d Bernardo Dal Seno
  """gnt-cluster modify --ipolicy-*"""
505 b3f3aa3d Bernardo Dal Seno
  basecmd = ["gnt-cluster", "modify"]
506 b3f3aa3d Bernardo Dal Seno
  (old_policy, old_specs) = _GetClusterIPolicy()
507 b3f3aa3d Bernardo Dal Seno
  for par in ["vcpu-ratio", "spindle-ratio"]:
508 b3f3aa3d Bernardo Dal Seno
    curr_val = float(old_policy[par])
509 b3f3aa3d Bernardo Dal Seno
    test_values = [
510 b3f3aa3d Bernardo Dal Seno
      (True, 1.0),
511 b3f3aa3d Bernardo Dal Seno
      (True, 1.5),
512 b3f3aa3d Bernardo Dal Seno
      (True, 2),
513 b3f3aa3d Bernardo Dal Seno
      (False, "a"),
514 b3f3aa3d Bernardo Dal Seno
      # Restore the old value
515 b3f3aa3d Bernardo Dal Seno
      (True, curr_val),
516 b3f3aa3d Bernardo Dal Seno
      ]
517 b3f3aa3d Bernardo Dal Seno
    for (good, val) in test_values:
518 b3f3aa3d Bernardo Dal Seno
      cmd = basecmd + ["--ipolicy-%s=%s" % (par, val)]
519 b3f3aa3d Bernardo Dal Seno
      AssertCommand(cmd, fail=not good)
520 b3f3aa3d Bernardo Dal Seno
      if good:
521 b3f3aa3d Bernardo Dal Seno
        curr_val = val
522 b3f3aa3d Bernardo Dal Seno
      # Check the affected parameter
523 b3f3aa3d Bernardo Dal Seno
      (eff_policy, eff_specs) = _GetClusterIPolicy()
524 b3f3aa3d Bernardo Dal Seno
      AssertEqual(float(eff_policy[par]), curr_val)
525 b3f3aa3d Bernardo Dal Seno
      # Check everything else
526 b3f3aa3d Bernardo Dal Seno
      AssertEqual(eff_specs, old_specs)
527 b3f3aa3d Bernardo Dal Seno
      for p in eff_policy.keys():
528 b3f3aa3d Bernardo Dal Seno
        if p == par:
529 b3f3aa3d Bernardo Dal Seno
          continue
530 b3f3aa3d Bernardo Dal Seno
        AssertEqual(eff_policy[p], old_policy[p])
531 b3f3aa3d Bernardo Dal Seno
532 b3f3aa3d Bernardo Dal Seno
  # Disk templates are treated slightly differently
533 b3f3aa3d Bernardo Dal Seno
  par = "disk-templates"
534 b3f3aa3d Bernardo Dal Seno
  disp_str = "enabled disk templates"
535 b3f3aa3d Bernardo Dal Seno
  curr_val = old_policy[disp_str]
536 b3f3aa3d Bernardo Dal Seno
  test_values = [
537 b3f3aa3d Bernardo Dal Seno
    (True, constants.DT_PLAIN),
538 b3f3aa3d Bernardo Dal Seno
    (True, "%s,%s" % (constants.DT_PLAIN, constants.DT_DRBD8)),
539 b3f3aa3d Bernardo Dal Seno
    (False, "thisisnotadisktemplate"),
540 b3f3aa3d Bernardo Dal Seno
    (False, ""),
541 b3f3aa3d Bernardo Dal Seno
    # Restore the old value
542 b3f3aa3d Bernardo Dal Seno
    (True, curr_val.replace(" ", "")),
543 b3f3aa3d Bernardo Dal Seno
    ]
544 b3f3aa3d Bernardo Dal Seno
  for (good, val) in test_values:
545 b3f3aa3d Bernardo Dal Seno
    cmd = basecmd + ["--ipolicy-%s=%s" % (par, val)]
546 b3f3aa3d Bernardo Dal Seno
    AssertCommand(cmd, fail=not good)
547 b3f3aa3d Bernardo Dal Seno
    if good:
548 b3f3aa3d Bernardo Dal Seno
      curr_val = val
549 b3f3aa3d Bernardo Dal Seno
    # Check the affected parameter
550 b3f3aa3d Bernardo Dal Seno
    (eff_policy, eff_specs) = _GetClusterIPolicy()
551 b3f3aa3d Bernardo Dal Seno
    AssertEqual(eff_policy[disp_str].replace(" ", ""), curr_val)
552 b3f3aa3d Bernardo Dal Seno
    # Check everything else
553 b3f3aa3d Bernardo Dal Seno
    AssertEqual(eff_specs, old_specs)
554 b3f3aa3d Bernardo Dal Seno
    for p in eff_policy.keys():
555 b3f3aa3d Bernardo Dal Seno
      if p == disp_str:
556 b3f3aa3d Bernardo Dal Seno
        continue
557 b3f3aa3d Bernardo Dal Seno
      AssertEqual(eff_policy[p], old_policy[p])
558 b3f3aa3d Bernardo Dal Seno
559 b3f3aa3d Bernardo Dal Seno
560 b3f3aa3d Bernardo Dal Seno
def TestClusterSetISpecs(new_specs, fail=False, old_values=None):
561 b3f3aa3d Bernardo Dal Seno
  """Change instance specs.
562 b3f3aa3d Bernardo Dal Seno

563 b3f3aa3d Bernardo Dal Seno
  @type new_specs: dict of dict
564 b3f3aa3d Bernardo Dal Seno
  @param new_specs: new_specs[par][key], where key is "min", "max", "std". It
565 b3f3aa3d Bernardo Dal Seno
      can be an empty dictionary.
566 b3f3aa3d Bernardo Dal Seno
  @type fail: bool
567 b3f3aa3d Bernardo Dal Seno
  @param fail: if the change is expected to fail
568 b3f3aa3d Bernardo Dal Seno
  @type old_values: tuple
569 b3f3aa3d Bernardo Dal Seno
  @param old_values: (old_policy, old_specs), as returned by
570 b3f3aa3d Bernardo Dal Seno
     L{_GetClusterIPolicy}
571 b3f3aa3d Bernardo Dal Seno
  @return: same as L{_GetClusterIPolicy}
572 b3f3aa3d Bernardo Dal Seno

573 b3f3aa3d Bernardo Dal Seno
  """
574 b3f3aa3d Bernardo Dal Seno
  if old_values:
575 b3f3aa3d Bernardo Dal Seno
    (old_policy, old_specs) = old_values
576 b3f3aa3d Bernardo Dal Seno
  else:
577 b3f3aa3d Bernardo Dal Seno
    (old_policy, old_specs) = _GetClusterIPolicy()
578 b3f3aa3d Bernardo Dal Seno
  if new_specs:
579 b3f3aa3d Bernardo Dal Seno
    cmd = ["gnt-cluster", "modify"]
580 b3f3aa3d Bernardo Dal Seno
    for (par, keyvals) in new_specs.items():
581 b3f3aa3d Bernardo Dal Seno
      if par == "spindle-use":
582 b3f3aa3d Bernardo Dal Seno
        # ignore spindle-use, which is not settable
583 b3f3aa3d Bernardo Dal Seno
        continue
584 b3f3aa3d Bernardo Dal Seno
      cmd += [
585 b3f3aa3d Bernardo Dal Seno
        "--specs-%s" % par,
586 b3f3aa3d Bernardo Dal Seno
        ",".join(["%s=%s" % (k, v) for (k, v) in keyvals.items()]),
587 b3f3aa3d Bernardo Dal Seno
        ]
588 b3f3aa3d Bernardo Dal Seno
    AssertCommand(cmd, fail=fail)
589 b3f3aa3d Bernardo Dal Seno
  # Check the new state
590 b3f3aa3d Bernardo Dal Seno
  (eff_policy, eff_specs) = _GetClusterIPolicy()
591 b3f3aa3d Bernardo Dal Seno
  AssertEqual(eff_policy, old_policy)
592 b3f3aa3d Bernardo Dal Seno
  if fail:
593 b3f3aa3d Bernardo Dal Seno
    AssertEqual(eff_specs, old_specs)
594 b3f3aa3d Bernardo Dal Seno
  else:
595 b3f3aa3d Bernardo Dal Seno
    for par in eff_specs:
596 b3f3aa3d Bernardo Dal Seno
      for key in eff_specs[par]:
597 b3f3aa3d Bernardo Dal Seno
        if par in new_specs and key in new_specs[par]:
598 b3f3aa3d Bernardo Dal Seno
          AssertEqual(int(eff_specs[par][key]), int(new_specs[par][key]))
599 b3f3aa3d Bernardo Dal Seno
        else:
600 b3f3aa3d Bernardo Dal Seno
          AssertEqual(int(eff_specs[par][key]), int(old_specs[par][key]))
601 b3f3aa3d Bernardo Dal Seno
  return (eff_policy, eff_specs)
602 b3f3aa3d Bernardo Dal Seno
603 b3f3aa3d Bernardo Dal Seno
604 b3f3aa3d Bernardo Dal Seno
def TestClusterModifyISpecs():
605 b3f3aa3d Bernardo Dal Seno
  """gnt-cluster modify --specs-*"""
606 b3f3aa3d Bernardo Dal Seno
  params = ["mem-size", "disk-size", "disk-count", "cpu-count", "nic-count"]
607 b3f3aa3d Bernardo Dal Seno
  (cur_policy, cur_specs) = _GetClusterIPolicy()
608 b3f3aa3d Bernardo Dal Seno
  for par in params:
609 b3f3aa3d Bernardo Dal Seno
    test_values = [
610 b3f3aa3d Bernardo Dal Seno
      (True, 0, 4, 12),
611 b3f3aa3d Bernardo Dal Seno
      (True, 4, 4, 12),
612 b3f3aa3d Bernardo Dal Seno
      (True, 4, 12, 12),
613 b3f3aa3d Bernardo Dal Seno
      (True, 4, 4, 4),
614 b3f3aa3d Bernardo Dal Seno
      (False, 4, 0, 12),
615 b3f3aa3d Bernardo Dal Seno
      (False, 4, 16, 12),
616 b3f3aa3d Bernardo Dal Seno
      (False, 4, 4, 0),
617 b3f3aa3d Bernardo Dal Seno
      (False, 12, 4, 4),
618 b3f3aa3d Bernardo Dal Seno
      (False, 12, 4, 0),
619 b3f3aa3d Bernardo Dal Seno
      (False, "a", 4, 12),
620 b3f3aa3d Bernardo Dal Seno
      (False, 0, "a", 12),
621 b3f3aa3d Bernardo Dal Seno
      (False, 0, 4, "a"),
622 b3f3aa3d Bernardo Dal Seno
      # This is to restore the old values
623 b3f3aa3d Bernardo Dal Seno
      (True,
624 b3f3aa3d Bernardo Dal Seno
       cur_specs[par]["min"], cur_specs[par]["std"], cur_specs[par]["max"])
625 b3f3aa3d Bernardo Dal Seno
      ]
626 b3f3aa3d Bernardo Dal Seno
    for (good, mn, st, mx) in test_values:
627 b3f3aa3d Bernardo Dal Seno
      new_vals = {par: {"min": str(mn), "std": str(st), "max": str(mx)}}
628 b3f3aa3d Bernardo Dal Seno
      cur_state = (cur_policy, cur_specs)
629 b3f3aa3d Bernardo Dal Seno
      # We update cur_specs, as we've copied the values to restore already
630 b3f3aa3d Bernardo Dal Seno
      (cur_policy, cur_specs) = TestClusterSetISpecs(new_vals, fail=not good,
631 b3f3aa3d Bernardo Dal Seno
                                                     old_values=cur_state)
632 b3f3aa3d Bernardo Dal Seno
633 b3f3aa3d Bernardo Dal Seno
634 cec9845c Michael Hanselmann
def TestClusterInfo():
635 cec9845c Michael Hanselmann
  """gnt-cluster info"""
636 2f4b4f78 Iustin Pop
  AssertCommand(["gnt-cluster", "info"])
637 283f9d4c Michael Hanselmann
638 283f9d4c Michael Hanselmann
639 3e8b5a9c Iustin Pop
def TestClusterRedistConf():
640 3e8b5a9c Iustin Pop
  """gnt-cluster redist-conf"""
641 3e8b5a9c Iustin Pop
  AssertCommand(["gnt-cluster", "redist-conf"])
642 3e8b5a9c Iustin Pop
643 3e8b5a9c Iustin Pop
644 283f9d4c Michael Hanselmann
def TestClusterGetmaster():
645 283f9d4c Michael Hanselmann
  """gnt-cluster getmaster"""
646 2f4b4f78 Iustin Pop
  AssertCommand(["gnt-cluster", "getmaster"])
647 283f9d4c Michael Hanselmann
648 283f9d4c Michael Hanselmann
649 283f9d4c Michael Hanselmann
def TestClusterVersion():
650 283f9d4c Michael Hanselmann
  """gnt-cluster version"""
651 2f4b4f78 Iustin Pop
  AssertCommand(["gnt-cluster", "version"])
652 cec9845c Michael Hanselmann
653 cec9845c Michael Hanselmann
654 6d4a1656 Michael Hanselmann
def TestClusterRenewCrypto():
655 6d4a1656 Michael Hanselmann
  """gnt-cluster renew-crypto"""
656 6d4a1656 Michael Hanselmann
  master = qa_config.GetMasterNode()
657 6d4a1656 Michael Hanselmann
658 6d4a1656 Michael Hanselmann
  # Conflicting options
659 6d4a1656 Michael Hanselmann
  cmd = ["gnt-cluster", "renew-crypto", "--force",
660 3db3eb2a Michael Hanselmann
         "--new-cluster-certificate", "--new-confd-hmac-key"]
661 3db3eb2a Michael Hanselmann
  conflicting = [
662 3db3eb2a Michael Hanselmann
    ["--new-rapi-certificate", "--rapi-certificate=/dev/null"],
663 3db3eb2a Michael Hanselmann
    ["--new-cluster-domain-secret", "--cluster-domain-secret=/dev/null"],
664 3db3eb2a Michael Hanselmann
    ]
665 3db3eb2a Michael Hanselmann
  for i in conflicting:
666 21bf2e2e Andrea Spadaccini
    AssertCommand(cmd + i, fail=True)
667 6d4a1656 Michael Hanselmann
668 6d4a1656 Michael Hanselmann
  # Invalid RAPI certificate
669 6d4a1656 Michael Hanselmann
  cmd = ["gnt-cluster", "renew-crypto", "--force",
670 6d4a1656 Michael Hanselmann
         "--rapi-certificate=/dev/null"]
671 2f4b4f78 Iustin Pop
  AssertCommand(cmd, fail=True)
672 6d4a1656 Michael Hanselmann
673 aecba21e Michael Hanselmann
  rapi_cert_backup = qa_utils.BackupFile(master.primary,
674 304d9f02 Michael Hanselmann
                                         pathutils.RAPI_CERT_FILE)
675 502f5236 Michael Hanselmann
  try:
676 502f5236 Michael Hanselmann
    # Custom RAPI certificate
677 502f5236 Michael Hanselmann
    fh = tempfile.NamedTemporaryFile()
678 6d4a1656 Michael Hanselmann
679 502f5236 Michael Hanselmann
    # Ensure certificate doesn't cause "gnt-cluster verify" to complain
680 502f5236 Michael Hanselmann
    validity = constants.SSL_CERT_EXPIRATION_WARN * 3
681 6d4a1656 Michael Hanselmann
682 5e26633b Michael Hanselmann
    utils.GenerateSelfSignedSslCert(fh.name, validity=validity)
683 6d4a1656 Michael Hanselmann
684 aecba21e Michael Hanselmann
    tmpcert = qa_utils.UploadFile(master.primary, fh.name)
685 502f5236 Michael Hanselmann
    try:
686 2f4b4f78 Iustin Pop
      AssertCommand(["gnt-cluster", "renew-crypto", "--force",
687 2f4b4f78 Iustin Pop
                     "--rapi-certificate=%s" % tmpcert])
688 502f5236 Michael Hanselmann
    finally:
689 2f4b4f78 Iustin Pop
      AssertCommand(["rm", "-f", tmpcert])
690 502f5236 Michael Hanselmann
691 5e26633b Michael Hanselmann
    # Custom cluster domain secret
692 5e26633b Michael Hanselmann
    cds_fh = tempfile.NamedTemporaryFile()
693 5e26633b Michael Hanselmann
    cds_fh.write(utils.GenerateSecret())
694 5e26633b Michael Hanselmann
    cds_fh.write("\n")
695 5e26633b Michael Hanselmann
    cds_fh.flush()
696 5e26633b Michael Hanselmann
697 aecba21e Michael Hanselmann
    tmpcds = qa_utils.UploadFile(master.primary, cds_fh.name)
698 5e26633b Michael Hanselmann
    try:
699 2f4b4f78 Iustin Pop
      AssertCommand(["gnt-cluster", "renew-crypto", "--force",
700 2f4b4f78 Iustin Pop
                     "--cluster-domain-secret=%s" % tmpcds])
701 5e26633b Michael Hanselmann
    finally:
702 2f4b4f78 Iustin Pop
      AssertCommand(["rm", "-f", tmpcds])
703 5e26633b Michael Hanselmann
704 502f5236 Michael Hanselmann
    # Normal case
705 2f4b4f78 Iustin Pop
    AssertCommand(["gnt-cluster", "renew-crypto", "--force",
706 2f4b4f78 Iustin Pop
                   "--new-cluster-certificate", "--new-confd-hmac-key",
707 2f4b4f78 Iustin Pop
                   "--new-rapi-certificate", "--new-cluster-domain-secret"])
708 3db3eb2a Michael Hanselmann
709 502f5236 Michael Hanselmann
    # Restore RAPI certificate
710 2f4b4f78 Iustin Pop
    AssertCommand(["gnt-cluster", "renew-crypto", "--force",
711 2f4b4f78 Iustin Pop
                   "--rapi-certificate=%s" % rapi_cert_backup])
712 3db3eb2a Michael Hanselmann
  finally:
713 2f4b4f78 Iustin Pop
    AssertCommand(["rm", "-f", rapi_cert_backup])
714 3db3eb2a Michael Hanselmann
715 6d4a1656 Michael Hanselmann
716 cec9845c Michael Hanselmann
def TestClusterBurnin():
717 cec9845c Michael Hanselmann
  """Burnin"""
718 cec9845c Michael Hanselmann
  master = qa_config.GetMasterNode()
719 cec9845c Michael Hanselmann
720 d0c8c01d Iustin Pop
  options = qa_config.get("options", {})
721 68c8c3df Michael Hanselmann
  disk_template = options.get("burnin-disk-template", constants.DT_DRBD8)
722 d0c8c01d Iustin Pop
  parallel = options.get("burnin-in-parallel", False)
723 d0c8c01d Iustin Pop
  check_inst = options.get("burnin-check-instances", False)
724 d0c8c01d Iustin Pop
  do_rename = options.get("burnin-rename", "")
725 d0c8c01d Iustin Pop
  do_reboot = options.get("burnin-reboot", True)
726 1d103c02 Iustin Pop
  reboot_types = options.get("reboot-types", constants.REBOOT_TYPES)
727 23103544 Michael Hanselmann
728 cec9845c Michael Hanselmann
  # Get as many instances as we need
729 cec9845c Michael Hanselmann
  instances = []
730 cec9845c Michael Hanselmann
  try:
731 23103544 Michael Hanselmann
    try:
732 d0c8c01d Iustin Pop
      num = qa_config.get("options", {}).get("burnin-instances", 1)
733 f1501b3f Michael Hanselmann
      for _ in range(0, num):
734 23103544 Michael Hanselmann
        instances.append(qa_config.AcquireInstance())
735 23103544 Michael Hanselmann
    except qa_error.OutOfInstancesError:
736 23103544 Michael Hanselmann
      print "Not enough instances, continuing anyway."
737 cec9845c Michael Hanselmann
738 23103544 Michael Hanselmann
    if len(instances) < 1:
739 23103544 Michael Hanselmann
      raise qa_error.Error("Burnin needs at least one instance")
740 cec9845c Michael Hanselmann
741 aecba21e Michael Hanselmann
    script = qa_utils.UploadFile(master.primary, "../tools/burnin")
742 cec9845c Michael Hanselmann
    try:
743 23103544 Michael Hanselmann
      # Run burnin
744 cec9845c Michael Hanselmann
      cmd = [script,
745 d0c8c01d Iustin Pop
             "--os=%s" % qa_config.get("os"),
746 f356202a Guido Trotter
             "--minmem-size=%s" % qa_config.get(constants.BE_MINMEM),
747 f356202a Guido Trotter
             "--maxmem-size=%s" % qa_config.get(constants.BE_MAXMEM),
748 d0c8c01d Iustin Pop
             "--disk-size=%s" % ",".join(qa_config.get("disk")),
749 d0c8c01d Iustin Pop
             "--disk-growth=%s" % ",".join(qa_config.get("disk-growth")),
750 d0c8c01d Iustin Pop
             "--disk-template=%s" % disk_template]
751 0b0a150a Iustin Pop
      if parallel:
752 d0c8c01d Iustin Pop
        cmd.append("--parallel")
753 d0c8c01d Iustin Pop
        cmd.append("--early-release")
754 0b0a150a Iustin Pop
      if check_inst:
755 d0c8c01d Iustin Pop
        cmd.append("--http-check")
756 4dc76b24 Iustin Pop
      if do_rename:
757 d0c8c01d Iustin Pop
        cmd.append("--rename=%s" % do_rename)
758 58598264 Iustin Pop
      if not do_reboot:
759 d0c8c01d Iustin Pop
        cmd.append("--no-reboot")
760 1d103c02 Iustin Pop
      else:
761 d0c8c01d Iustin Pop
        cmd.append("--reboot-types=%s" % ",".join(reboot_types))
762 b5f33afa Michael Hanselmann
      cmd += [inst.name for inst in instances]
763 2f4b4f78 Iustin Pop
      AssertCommand(cmd)
764 cec9845c Michael Hanselmann
    finally:
765 2f4b4f78 Iustin Pop
      AssertCommand(["rm", "-f", script])
766 2f4b4f78 Iustin Pop
767 cec9845c Michael Hanselmann
  finally:
768 cec9845c Michael Hanselmann
    for inst in instances:
769 6f88e076 Michael Hanselmann
      inst.Release()
770 cec9845c Michael Hanselmann
771 cec9845c Michael Hanselmann
772 cec9845c Michael Hanselmann
def TestClusterMasterFailover():
773 c28502b1 Iustin Pop
  """gnt-cluster master-failover"""
774 cec9845c Michael Hanselmann
  master = qa_config.GetMasterNode()
775 cec9845c Michael Hanselmann
  failovermaster = qa_config.AcquireNode(exclude=master)
776 cec9845c Michael Hanselmann
777 2f4b4f78 Iustin Pop
  cmd = ["gnt-cluster", "master-failover"]
778 2f4b4f78 Iustin Pop
  try:
779 2f4b4f78 Iustin Pop
    AssertCommand(cmd, node=failovermaster)
780 ff699aa9 Michael Hanselmann
    # Back to original master node
781 2f4b4f78 Iustin Pop
    AssertCommand(cmd, node=master)
782 cec9845c Michael Hanselmann
  finally:
783 565cb4bf Michael Hanselmann
    failovermaster.Release()
784 cec9845c Michael Hanselmann
785 cec9845c Michael Hanselmann
786 2df92990 Michael Hanselmann
def _NodeQueueDrainFile(node):
787 2df92990 Michael Hanselmann
  """Returns path to queue drain file for a node.
788 2df92990 Michael Hanselmann

789 2df92990 Michael Hanselmann
  """
790 2df92990 Michael Hanselmann
  return qa_utils.MakeNodePath(node, pathutils.JOB_QUEUE_DRAIN_FILE)
791 2df92990 Michael Hanselmann
792 2df92990 Michael Hanselmann
793 2df92990 Michael Hanselmann
def _AssertDrainFile(node, **kwargs):
794 2df92990 Michael Hanselmann
  """Checks for the queue drain file.
795 2df92990 Michael Hanselmann

796 2df92990 Michael Hanselmann
  """
797 2df92990 Michael Hanselmann
  AssertCommand(["test", "-f", _NodeQueueDrainFile(node)], node=node, **kwargs)
798 2df92990 Michael Hanselmann
799 2df92990 Michael Hanselmann
800 ff699aa9 Michael Hanselmann
def TestClusterMasterFailoverWithDrainedQueue():
801 ff699aa9 Michael Hanselmann
  """gnt-cluster master-failover with drained queue"""
802 ff699aa9 Michael Hanselmann
  master = qa_config.GetMasterNode()
803 ff699aa9 Michael Hanselmann
  failovermaster = qa_config.AcquireNode(exclude=master)
804 ff699aa9 Michael Hanselmann
805 ff699aa9 Michael Hanselmann
  # Ensure queue is not drained
806 ff699aa9 Michael Hanselmann
  for node in [master, failovermaster]:
807 2df92990 Michael Hanselmann
    _AssertDrainFile(node, fail=True)
808 ff699aa9 Michael Hanselmann
809 ff699aa9 Michael Hanselmann
  # Drain queue on failover master
810 2df92990 Michael Hanselmann
  AssertCommand(["touch", _NodeQueueDrainFile(failovermaster)],
811 2df92990 Michael Hanselmann
                node=failovermaster)
812 ff699aa9 Michael Hanselmann
813 ff699aa9 Michael Hanselmann
  cmd = ["gnt-cluster", "master-failover"]
814 ff699aa9 Michael Hanselmann
  try:
815 2df92990 Michael Hanselmann
    _AssertDrainFile(failovermaster)
816 ff699aa9 Michael Hanselmann
    AssertCommand(cmd, node=failovermaster)
817 2df92990 Michael Hanselmann
    _AssertDrainFile(master, fail=True)
818 2df92990 Michael Hanselmann
    _AssertDrainFile(failovermaster, fail=True)
819 ff699aa9 Michael Hanselmann
820 ff699aa9 Michael Hanselmann
    # Back to original master node
821 ff699aa9 Michael Hanselmann
    AssertCommand(cmd, node=master)
822 ff699aa9 Michael Hanselmann
  finally:
823 565cb4bf Michael Hanselmann
    failovermaster.Release()
824 ff699aa9 Michael Hanselmann
825 2df92990 Michael Hanselmann
  # Ensure queue is not drained
826 2df92990 Michael Hanselmann
  for node in [master, failovermaster]:
827 2df92990 Michael Hanselmann
    _AssertDrainFile(node, fail=True)
828 ff699aa9 Michael Hanselmann
829 ff699aa9 Michael Hanselmann
830 cec9845c Michael Hanselmann
def TestClusterCopyfile():
831 cec9845c Michael Hanselmann
  """gnt-cluster copyfile"""
832 cec9845c Michael Hanselmann
  master = qa_config.GetMasterNode()
833 cec9845c Michael Hanselmann
834 24818e8f Michael Hanselmann
  uniqueid = utils.NewUUID()
835 830da270 Michael Hanselmann
836 cec9845c Michael Hanselmann
  # Create temporary file
837 cec9845c Michael Hanselmann
  f = tempfile.NamedTemporaryFile()
838 830da270 Michael Hanselmann
  f.write(uniqueid)
839 cec9845c Michael Hanselmann
  f.flush()
840 cec9845c Michael Hanselmann
  f.seek(0)
841 cec9845c Michael Hanselmann
842 cec9845c Michael Hanselmann
  # Upload file to master node
843 aecba21e Michael Hanselmann
  testname = qa_utils.UploadFile(master.primary, f.name)
844 cec9845c Michael Hanselmann
  try:
845 cec9845c Michael Hanselmann
    # Copy file to all nodes
846 2f4b4f78 Iustin Pop
    AssertCommand(["gnt-cluster", "copyfile", testname])
847 830da270 Michael Hanselmann
    _CheckFileOnAllNodes(testname, uniqueid)
848 cec9845c Michael Hanselmann
  finally:
849 830da270 Michael Hanselmann
    _RemoveFileFromAllNodes(testname)
850 830da270 Michael Hanselmann
851 830da270 Michael Hanselmann
852 830da270 Michael Hanselmann
def TestClusterCommand():
853 830da270 Michael Hanselmann
  """gnt-cluster command"""
854 24818e8f Michael Hanselmann
  uniqueid = utils.NewUUID()
855 24818e8f Michael Hanselmann
  rfile = "/tmp/gnt%s" % utils.NewUUID()
856 d0c8c01d Iustin Pop
  rcmd = utils.ShellQuoteArgs(["echo", "-n", uniqueid])
857 d0c8c01d Iustin Pop
  cmd = utils.ShellQuoteArgs(["gnt-cluster", "command",
858 830da270 Michael Hanselmann
                              "%s >%s" % (rcmd, rfile)])
859 830da270 Michael Hanselmann
860 830da270 Michael Hanselmann
  try:
861 2f4b4f78 Iustin Pop
    AssertCommand(cmd)
862 830da270 Michael Hanselmann
    _CheckFileOnAllNodes(rfile, uniqueid)
863 830da270 Michael Hanselmann
  finally:
864 830da270 Michael Hanselmann
    _RemoveFileFromAllNodes(rfile)
865 cec9845c Michael Hanselmann
866 cec9845c Michael Hanselmann
867 cec9845c Michael Hanselmann
def TestClusterDestroy():
868 cec9845c Michael Hanselmann
  """gnt-cluster destroy"""
869 2f4b4f78 Iustin Pop
  AssertCommand(["gnt-cluster", "destroy", "--yes-do-it"])
870 65a884ef Iustin Pop
871 65a884ef Iustin Pop
872 65a884ef Iustin Pop
def TestClusterRepairDiskSizes():
873 65a884ef Iustin Pop
  """gnt-cluster repair-disk-sizes"""
874 65a884ef Iustin Pop
  AssertCommand(["gnt-cluster", "repair-disk-sizes"])
875 50ef6a41 Bernardo Dal Seno
876 50ef6a41 Bernardo Dal Seno
877 50ef6a41 Bernardo Dal Seno
def TestSetExclStorCluster(newvalue):
878 50ef6a41 Bernardo Dal Seno
  """Set the exclusive_storage node parameter at the cluster level.
879 50ef6a41 Bernardo Dal Seno

880 50ef6a41 Bernardo Dal Seno
  @type newvalue: bool
881 50ef6a41 Bernardo Dal Seno
  @param newvalue: New value of exclusive_storage
882 50ef6a41 Bernardo Dal Seno
  @rtype: bool
883 50ef6a41 Bernardo Dal Seno
  @return: The old value of exclusive_storage
884 50ef6a41 Bernardo Dal Seno

885 50ef6a41 Bernardo Dal Seno
  """
886 50ef6a41 Bernardo Dal Seno
  oldvalue = _GetBoolClusterField("exclusive_storage")
887 50ef6a41 Bernardo Dal Seno
  AssertCommand(["gnt-cluster", "modify", "--node-parameters",
888 50ef6a41 Bernardo Dal Seno
                 "exclusive_storage=%s" % newvalue])
889 50ef6a41 Bernardo Dal Seno
  effvalue = _GetBoolClusterField("exclusive_storage")
890 50ef6a41 Bernardo Dal Seno
  if effvalue != newvalue:
891 50ef6a41 Bernardo Dal Seno
    raise qa_error.Error("exclusive_storage has the wrong value: %s instead"
892 50ef6a41 Bernardo Dal Seno
                         " of %s" % (effvalue, newvalue))
893 6a0f22e1 Bernardo Dal Seno
  qa_config.SetExclusiveStorage(newvalue)
894 50ef6a41 Bernardo Dal Seno
  return oldvalue
895 e8b919a1 Bernardo Dal Seno
896 e8b919a1 Bernardo Dal Seno
897 21e2734f Bernardo Dal Seno
def TestExclStorSharedPv(node):
898 21e2734f Bernardo Dal Seno
  """cluster-verify reports LVs that share the same PV with exclusive_storage.
899 21e2734f Bernardo Dal Seno

900 21e2734f Bernardo Dal Seno
  """
901 21e2734f Bernardo Dal Seno
  vgname = qa_config.get("vg-name", constants.DEFAULT_VG)
902 21e2734f Bernardo Dal Seno
  lvname1 = _QA_LV_PREFIX + "vol1"
903 21e2734f Bernardo Dal Seno
  lvname2 = _QA_LV_PREFIX + "vol2"
904 aecba21e Michael Hanselmann
  node_name = node.primary
905 21e2734f Bernardo Dal Seno
  AssertCommand(["lvcreate", "-L1G", "-n", lvname1, vgname], node=node_name)
906 21e2734f Bernardo Dal Seno
  AssertClusterVerify(fail=True, errors=[constants.CV_ENODEORPHANLV])
907 21e2734f Bernardo Dal Seno
  AssertCommand(["lvcreate", "-L1G", "-n", lvname2, vgname], node=node_name)
908 21e2734f Bernardo Dal Seno
  AssertClusterVerify(fail=True, errors=[constants.CV_ENODELVM,
909 21e2734f Bernardo Dal Seno
                                         constants.CV_ENODEORPHANLV])
910 21e2734f Bernardo Dal Seno
  AssertCommand(["lvremove", "-f", "/".join([vgname, lvname1])], node=node_name)
911 21e2734f Bernardo Dal Seno
  AssertCommand(["lvremove", "-f", "/".join([vgname, lvname2])], node=node_name)
912 21e2734f Bernardo Dal Seno
  AssertClusterVerify()