Statistics
| Branch: | Tag: | Revision:

root / qa / qa_instance.py @ f7f03738

History | View | Annotate | Download (28.5 kB)

1 c68d1f43 Michael Hanselmann
#
2 c68d1f43 Michael Hanselmann
#
3 c68d1f43 Michael Hanselmann
4 deaa347b Bernardo Dal Seno
# Copyright (C) 2007, 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
"""Instance related QA tests.
23 cec9845c Michael Hanselmann

24 cec9845c Michael Hanselmann
"""
25 cec9845c Michael Hanselmann
26 c99200a3 Bernardo Dal Seno
import operator
27 d0a44ec0 Klaus Aehlig
import os
28 e8ae0c20 Michael Hanselmann
import re
29 e8ae0c20 Michael Hanselmann
30 cec9845c Michael Hanselmann
from ganeti import utils
31 5d640672 Michael Hanselmann
from ganeti import constants
32 288d6440 Michael Hanselmann
from ganeti import query
33 304d9f02 Michael Hanselmann
from ganeti import pathutils
34 cec9845c Michael Hanselmann
35 cec9845c Michael Hanselmann
import qa_config
36 5d640672 Michael Hanselmann
import qa_utils
37 e8ae0c20 Michael Hanselmann
import qa_error
38 e8ae0c20 Michael Hanselmann
39 cc27265e René Nussbaumer
from qa_utils import AssertIn, AssertCommand, AssertEqual
40 5fa0375e Michael Hanselmann
from qa_utils import InstanceCheck, INST_DOWN, INST_UP, FIRST_ARG, RETURN_VALUE
41 cec9845c Michael Hanselmann
42 e8ae0c20 Michael Hanselmann
43 e8ae0c20 Michael Hanselmann
def _GetDiskStatePath(disk):
44 e8ae0c20 Michael Hanselmann
  return "/sys/block/%s/device/state" % disk
45 cec9845c Michael Hanselmann
46 cec9845c Michael Hanselmann
47 59c75517 Michael Hanselmann
def _GetGenericAddParameters(inst, disk_template, force_mac=None):
48 8ccbbe4b Guido Trotter
  params = ["-B"]
49 8ccbbe4b Guido Trotter
  params.append("%s=%s,%s=%s" % (constants.BE_MINMEM,
50 8ccbbe4b Guido Trotter
                                 qa_config.get(constants.BE_MINMEM),
51 8ccbbe4b Guido Trotter
                                 constants.BE_MAXMEM,
52 8ccbbe4b Guido Trotter
                                 qa_config.get(constants.BE_MAXMEM)))
53 59c75517 Michael Hanselmann
54 59c75517 Michael Hanselmann
  if disk_template != constants.DT_DISKLESS:
55 59c75517 Michael Hanselmann
    for idx, size in enumerate(qa_config.get("disk")):
56 59c75517 Michael Hanselmann
      params.extend(["--disk", "%s:size=%s" % (idx, size)])
57 f346a7d9 Michael Hanselmann
58 f346a7d9 Michael Hanselmann
  # Set static MAC address if configured
59 1c573fb4 Iustin Pop
  if force_mac:
60 1c573fb4 Iustin Pop
    nic0_mac = force_mac
61 1c573fb4 Iustin Pop
  else:
62 0afce24e Michael Hanselmann
    nic0_mac = inst.GetNicMacAddr(0, None)
63 0afce24e Michael Hanselmann
64 f346a7d9 Michael Hanselmann
  if nic0_mac:
65 f346a7d9 Michael Hanselmann
    params.extend(["--net", "0:mac=%s" % nic0_mac])
66 f346a7d9 Michael Hanselmann
67 1d693311 Michael Hanselmann
  return params
68 5d640672 Michael Hanselmann
69 5d640672 Michael Hanselmann
70 fa84c8a4 Bernardo Dal Seno
def _DiskTest(node, disk_template, fail=False):
71 cec9845c Michael Hanselmann
  instance = qa_config.AcquireInstance()
72 cec9845c Michael Hanselmann
  try:
73 d0c8c01d Iustin Pop
    cmd = (["gnt-instance", "add",
74 d0c8c01d Iustin Pop
            "--os-type=%s" % qa_config.get("os"),
75 d0c8c01d Iustin Pop
            "--disk-template=%s" % disk_template,
76 d0c8c01d Iustin Pop
            "--node=%s" % node] +
77 59c75517 Michael Hanselmann
           _GetGenericAddParameters(instance, disk_template))
78 b5f33afa Michael Hanselmann
    cmd.append(instance.name)
79 cec9845c Michael Hanselmann
80 fa84c8a4 Bernardo Dal Seno
    AssertCommand(cmd, fail=fail)
81 6a343475 Michael Hanselmann
82 fa84c8a4 Bernardo Dal Seno
    if not fail:
83 46d21495 Bernardo Dal Seno
      _CheckSsconfInstanceList(instance.name)
84 46d21495 Bernardo Dal Seno
      instance.SetDiskTemplate(disk_template)
85 6a343475 Michael Hanselmann
86 fa84c8a4 Bernardo Dal Seno
      return instance
87 cec9845c Michael Hanselmann
  except:
88 6f88e076 Michael Hanselmann
    instance.Release()
89 cec9845c Michael Hanselmann
    raise
90 cec9845c Michael Hanselmann
91 fa84c8a4 Bernardo Dal Seno
  # Handle the case where creation is expected to fail
92 fa84c8a4 Bernardo Dal Seno
  assert fail
93 46d21495 Bernardo Dal Seno
  instance.Release()
94 fa84c8a4 Bernardo Dal Seno
  return None
95 fa84c8a4 Bernardo Dal Seno
96 cec9845c Michael Hanselmann
97 cc4b14f0 Bernardo Dal Seno
def _GetInstanceInfo(instance):
98 cc4b14f0 Bernardo Dal Seno
  """Return information about the actual state of an instance.
99 82d2f3df Bernardo Dal Seno

100 b07afbb3 Iustin Pop
  @type instance: string
101 b07afbb3 Iustin Pop
  @param instance: the instance name
102 f006f110 Bernardo Dal Seno
  @return: a dictionary with the following keys:
103 b07afbb3 Iustin Pop
      - "nodes": instance nodes, a list of strings
104 b07afbb3 Iustin Pop
      - "volumes": instance volume IDs, a list of strings
105 f006f110 Bernardo Dal Seno
      - "drbd-minors": DRBD minors used by the instance, a dictionary where
106 f006f110 Bernardo Dal Seno
        keys are nodes, and values are lists of integers (or an empty
107 f006f110 Bernardo Dal Seno
        dictionary for non-DRBD instances)
108 82d2f3df Bernardo Dal Seno

109 82d2f3df Bernardo Dal Seno
  """
110 82d2f3df Bernardo Dal Seno
  node_elem = r"([^,()]+)(?:\s+\([^)]+\))?"
111 82d2f3df Bernardo Dal Seno
  # re_nodelist matches a list of nodes returned by gnt-instance info, e.g.:
112 82d2f3df Bernardo Dal Seno
  #  node1.fqdn
113 82d2f3df Bernardo Dal Seno
  #  node2.fqdn,node3.fqdn
114 82d2f3df Bernardo Dal Seno
  #  node4.fqdn (group mygroup, group UUID 01234567-abcd-0123-4567-0123456789ab)
115 82d2f3df Bernardo Dal Seno
  # FIXME This works with no more than 2 secondaries
116 82d2f3df Bernardo Dal Seno
  re_nodelist = re.compile(node_elem + "(?:," + node_elem + ")?$")
117 2cbcf95d Bernardo Dal Seno
118 2cbcf95d Bernardo Dal Seno
  info = qa_utils.GetObjectInfo(["gnt-instance", "info", instance])[0]
119 82d2f3df Bernardo Dal Seno
  nodes = []
120 2cbcf95d Bernardo Dal Seno
  for nodeinfo in info["Nodes"]:
121 2cbcf95d Bernardo Dal Seno
    if "primary" in nodeinfo:
122 2cbcf95d Bernardo Dal Seno
      nodes.append(nodeinfo["primary"])
123 2cbcf95d Bernardo Dal Seno
    elif "secondaries" in nodeinfo:
124 2cbcf95d Bernardo Dal Seno
      nodestr = nodeinfo["secondaries"]
125 2cbcf95d Bernardo Dal Seno
      if nodestr:
126 2cbcf95d Bernardo Dal Seno
        m = re_nodelist.match(nodestr)
127 2cbcf95d Bernardo Dal Seno
        if m:
128 2cbcf95d Bernardo Dal Seno
          nodes.extend(filter(None, m.groups()))
129 2cbcf95d Bernardo Dal Seno
        else:
130 2cbcf95d Bernardo Dal Seno
          nodes.append(nodestr)
131 2cbcf95d Bernardo Dal Seno
132 2cbcf95d Bernardo Dal Seno
  re_drbdnode = re.compile(r"^([^\s,]+),\s+minor=([0-9]+)$")
133 82d2f3df Bernardo Dal Seno
  vols = []
134 f006f110 Bernardo Dal Seno
  drbd_min = {}
135 2cbcf95d Bernardo Dal Seno
  for (count, diskinfo) in enumerate(info["Disks"]):
136 2cbcf95d Bernardo Dal Seno
    (dtype, _) = diskinfo["disk/%s" % count].split(",", 1)
137 2cbcf95d Bernardo Dal Seno
    if dtype == constants.LD_DRBD8:
138 2cbcf95d Bernardo Dal Seno
      for child in diskinfo["child devices"]:
139 2cbcf95d Bernardo Dal Seno
        vols.append(child["logical_id"])
140 2cbcf95d Bernardo Dal Seno
      for key in ["nodeA", "nodeB"]:
141 2cbcf95d Bernardo Dal Seno
        m = re_drbdnode.match(diskinfo[key])
142 2cbcf95d Bernardo Dal Seno
        if not m:
143 2cbcf95d Bernardo Dal Seno
          raise qa_error.Error("Cannot parse DRBD info: %s" % diskinfo[key])
144 2cbcf95d Bernardo Dal Seno
        node = m.group(1)
145 2cbcf95d Bernardo Dal Seno
        minor = int(m.group(2))
146 2cbcf95d Bernardo Dal Seno
        minorlist = drbd_min.setdefault(node, [])
147 2cbcf95d Bernardo Dal Seno
        minorlist.append(minor)
148 2cbcf95d Bernardo Dal Seno
    elif dtype == constants.LD_LV:
149 2cbcf95d Bernardo Dal Seno
      vols.append(diskinfo["logical_id"])
150 b296c810 Michael Hanselmann
151 82d2f3df Bernardo Dal Seno
  assert nodes
152 b296c810 Michael Hanselmann
  assert len(nodes) < 2 or vols
153 1a6db3df Michael Hanselmann
  return {
154 1a6db3df Michael Hanselmann
    "nodes": nodes,
155 1a6db3df Michael Hanselmann
    "volumes": vols,
156 1a6db3df Michael Hanselmann
    "drbd-minors": drbd_min,
157 1a6db3df Michael Hanselmann
    }
158 cc4b14f0 Bernardo Dal Seno
159 cc4b14f0 Bernardo Dal Seno
160 cc4b14f0 Bernardo Dal Seno
def _DestroyInstanceVolumes(instance):
161 cc4b14f0 Bernardo Dal Seno
  """Remove all the LVM volumes of an instance.
162 cc4b14f0 Bernardo Dal Seno

163 cc4b14f0 Bernardo Dal Seno
  This is used to simulate HW errors (dead nodes, broken disks...); the
164 cc4b14f0 Bernardo Dal Seno
  configuration of the instance is not affected.
165 cc4b14f0 Bernardo Dal Seno
  @type instance: dictionary
166 cc4b14f0 Bernardo Dal Seno
  @param instance: the instance
167 cc4b14f0 Bernardo Dal Seno

168 cc4b14f0 Bernardo Dal Seno
  """
169 b5f33afa Michael Hanselmann
  info = _GetInstanceInfo(instance.name)
170 cc4b14f0 Bernardo Dal Seno
  vols = info["volumes"]
171 cc4b14f0 Bernardo Dal Seno
  for node in info["nodes"]:
172 82d2f3df Bernardo Dal Seno
    AssertCommand(["lvremove", "-f"] + vols, node=node)
173 82d2f3df Bernardo Dal Seno
174 82d2f3df Bernardo Dal Seno
175 ab4832d1 Bernardo Dal Seno
def _GetInstanceField(instance, field):
176 ab4832d1 Bernardo Dal Seno
  """Get the value of a field of an instance.
177 d55408b0 Bernardo Dal Seno

178 d55408b0 Bernardo Dal Seno
  @type instance: string
179 d55408b0 Bernardo Dal Seno
  @param instance: Instance name
180 d55408b0 Bernardo Dal Seno
  @type field: string
181 d55408b0 Bernardo Dal Seno
  @param field: Name of the field
182 ab4832d1 Bernardo Dal Seno
  @rtype: string
183 d55408b0 Bernardo Dal Seno

184 d55408b0 Bernardo Dal Seno
  """
185 d55408b0 Bernardo Dal Seno
  master = qa_config.GetMasterNode()
186 d55408b0 Bernardo Dal Seno
  infocmd = utils.ShellQuoteArgs(["gnt-instance", "list", "--no-headers",
187 ab4832d1 Bernardo Dal Seno
                                  "--units", "m", "-o", field, instance])
188 46d21495 Bernardo Dal Seno
  return qa_utils.GetCommandOutput(master.primary, infocmd).strip()
189 ab4832d1 Bernardo Dal Seno
190 ab4832d1 Bernardo Dal Seno
191 ab4832d1 Bernardo Dal Seno
def _GetBoolInstanceField(instance, field):
192 ab4832d1 Bernardo Dal Seno
  """Get the Boolean value of a field of an instance.
193 ab4832d1 Bernardo Dal Seno

194 ab4832d1 Bernardo Dal Seno
  @type instance: string
195 ab4832d1 Bernardo Dal Seno
  @param instance: Instance name
196 ab4832d1 Bernardo Dal Seno
  @type field: string
197 ab4832d1 Bernardo Dal Seno
  @param field: Name of the field
198 ab4832d1 Bernardo Dal Seno
  @rtype: bool
199 ab4832d1 Bernardo Dal Seno

200 ab4832d1 Bernardo Dal Seno
  """
201 ab4832d1 Bernardo Dal Seno
  info_out = _GetInstanceField(instance, field)
202 d55408b0 Bernardo Dal Seno
  if info_out == "Y":
203 d55408b0 Bernardo Dal Seno
    return True
204 d55408b0 Bernardo Dal Seno
  elif info_out == "N":
205 d55408b0 Bernardo Dal Seno
    return False
206 d55408b0 Bernardo Dal Seno
  else:
207 d55408b0 Bernardo Dal Seno
    raise qa_error.Error("Field %s of instance %s has a non-Boolean value:"
208 d55408b0 Bernardo Dal Seno
                         " %s" % (field, instance, info_out))
209 d55408b0 Bernardo Dal Seno
210 d55408b0 Bernardo Dal Seno
211 ab4832d1 Bernardo Dal Seno
def _GetNumInstanceField(instance, field):
212 ab4832d1 Bernardo Dal Seno
  """Get a numeric value of a field of an instance.
213 ab4832d1 Bernardo Dal Seno

214 ab4832d1 Bernardo Dal Seno
  @type instance: string
215 ab4832d1 Bernardo Dal Seno
  @param instance: Instance name
216 ab4832d1 Bernardo Dal Seno
  @type field: string
217 ab4832d1 Bernardo Dal Seno
  @param field: Name of the field
218 ab4832d1 Bernardo Dal Seno
  @rtype: int or float
219 ab4832d1 Bernardo Dal Seno

220 ab4832d1 Bernardo Dal Seno
  """
221 ab4832d1 Bernardo Dal Seno
  info_out = _GetInstanceField(instance, field)
222 ab4832d1 Bernardo Dal Seno
  try:
223 ab4832d1 Bernardo Dal Seno
    ret = int(info_out)
224 ab4832d1 Bernardo Dal Seno
  except ValueError:
225 ab4832d1 Bernardo Dal Seno
    try:
226 ab4832d1 Bernardo Dal Seno
      ret = float(info_out)
227 ab4832d1 Bernardo Dal Seno
    except ValueError:
228 ab4832d1 Bernardo Dal Seno
      raise qa_error.Error("Field %s of instance %s has a non-numeric value:"
229 ab4832d1 Bernardo Dal Seno
                           " %s" % (field, instance, info_out))
230 ab4832d1 Bernardo Dal Seno
  return ret
231 ab4832d1 Bernardo Dal Seno
232 ab4832d1 Bernardo Dal Seno
233 ab4832d1 Bernardo Dal Seno
def GetInstanceSpec(instance, spec):
234 ab4832d1 Bernardo Dal Seno
  """Return the current spec for the given parameter.
235 ab4832d1 Bernardo Dal Seno

236 ab4832d1 Bernardo Dal Seno
  @type instance: string
237 ab4832d1 Bernardo Dal Seno
  @param instance: Instance name
238 ab4832d1 Bernardo Dal Seno
  @type spec: string
239 ab4832d1 Bernardo Dal Seno
  @param spec: one of the supported parameters: "mem-size", "cpu-count",
240 ab4832d1 Bernardo Dal Seno
      "disk-count", "disk-size", "nic-count"
241 ab4832d1 Bernardo Dal Seno
  @rtype: tuple
242 ab4832d1 Bernardo Dal Seno
  @return: (minspec, maxspec); minspec and maxspec can be different only for
243 ab4832d1 Bernardo Dal Seno
      memory and disk size
244 ab4832d1 Bernardo Dal Seno

245 ab4832d1 Bernardo Dal Seno
  """
246 ab4832d1 Bernardo Dal Seno
  specmap = {
247 ab4832d1 Bernardo Dal Seno
    "mem-size": ["be/minmem", "be/maxmem"],
248 ab4832d1 Bernardo Dal Seno
    "cpu-count": ["vcpus"],
249 ab4832d1 Bernardo Dal Seno
    "disk-count": ["disk.count"],
250 ab4832d1 Bernardo Dal Seno
    "disk-size": ["disk.size/ "],
251 ab4832d1 Bernardo Dal Seno
    "nic-count": ["nic.count"],
252 ab4832d1 Bernardo Dal Seno
    }
253 ab4832d1 Bernardo Dal Seno
  # For disks, first we need the number of disks
254 ab4832d1 Bernardo Dal Seno
  if spec == "disk-size":
255 ab4832d1 Bernardo Dal Seno
    (numdisk, _) = GetInstanceSpec(instance, "disk-count")
256 ab4832d1 Bernardo Dal Seno
    fields = ["disk.size/%s" % k for k in range(0, numdisk)]
257 ab4832d1 Bernardo Dal Seno
  else:
258 ab4832d1 Bernardo Dal Seno
    assert spec in specmap, "%s not in %s" % (spec, specmap)
259 ab4832d1 Bernardo Dal Seno
    fields = specmap[spec]
260 ab4832d1 Bernardo Dal Seno
  values = [_GetNumInstanceField(instance, f) for f in fields]
261 ab4832d1 Bernardo Dal Seno
  return (min(values), max(values))
262 ab4832d1 Bernardo Dal Seno
263 ab4832d1 Bernardo Dal Seno
264 5de31440 Bernardo Dal Seno
def IsFailoverSupported(instance):
265 02a5fe0e Michael Hanselmann
  return instance.disk_template in constants.DTS_MIRRORED
266 5de31440 Bernardo Dal Seno
267 5de31440 Bernardo Dal Seno
268 5de31440 Bernardo Dal Seno
def IsMigrationSupported(instance):
269 02a5fe0e Michael Hanselmann
  return instance.disk_template in constants.DTS_MIRRORED
270 5de31440 Bernardo Dal Seno
271 5de31440 Bernardo Dal Seno
272 5de31440 Bernardo Dal Seno
def IsDiskReplacingSupported(instance):
273 02a5fe0e Michael Hanselmann
  return instance.disk_template == constants.DT_DRBD8
274 5de31440 Bernardo Dal Seno
275 5de31440 Bernardo Dal Seno
276 fa84c8a4 Bernardo Dal Seno
def TestInstanceAddWithPlainDisk(nodes, fail=False):
277 cec9845c Michael Hanselmann
  """gnt-instance add -t plain"""
278 c99200a3 Bernardo Dal Seno
  assert len(nodes) == 1
279 46d21495 Bernardo Dal Seno
  instance = _DiskTest(nodes[0].primary, constants.DT_PLAIN, fail=fail)
280 fa84c8a4 Bernardo Dal Seno
  if not fail:
281 fa84c8a4 Bernardo Dal Seno
    qa_utils.RunInstanceCheck(instance, True)
282 fa84c8a4 Bernardo Dal Seno
  return instance
283 cec9845c Michael Hanselmann
284 cec9845c Michael Hanselmann
285 5fa0375e Michael Hanselmann
@InstanceCheck(None, INST_UP, RETURN_VALUE)
286 c99200a3 Bernardo Dal Seno
def TestInstanceAddWithDrbdDisk(nodes):
287 7d7609a3 Michael Hanselmann
  """gnt-instance add -t drbd"""
288 c99200a3 Bernardo Dal Seno
  assert len(nodes) == 2
289 aecba21e Michael Hanselmann
  return _DiskTest(":".join(map(operator.attrgetter("primary"), nodes)),
290 68c8c3df Michael Hanselmann
                   constants.DT_DRBD8)
291 7d7609a3 Michael Hanselmann
292 7d7609a3 Michael Hanselmann
293 59c75517 Michael Hanselmann
@InstanceCheck(None, INST_UP, RETURN_VALUE)
294 6970c89c Klaus Aehlig
def TestInstanceAddFile(nodes):
295 6970c89c Klaus Aehlig
  """gnt-instance add -t file"""
296 6970c89c Klaus Aehlig
  assert len(nodes) == 1
297 6970c89c Klaus Aehlig
  return _DiskTest(nodes[0].primary, constants.DT_FILE)
298 6970c89c Klaus Aehlig
299 6970c89c Klaus Aehlig
300 6970c89c Klaus Aehlig
@InstanceCheck(None, INST_UP, RETURN_VALUE)
301 59c75517 Michael Hanselmann
def TestInstanceAddDiskless(nodes):
302 59c75517 Michael Hanselmann
  """gnt-instance add -t diskless"""
303 59c75517 Michael Hanselmann
  assert len(nodes) == 1
304 59c75517 Michael Hanselmann
  return _DiskTest(nodes[0].primary, constants.DT_DISKLESS)
305 59c75517 Michael Hanselmann
306 59c75517 Michael Hanselmann
307 5fa0375e Michael Hanselmann
@InstanceCheck(None, INST_DOWN, FIRST_ARG)
308 cec9845c Michael Hanselmann
def TestInstanceRemove(instance):
309 cec9845c Michael Hanselmann
  """gnt-instance remove"""
310 b5f33afa Michael Hanselmann
  AssertCommand(["gnt-instance", "remove", "-f", instance.name])
311 cec9845c Michael Hanselmann
312 cec9845c Michael Hanselmann
313 5fa0375e Michael Hanselmann
@InstanceCheck(INST_DOWN, INST_UP, FIRST_ARG)
314 cec9845c Michael Hanselmann
def TestInstanceStartup(instance):
315 cec9845c Michael Hanselmann
  """gnt-instance startup"""
316 b5f33afa Michael Hanselmann
  AssertCommand(["gnt-instance", "startup", instance.name])
317 cec9845c Michael Hanselmann
318 cec9845c Michael Hanselmann
319 5fa0375e Michael Hanselmann
@InstanceCheck(INST_UP, INST_DOWN, FIRST_ARG)
320 cec9845c Michael Hanselmann
def TestInstanceShutdown(instance):
321 cec9845c Michael Hanselmann
  """gnt-instance shutdown"""
322 b5f33afa Michael Hanselmann
  AssertCommand(["gnt-instance", "shutdown", instance.name])
323 cec9845c Michael Hanselmann
324 cec9845c Michael Hanselmann
325 5fa0375e Michael Hanselmann
@InstanceCheck(INST_UP, INST_UP, FIRST_ARG)
326 8a4e8898 Michael Hanselmann
def TestInstanceReboot(instance):
327 8a4e8898 Michael Hanselmann
  """gnt-instance reboot"""
328 d0c8c01d Iustin Pop
  options = qa_config.get("options", {})
329 1d103c02 Iustin Pop
  reboot_types = options.get("reboot-types", constants.REBOOT_TYPES)
330 b5f33afa Michael Hanselmann
  name = instance.name
331 1d103c02 Iustin Pop
  for rtype in reboot_types:
332 2f4b4f78 Iustin Pop
    AssertCommand(["gnt-instance", "reboot", "--type=%s" % rtype, name])
333 8a4e8898 Michael Hanselmann
334 cc27265e René Nussbaumer
  AssertCommand(["gnt-instance", "shutdown", name])
335 5fa0375e Michael Hanselmann
  qa_utils.RunInstanceCheck(instance, False)
336 cc27265e René Nussbaumer
  AssertCommand(["gnt-instance", "reboot", name])
337 cc27265e René Nussbaumer
338 cc27265e René Nussbaumer
  master = qa_config.GetMasterNode()
339 58ea8d17 Michael Hanselmann
  cmd = ["gnt-instance", "list", "--no-headers", "-o", "status", name]
340 aecba21e Michael Hanselmann
  result_output = qa_utils.GetCommandOutput(master.primary,
341 cc27265e René Nussbaumer
                                            utils.ShellQuoteArgs(cmd))
342 cc27265e René Nussbaumer
  AssertEqual(result_output.strip(), constants.INSTST_RUNNING)
343 cc27265e René Nussbaumer
344 8a4e8898 Michael Hanselmann
345 5fa0375e Michael Hanselmann
@InstanceCheck(INST_DOWN, INST_DOWN, FIRST_ARG)
346 283f9d4c Michael Hanselmann
def TestInstanceReinstall(instance):
347 283f9d4c Michael Hanselmann
  """gnt-instance reinstall"""
348 a90636b2 Michael Hanselmann
  if instance.disk_template == constants.DT_DISKLESS:
349 a90636b2 Michael Hanselmann
    print qa_utils.FormatInfo("Test not supported for diskless instances")
350 a90636b2 Michael Hanselmann
    return
351 a90636b2 Michael Hanselmann
352 b5f33afa Michael Hanselmann
  AssertCommand(["gnt-instance", "reinstall", "-f", instance.name])
353 283f9d4c Michael Hanselmann
354 64be07b1 Michael Hanselmann
  # Test with non-existant OS definition
355 64be07b1 Michael Hanselmann
  AssertCommand(["gnt-instance", "reinstall", "-f",
356 64be07b1 Michael Hanselmann
                 "--os-type=NonExistantOsForQa",
357 b5f33afa Michael Hanselmann
                 instance.name],
358 64be07b1 Michael Hanselmann
                fail=True)
359 64be07b1 Michael Hanselmann
360 283f9d4c Michael Hanselmann
361 6a343475 Michael Hanselmann
def _ReadSsconfInstanceList():
362 6a343475 Michael Hanselmann
  """Reads ssconf_instance_list from the master node.
363 6a343475 Michael Hanselmann

364 6a343475 Michael Hanselmann
  """
365 6a343475 Michael Hanselmann
  master = qa_config.GetMasterNode()
366 6a343475 Michael Hanselmann
367 e35c341e Michael Hanselmann
  ssconf_path = utils.PathJoin(pathutils.DATA_DIR,
368 e35c341e Michael Hanselmann
                               "ssconf_%s" % constants.SS_INSTANCE_LIST)
369 e35c341e Michael Hanselmann
370 e35c341e Michael Hanselmann
  cmd = ["cat", qa_utils.MakeNodePath(master, ssconf_path)]
371 6a343475 Michael Hanselmann
372 aecba21e Michael Hanselmann
  return qa_utils.GetCommandOutput(master.primary,
373 6a343475 Michael Hanselmann
                                   utils.ShellQuoteArgs(cmd)).splitlines()
374 6a343475 Michael Hanselmann
375 6a343475 Michael Hanselmann
376 6a343475 Michael Hanselmann
def _CheckSsconfInstanceList(instance):
377 6a343475 Michael Hanselmann
  """Checks if a certain instance is in the ssconf instance list.
378 6a343475 Michael Hanselmann

379 6a343475 Michael Hanselmann
  @type instance: string
380 6a343475 Michael Hanselmann
  @param instance: Instance name
381 6a343475 Michael Hanselmann

382 6a343475 Michael Hanselmann
  """
383 6a343475 Michael Hanselmann
  AssertIn(qa_utils.ResolveInstanceName(instance),
384 6a343475 Michael Hanselmann
           _ReadSsconfInstanceList())
385 6a343475 Michael Hanselmann
386 6a343475 Michael Hanselmann
387 51131cad Michael Hanselmann
@InstanceCheck(INST_DOWN, INST_DOWN, FIRST_ARG)
388 4c1a464b Iustin Pop
def TestInstanceRenameAndBack(rename_source, rename_target):
389 4c1a464b Iustin Pop
  """gnt-instance rename
390 4c1a464b Iustin Pop

391 4c1a464b Iustin Pop
  This must leave the instance with the original name, not the target
392 4c1a464b Iustin Pop
  name.
393 4c1a464b Iustin Pop

394 4c1a464b Iustin Pop
  """
395 31fe5102 René Nussbaumer
  _CheckSsconfInstanceList(rename_source)
396 5fa0375e Michael Hanselmann
397 4c1a464b Iustin Pop
  # first do a rename to a different actual name, expecting it to fail
398 31fe5102 René Nussbaumer
  qa_utils.AddToEtcHosts(["meeeeh-not-exists", rename_target])
399 31fe5102 René Nussbaumer
  try:
400 31fe5102 René Nussbaumer
    AssertCommand(["gnt-instance", "rename", rename_source, rename_target],
401 31fe5102 René Nussbaumer
                  fail=True)
402 31fe5102 René Nussbaumer
    _CheckSsconfInstanceList(rename_source)
403 31fe5102 René Nussbaumer
  finally:
404 31fe5102 René Nussbaumer
    qa_utils.RemoveFromEtcHosts(["meeeeh-not-exists", rename_target])
405 5fa0375e Michael Hanselmann
406 b07afbb3 Iustin Pop
  # Check instance volume tags correctly updated
407 b07afbb3 Iustin Pop
  # FIXME: this is LVM specific!
408 b07afbb3 Iustin Pop
  info = _GetInstanceInfo(rename_source)
409 b07afbb3 Iustin Pop
  tags_cmd = ("lvs -o tags --noheadings %s | grep " %
410 b07afbb3 Iustin Pop
              (" ".join(info["volumes"]), ))
411 b07afbb3 Iustin Pop
412 4c1a464b Iustin Pop
  # and now rename instance to rename_target...
413 31fe5102 René Nussbaumer
  AssertCommand(["gnt-instance", "rename", rename_source, rename_target])
414 31fe5102 René Nussbaumer
  _CheckSsconfInstanceList(rename_target)
415 5fa0375e Michael Hanselmann
  qa_utils.RunInstanceCheck(rename_source, False)
416 51131cad Michael Hanselmann
  qa_utils.RunInstanceCheck(rename_target, False)
417 5fa0375e Michael Hanselmann
418 b07afbb3 Iustin Pop
  # NOTE: tags might not be the exactly as the instance name, due to
419 b07afbb3 Iustin Pop
  # charset restrictions; hence the test might be flaky
420 b07afbb3 Iustin Pop
  if rename_source != rename_target:
421 b07afbb3 Iustin Pop
    for node in info["nodes"]:
422 b07afbb3 Iustin Pop
      AssertCommand(tags_cmd + rename_source, node=node, fail=True)
423 b07afbb3 Iustin Pop
      AssertCommand(tags_cmd + rename_target, node=node, fail=False)
424 b07afbb3 Iustin Pop
425 4c1a464b Iustin Pop
  # and back
426 4c1a464b Iustin Pop
  AssertCommand(["gnt-instance", "rename", rename_target, rename_source])
427 4c1a464b Iustin Pop
  _CheckSsconfInstanceList(rename_source)
428 5fa0375e Michael Hanselmann
  qa_utils.RunInstanceCheck(rename_target, False)
429 18337ca9 Iustin Pop
430 b07afbb3 Iustin Pop
  if rename_source != rename_target:
431 b07afbb3 Iustin Pop
    for node in info["nodes"]:
432 b07afbb3 Iustin Pop
      AssertCommand(tags_cmd + rename_source, node=node, fail=False)
433 b07afbb3 Iustin Pop
      AssertCommand(tags_cmd + rename_target, node=node, fail=True)
434 b07afbb3 Iustin Pop
435 18337ca9 Iustin Pop
436 5fa0375e Michael Hanselmann
@InstanceCheck(INST_UP, INST_UP, FIRST_ARG)
437 cec9845c Michael Hanselmann
def TestInstanceFailover(instance):
438 cec9845c Michael Hanselmann
  """gnt-instance failover"""
439 5de31440 Bernardo Dal Seno
  if not IsFailoverSupported(instance):
440 5de31440 Bernardo Dal Seno
    print qa_utils.FormatInfo("Instance doesn't support failover, skipping"
441 5de31440 Bernardo Dal Seno
                              " test")
442 5de31440 Bernardo Dal Seno
    return
443 5de31440 Bernardo Dal Seno
444 b5f33afa Michael Hanselmann
  cmd = ["gnt-instance", "failover", "--force", instance.name]
445 5fa0375e Michael Hanselmann
446 2f4b4f78 Iustin Pop
  # failover ...
447 2f4b4f78 Iustin Pop
  AssertCommand(cmd)
448 5fa0375e Michael Hanselmann
  qa_utils.RunInstanceCheck(instance, True)
449 5fa0375e Michael Hanselmann
450 76f59a32 Michael Hanselmann
  # ... and back
451 2f4b4f78 Iustin Pop
  AssertCommand(cmd)
452 76f59a32 Michael Hanselmann
453 cec9845c Michael Hanselmann
454 5fa0375e Michael Hanselmann
@InstanceCheck(INST_UP, INST_UP, FIRST_ARG)
455 d55408b0 Bernardo Dal Seno
def TestInstanceMigrate(instance, toggle_always_failover=True):
456 938bde86 Michael Hanselmann
  """gnt-instance migrate"""
457 5de31440 Bernardo Dal Seno
  if not IsMigrationSupported(instance):
458 5de31440 Bernardo Dal Seno
    print qa_utils.FormatInfo("Instance doesn't support migration, skipping"
459 5de31440 Bernardo Dal Seno
                              " test")
460 5de31440 Bernardo Dal Seno
    return
461 5de31440 Bernardo Dal Seno
462 b5f33afa Michael Hanselmann
  cmd = ["gnt-instance", "migrate", "--force", instance.name]
463 d55408b0 Bernardo Dal Seno
  af_par = constants.BE_ALWAYS_FAILOVER
464 d55408b0 Bernardo Dal Seno
  af_field = "be/" + constants.BE_ALWAYS_FAILOVER
465 b5f33afa Michael Hanselmann
  af_init_val = _GetBoolInstanceField(instance.name, af_field)
466 5fa0375e Michael Hanselmann
467 2f4b4f78 Iustin Pop
  # migrate ...
468 2f4b4f78 Iustin Pop
  AssertCommand(cmd)
469 d55408b0 Bernardo Dal Seno
  # TODO: Verify the choice between failover and migration
470 5fa0375e Michael Hanselmann
  qa_utils.RunInstanceCheck(instance, True)
471 5fa0375e Michael Hanselmann
472 d55408b0 Bernardo Dal Seno
  # ... and back (possibly with always_failover toggled)
473 d55408b0 Bernardo Dal Seno
  if toggle_always_failover:
474 d55408b0 Bernardo Dal Seno
    AssertCommand(["gnt-instance", "modify", "-B",
475 d55408b0 Bernardo Dal Seno
                   ("%s=%s" % (af_par, not af_init_val)),
476 b5f33afa Michael Hanselmann
                   instance.name])
477 2f4b4f78 Iustin Pop
  AssertCommand(cmd)
478 d55408b0 Bernardo Dal Seno
  # TODO: Verify the choice between failover and migration
479 d55408b0 Bernardo Dal Seno
  qa_utils.RunInstanceCheck(instance, True)
480 d55408b0 Bernardo Dal Seno
  if toggle_always_failover:
481 d55408b0 Bernardo Dal Seno
    AssertCommand(["gnt-instance", "modify", "-B",
482 b5f33afa Michael Hanselmann
                   ("%s=%s" % (af_par, af_init_val)), instance.name])
483 5fa0375e Michael Hanselmann
484 5fa0375e Michael Hanselmann
  # TODO: Split into multiple tests
485 b5f33afa Michael Hanselmann
  AssertCommand(["gnt-instance", "shutdown", instance.name])
486 5fa0375e Michael Hanselmann
  qa_utils.RunInstanceCheck(instance, False)
487 e9c487be René Nussbaumer
  AssertCommand(cmd, fail=True)
488 e9c487be René Nussbaumer
  AssertCommand(["gnt-instance", "migrate", "--force", "--allow-failover",
489 b5f33afa Michael Hanselmann
                 instance.name])
490 b5f33afa Michael Hanselmann
  AssertCommand(["gnt-instance", "start", instance.name])
491 e9c487be René Nussbaumer
  AssertCommand(cmd)
492 d55408b0 Bernardo Dal Seno
  # @InstanceCheck enforces the check that the instance is running
493 5fa0375e Michael Hanselmann
  qa_utils.RunInstanceCheck(instance, True)
494 5fa0375e Michael Hanselmann
495 42a769f9 Bernardo Dal Seno
  AssertCommand(["gnt-instance", "modify", "-B",
496 42a769f9 Bernardo Dal Seno
                 ("%s=%s" %
497 42a769f9 Bernardo Dal Seno
                  (constants.BE_ALWAYS_FAILOVER, constants.VALUE_TRUE)),
498 b5f33afa Michael Hanselmann
                 instance.name])
499 5fa0375e Michael Hanselmann
500 320a5dae Bernardo Dal Seno
  AssertCommand(cmd)
501 5fa0375e Michael Hanselmann
  qa_utils.RunInstanceCheck(instance, True)
502 320a5dae Bernardo Dal Seno
  # TODO: Verify that a failover has been done instead of a migration
503 5fa0375e Michael Hanselmann
504 5fa0375e Michael Hanselmann
  # TODO: Verify whether the default value is restored here (not hardcoded)
505 42a769f9 Bernardo Dal Seno
  AssertCommand(["gnt-instance", "modify", "-B",
506 42a769f9 Bernardo Dal Seno
                 ("%s=%s" %
507 42a769f9 Bernardo Dal Seno
                  (constants.BE_ALWAYS_FAILOVER, constants.VALUE_FALSE)),
508 b5f33afa Michael Hanselmann
                 instance.name])
509 5fa0375e Michael Hanselmann
510 42a769f9 Bernardo Dal Seno
  AssertCommand(cmd)
511 5fa0375e Michael Hanselmann
  qa_utils.RunInstanceCheck(instance, True)
512 938bde86 Michael Hanselmann
513 938bde86 Michael Hanselmann
514 cec9845c Michael Hanselmann
def TestInstanceInfo(instance):
515 cec9845c Michael Hanselmann
  """gnt-instance info"""
516 b5f33afa Michael Hanselmann
  AssertCommand(["gnt-instance", "info", instance.name])
517 5d640672 Michael Hanselmann
518 5d640672 Michael Hanselmann
519 5fa0375e Michael Hanselmann
@InstanceCheck(INST_UP, INST_UP, FIRST_ARG)
520 c0f74c55 Iustin Pop
def TestInstanceModify(instance):
521 c0f74c55 Iustin Pop
  """gnt-instance modify"""
522 d488adb6 Michael Hanselmann
  default_hv = qa_config.GetDefaultHypervisor()
523 d488adb6 Michael Hanselmann
524 1d693311 Michael Hanselmann
  # Assume /sbin/init exists on all systems
525 1d693311 Michael Hanselmann
  test_kernel = "/sbin/init"
526 1d693311 Michael Hanselmann
  test_initrd = test_kernel
527 1d693311 Michael Hanselmann
528 8ccbbe4b Guido Trotter
  orig_maxmem = qa_config.get(constants.BE_MAXMEM)
529 8ccbbe4b Guido Trotter
  orig_minmem = qa_config.get(constants.BE_MINMEM)
530 2f4b4f78 Iustin Pop
  #orig_bridge = qa_config.get("bridge", "xen-br0")
531 d488adb6 Michael Hanselmann
532 c0f74c55 Iustin Pop
  args = [
533 8ccbbe4b Guido Trotter
    ["-B", "%s=128" % constants.BE_MINMEM],
534 8ccbbe4b Guido Trotter
    ["-B", "%s=128" % constants.BE_MAXMEM],
535 8ccbbe4b Guido Trotter
    ["-B", "%s=%s,%s=%s" % (constants.BE_MINMEM, orig_minmem,
536 8ccbbe4b Guido Trotter
                            constants.BE_MAXMEM, orig_maxmem)],
537 1d693311 Michael Hanselmann
    ["-B", "%s=2" % constants.BE_VCPUS],
538 1d693311 Michael Hanselmann
    ["-B", "%s=1" % constants.BE_VCPUS],
539 1d693311 Michael Hanselmann
    ["-B", "%s=%s" % (constants.BE_VCPUS, constants.VALUE_DEFAULT)],
540 42a769f9 Bernardo Dal Seno
    ["-B", "%s=%s" % (constants.BE_ALWAYS_FAILOVER, constants.VALUE_TRUE)],
541 42a769f9 Bernardo Dal Seno
    ["-B", "%s=%s" % (constants.BE_ALWAYS_FAILOVER, constants.VALUE_DEFAULT)],
542 1d693311 Michael Hanselmann
543 1d693311 Michael Hanselmann
    ["-H", "%s=%s" % (constants.HV_KERNEL_PATH, test_kernel)],
544 1d693311 Michael Hanselmann
    ["-H", "%s=%s" % (constants.HV_KERNEL_PATH, constants.VALUE_DEFAULT)],
545 1d693311 Michael Hanselmann
546 1d693311 Michael Hanselmann
    # TODO: bridge tests
547 1d693311 Michael Hanselmann
    #["--bridge", "xen-br1"],
548 1d693311 Michael Hanselmann
    #["--bridge", orig_bridge],
549 c0f74c55 Iustin Pop
    ]
550 d488adb6 Michael Hanselmann
551 d488adb6 Michael Hanselmann
  if default_hv == constants.HT_XEN_PVM:
552 d488adb6 Michael Hanselmann
    args.extend([
553 d488adb6 Michael Hanselmann
      ["-H", "%s=%s" % (constants.HV_INITRD_PATH, test_initrd)],
554 d488adb6 Michael Hanselmann
      ["-H", "no_%s" % (constants.HV_INITRD_PATH, )],
555 d488adb6 Michael Hanselmann
      ["-H", "%s=%s" % (constants.HV_INITRD_PATH, constants.VALUE_DEFAULT)],
556 d488adb6 Michael Hanselmann
      ])
557 d488adb6 Michael Hanselmann
  elif default_hv == constants.HT_XEN_HVM:
558 d488adb6 Michael Hanselmann
    args.extend([
559 d488adb6 Michael Hanselmann
      ["-H", "%s=acn" % constants.HV_BOOT_ORDER],
560 d488adb6 Michael Hanselmann
      ["-H", "%s=%s" % (constants.HV_BOOT_ORDER, constants.VALUE_DEFAULT)],
561 d488adb6 Michael Hanselmann
      ])
562 d488adb6 Michael Hanselmann
563 c0f74c55 Iustin Pop
  for alist in args:
564 b5f33afa Michael Hanselmann
    AssertCommand(["gnt-instance", "modify"] + alist + [instance.name])
565 c0f74c55 Iustin Pop
566 c0f74c55 Iustin Pop
  # check no-modify
567 b5f33afa Michael Hanselmann
  AssertCommand(["gnt-instance", "modify", instance.name], fail=True)
568 c0f74c55 Iustin Pop
569 1ba25bad Guido Trotter
  # Marking offline while instance is running must fail...
570 b5f33afa Michael Hanselmann
  AssertCommand(["gnt-instance", "modify", "--offline", instance.name],
571 1ba25bad Guido Trotter
                 fail=True)
572 1ba25bad Guido Trotter
573 1ba25bad Guido Trotter
  # ...while making it online is ok, and should work
574 b5f33afa Michael Hanselmann
  AssertCommand(["gnt-instance", "modify", "--online", instance.name])
575 3016bc1f Michael Hanselmann
576 3016bc1f Michael Hanselmann
577 d0a44ec0 Klaus Aehlig
@InstanceCheck(INST_UP, INST_UP, FIRST_ARG)
578 d0a44ec0 Klaus Aehlig
def TestInstanceModifyPrimaryAndBack(instance, currentnode, othernode):
579 d0a44ec0 Klaus Aehlig
  """gnt-instance modify --new-primary
580 d0a44ec0 Klaus Aehlig

581 d0a44ec0 Klaus Aehlig
  This will leave the instance on its original primary node, not other node.
582 d0a44ec0 Klaus Aehlig

583 d0a44ec0 Klaus Aehlig
  """
584 d0a44ec0 Klaus Aehlig
  if instance.disk_template != constants.DT_FILE:
585 d0a44ec0 Klaus Aehlig
    print qa_utils.FormatInfo("Test only supported for the file disk template")
586 d0a44ec0 Klaus Aehlig
    return
587 d0a44ec0 Klaus Aehlig
588 d0a44ec0 Klaus Aehlig
  name = instance.name
589 d0a44ec0 Klaus Aehlig
  current = currentnode.primary
590 d0a44ec0 Klaus Aehlig
  other = othernode.primary
591 d0a44ec0 Klaus Aehlig
592 d0a44ec0 Klaus Aehlig
  filestorage = qa_config.get("file-storage-dir")
593 d0a44ec0 Klaus Aehlig
  disk = os.path.join(filestorage, name)
594 d0a44ec0 Klaus Aehlig
595 d0a44ec0 Klaus Aehlig
  AssertCommand(["gnt-instance", "modify", "--new-primary=%s" % other, name],
596 d0a44ec0 Klaus Aehlig
                fail=True)
597 d0a44ec0 Klaus Aehlig
  AssertCommand(["gnt-instance", "shutdown", name])
598 d0a44ec0 Klaus Aehlig
  AssertCommand(["scp", "-r", disk, "%s:%s" % (other, filestorage)])
599 d0a44ec0 Klaus Aehlig
  AssertCommand(["gnt-instance", "modify", "--new-primary=%s" % other, name])
600 d0a44ec0 Klaus Aehlig
  AssertCommand(["gnt-instance", "startup", name])
601 d0a44ec0 Klaus Aehlig
602 d0a44ec0 Klaus Aehlig
  # and back
603 d0a44ec0 Klaus Aehlig
  AssertCommand(["gnt-instance", "shutdown", name])
604 d0a44ec0 Klaus Aehlig
  AssertCommand(["rm", "-rf", disk], node=other)
605 d0a44ec0 Klaus Aehlig
  AssertCommand(["gnt-instance", "modify", "--new-primary=%s" % current, name])
606 d0a44ec0 Klaus Aehlig
  AssertCommand(["gnt-instance", "startup", name])
607 d0a44ec0 Klaus Aehlig
608 d0a44ec0 Klaus Aehlig
609 5fa0375e Michael Hanselmann
@InstanceCheck(INST_DOWN, INST_DOWN, FIRST_ARG)
610 3016bc1f Michael Hanselmann
def TestInstanceStoppedModify(instance):
611 3016bc1f Michael Hanselmann
  """gnt-instance modify (stopped instance)"""
612 b5f33afa Michael Hanselmann
  name = instance.name
613 3016bc1f Michael Hanselmann
614 58f0ce16 Michael Hanselmann
  # Instance was not marked offline; try marking it online once more
615 58f0ce16 Michael Hanselmann
  AssertCommand(["gnt-instance", "modify", "--online", name])
616 3016bc1f Michael Hanselmann
617 3016bc1f Michael Hanselmann
  # Mark instance as offline
618 3016bc1f Michael Hanselmann
  AssertCommand(["gnt-instance", "modify", "--offline", name])
619 3016bc1f Michael Hanselmann
620 1ba25bad Guido Trotter
  # When the instance is offline shutdown should only work with --force,
621 1ba25bad Guido Trotter
  # while start should never work
622 1ba25bad Guido Trotter
  AssertCommand(["gnt-instance", "shutdown", name], fail=True)
623 1ba25bad Guido Trotter
  AssertCommand(["gnt-instance", "shutdown", "--force", name])
624 1ba25bad Guido Trotter
  AssertCommand(["gnt-instance", "start", name], fail=True)
625 1ba25bad Guido Trotter
  AssertCommand(["gnt-instance", "start", "--force", name], fail=True)
626 1ba25bad Guido Trotter
627 1ba25bad Guido Trotter
  # Also do offline to offline
628 1ba25bad Guido Trotter
  AssertCommand(["gnt-instance", "modify", "--offline", name])
629 1ba25bad Guido Trotter
630 3016bc1f Michael Hanselmann
  # And online again
631 3016bc1f Michael Hanselmann
  AssertCommand(["gnt-instance", "modify", "--online", name])
632 3016bc1f Michael Hanselmann
633 c0f74c55 Iustin Pop
634 5fa0375e Michael Hanselmann
@InstanceCheck(INST_DOWN, INST_DOWN, FIRST_ARG)
635 c99200a3 Bernardo Dal Seno
def TestInstanceConvertDiskToPlain(instance, inodes):
636 7f69aabb Iustin Pop
  """gnt-instance modify -t"""
637 b5f33afa Michael Hanselmann
  name = instance.name
638 68c8c3df Michael Hanselmann
639 02a5fe0e Michael Hanselmann
  template = instance.disk_template
640 68c8c3df Michael Hanselmann
  if template != constants.DT_DRBD8:
641 5de31440 Bernardo Dal Seno
    print qa_utils.FormatInfo("Unsupported template %s, skipping conversion"
642 5de31440 Bernardo Dal Seno
                              " test" % template)
643 5de31440 Bernardo Dal Seno
    return
644 68c8c3df Michael Hanselmann
645 c99200a3 Bernardo Dal Seno
  assert len(inodes) == 2
646 68c8c3df Michael Hanselmann
  AssertCommand(["gnt-instance", "modify", "-t", constants.DT_PLAIN, name])
647 68c8c3df Michael Hanselmann
  AssertCommand(["gnt-instance", "modify", "-t", constants.DT_DRBD8,
648 aecba21e Michael Hanselmann
                 "-n", inodes[1].primary, name])
649 7f69aabb Iustin Pop
650 7f69aabb Iustin Pop
651 5fa0375e Michael Hanselmann
@InstanceCheck(INST_DOWN, INST_DOWN, FIRST_ARG)
652 26a5056d Iustin Pop
def TestInstanceGrowDisk(instance):
653 26a5056d Iustin Pop
  """gnt-instance grow-disk"""
654 5de31440 Bernardo Dal Seno
  if qa_config.GetExclusiveStorage():
655 5de31440 Bernardo Dal Seno
    print qa_utils.FormatInfo("Test not supported with exclusive_storage")
656 5de31440 Bernardo Dal Seno
    return
657 59c75517 Michael Hanselmann
658 59c75517 Michael Hanselmann
  if instance.disk_template == constants.DT_DISKLESS:
659 59c75517 Michael Hanselmann
    print qa_utils.FormatInfo("Test not supported for diskless instances")
660 59c75517 Michael Hanselmann
    return
661 59c75517 Michael Hanselmann
662 b5f33afa Michael Hanselmann
  name = instance.name
663 26a5056d Iustin Pop
  all_size = qa_config.get("disk")
664 26a5056d Iustin Pop
  all_grow = qa_config.get("disk-growth")
665 59c75517 Michael Hanselmann
666 26a5056d Iustin Pop
  if not all_grow:
667 26a5056d Iustin Pop
    # missing disk sizes but instance grow disk has been enabled,
668 26a5056d Iustin Pop
    # let's set fixed/nomimal growth
669 26a5056d Iustin Pop
    all_grow = ["128M" for _ in all_size]
670 59c75517 Michael Hanselmann
671 26a5056d Iustin Pop
  for idx, (size, grow) in enumerate(zip(all_size, all_grow)):
672 26a5056d Iustin Pop
    # succeed in grow by amount
673 26a5056d Iustin Pop
    AssertCommand(["gnt-instance", "grow-disk", name, str(idx), grow])
674 26a5056d Iustin Pop
    # fail in grow to the old size
675 26a5056d Iustin Pop
    AssertCommand(["gnt-instance", "grow-disk", "--absolute", name, str(idx),
676 26a5056d Iustin Pop
                   size], fail=True)
677 26a5056d Iustin Pop
    # succeed to grow to old size + 2 * growth
678 26a5056d Iustin Pop
    int_size = utils.ParseUnit(size)
679 26a5056d Iustin Pop
    int_grow = utils.ParseUnit(grow)
680 26a5056d Iustin Pop
    AssertCommand(["gnt-instance", "grow-disk", "--absolute", name, str(idx),
681 26a5056d Iustin Pop
                   str(int_size + 2 * int_grow)])
682 26a5056d Iustin Pop
683 26a5056d Iustin Pop
684 283f9d4c Michael Hanselmann
def TestInstanceList():
685 283f9d4c Michael Hanselmann
  """gnt-instance list"""
686 288d6440 Michael Hanselmann
  qa_utils.GenericQueryTest("gnt-instance", query.INSTANCE_FIELDS.keys())
687 283f9d4c Michael Hanselmann
688 283f9d4c Michael Hanselmann
689 2214cf14 Michael Hanselmann
def TestInstanceListFields():
690 2214cf14 Michael Hanselmann
  """gnt-instance list-fields"""
691 2214cf14 Michael Hanselmann
  qa_utils.GenericQueryFieldsTest("gnt-instance", query.INSTANCE_FIELDS.keys())
692 2214cf14 Michael Hanselmann
693 2214cf14 Michael Hanselmann
694 5fa0375e Michael Hanselmann
@InstanceCheck(INST_UP, INST_UP, FIRST_ARG)
695 4379b1fa Michael Hanselmann
def TestInstanceConsole(instance):
696 4379b1fa Michael Hanselmann
  """gnt-instance console"""
697 b5f33afa Michael Hanselmann
  AssertCommand(["gnt-instance", "console", "--show-cmd", instance.name])
698 4379b1fa Michael Hanselmann
699 4379b1fa Michael Hanselmann
700 5fa0375e Michael Hanselmann
@InstanceCheck(INST_UP, INST_UP, FIRST_ARG)
701 c99200a3 Bernardo Dal Seno
def TestReplaceDisks(instance, curr_nodes, other_nodes):
702 7910e7a5 Michael Hanselmann
  """gnt-instance replace-disks"""
703 7910e7a5 Michael Hanselmann
  def buildcmd(args):
704 d0c8c01d Iustin Pop
    cmd = ["gnt-instance", "replace-disks"]
705 7910e7a5 Michael Hanselmann
    cmd.extend(args)
706 b5f33afa Michael Hanselmann
    cmd.append(instance.name)
707 7910e7a5 Michael Hanselmann
    return cmd
708 7910e7a5 Michael Hanselmann
709 5de31440 Bernardo Dal Seno
  if not IsDiskReplacingSupported(instance):
710 5de31440 Bernardo Dal Seno
    print qa_utils.FormatInfo("Instance doesn't support disk replacing,"
711 5de31440 Bernardo Dal Seno
                              " skipping test")
712 5de31440 Bernardo Dal Seno
    return
713 5de31440 Bernardo Dal Seno
714 c99200a3 Bernardo Dal Seno
  # Currently all supported templates have one primary and one secondary node
715 c99200a3 Bernardo Dal Seno
  assert len(curr_nodes) == 2
716 c99200a3 Bernardo Dal Seno
  snode = curr_nodes[1]
717 c99200a3 Bernardo Dal Seno
  assert len(other_nodes) == 1
718 c99200a3 Bernardo Dal Seno
  othernode = other_nodes[0]
719 c99200a3 Bernardo Dal Seno
720 e85be22a Bernardo Dal Seno
  options = qa_config.get("options", {})
721 e85be22a Bernardo Dal Seno
  use_ialloc = options.get("use-iallocators", True)
722 2f4b4f78 Iustin Pop
  for data in [
723 2f4b4f78 Iustin Pop
    ["-p"],
724 2f4b4f78 Iustin Pop
    ["-s"],
725 e85be22a Bernardo Dal Seno
    # A placeholder; the actual command choice depends on use_ialloc
726 e85be22a Bernardo Dal Seno
    None,
727 e85be22a Bernardo Dal Seno
    # Restore the original secondary
728 aecba21e Michael Hanselmann
    ["--new-secondary=%s" % snode.primary],
729 2f4b4f78 Iustin Pop
    ]:
730 e85be22a Bernardo Dal Seno
    if data is None:
731 e85be22a Bernardo Dal Seno
      if use_ialloc:
732 e85be22a Bernardo Dal Seno
        data = ["-I", constants.DEFAULT_IALLOCATOR_SHORTCUT]
733 e85be22a Bernardo Dal Seno
      else:
734 aecba21e Michael Hanselmann
        data = ["--new-secondary=%s" % othernode.primary]
735 2f4b4f78 Iustin Pop
    AssertCommand(buildcmd(data))
736 7910e7a5 Michael Hanselmann
737 9026e935 René Nussbaumer
  AssertCommand(buildcmd(["-a"]))
738 b5f33afa Michael Hanselmann
  AssertCommand(["gnt-instance", "stop", instance.name])
739 9026e935 René Nussbaumer
  AssertCommand(buildcmd(["-a"]), fail=True)
740 b5f33afa Michael Hanselmann
  AssertCommand(["gnt-instance", "activate-disks", instance.name])
741 32da72f3 Iustin Pop
  AssertCommand(["gnt-instance", "activate-disks", "--wait-for-sync",
742 b5f33afa Michael Hanselmann
                 instance.name])
743 9026e935 René Nussbaumer
  AssertCommand(buildcmd(["-a"]))
744 b5f33afa Michael Hanselmann
  AssertCommand(["gnt-instance", "start", instance.name])
745 9026e935 René Nussbaumer
746 7910e7a5 Michael Hanselmann
747 83180411 Bernardo Dal Seno
def _AssertRecreateDisks(cmdargs, instance, fail=False, check=True,
748 83180411 Bernardo Dal Seno
                         destroy=True):
749 83180411 Bernardo Dal Seno
  """Execute gnt-instance recreate-disks and check the result
750 83180411 Bernardo Dal Seno

751 83180411 Bernardo Dal Seno
  @param cmdargs: Arguments (instance name excluded)
752 83180411 Bernardo Dal Seno
  @param instance: Instance to operate on
753 83180411 Bernardo Dal Seno
  @param fail: True if the command is expected to fail
754 83180411 Bernardo Dal Seno
  @param check: If True and fail is False, check that the disks work
755 83180411 Bernardo Dal Seno
  @prama destroy: If True, destroy the old disks first
756 83180411 Bernardo Dal Seno

757 83180411 Bernardo Dal Seno
  """
758 83180411 Bernardo Dal Seno
  if destroy:
759 83180411 Bernardo Dal Seno
    _DestroyInstanceVolumes(instance)
760 83180411 Bernardo Dal Seno
  AssertCommand((["gnt-instance", "recreate-disks"] + cmdargs +
761 b5f33afa Michael Hanselmann
                 [instance.name]), fail)
762 83180411 Bernardo Dal Seno
  if not fail and check:
763 83180411 Bernardo Dal Seno
    # Quick check that the disks are there
764 b5f33afa Michael Hanselmann
    AssertCommand(["gnt-instance", "activate-disks", instance.name])
765 32da72f3 Iustin Pop
    AssertCommand(["gnt-instance", "activate-disks", "--wait-for-sync",
766 b5f33afa Michael Hanselmann
                   instance.name])
767 b5f33afa Michael Hanselmann
    AssertCommand(["gnt-instance", "deactivate-disks", instance.name])
768 83180411 Bernardo Dal Seno
769 a1cd2ecf Bernardo Dal Seno
770 83180411 Bernardo Dal Seno
@InstanceCheck(INST_UP, INST_UP, FIRST_ARG)
771 c99200a3 Bernardo Dal Seno
def TestRecreateDisks(instance, inodes, othernodes):
772 83180411 Bernardo Dal Seno
  """gnt-instance recreate-disks
773 83180411 Bernardo Dal Seno

774 83180411 Bernardo Dal Seno
  @param instance: Instance to work on
775 c99200a3 Bernardo Dal Seno
  @param inodes: List of the current nodes of the instance
776 83180411 Bernardo Dal Seno
  @param othernodes: list/tuple of nodes where to temporarily recreate disks
777 83180411 Bernardo Dal Seno

778 83180411 Bernardo Dal Seno
  """
779 e85be22a Bernardo Dal Seno
  options = qa_config.get("options", {})
780 e85be22a Bernardo Dal Seno
  use_ialloc = options.get("use-iallocators", True)
781 aecba21e Michael Hanselmann
  other_seq = ":".join([n.primary for n in othernodes])
782 aecba21e Michael Hanselmann
  orig_seq = ":".join([n.primary for n in inodes])
783 a085d96d Bernardo Dal Seno
  # These fail because the instance is running
784 83180411 Bernardo Dal Seno
  _AssertRecreateDisks(["-n", other_seq], instance, fail=True, destroy=False)
785 e85be22a Bernardo Dal Seno
  if use_ialloc:
786 e85be22a Bernardo Dal Seno
    _AssertRecreateDisks(["-I", "hail"], instance, fail=True, destroy=False)
787 e85be22a Bernardo Dal Seno
  else:
788 e85be22a Bernardo Dal Seno
    _AssertRecreateDisks(["-n", other_seq], instance, fail=True, destroy=False)
789 b5f33afa Michael Hanselmann
  AssertCommand(["gnt-instance", "stop", instance.name])
790 83180411 Bernardo Dal Seno
  # Disks exist: this should fail
791 83180411 Bernardo Dal Seno
  _AssertRecreateDisks([], instance, fail=True, destroy=False)
792 83180411 Bernardo Dal Seno
  # Recreate disks in place
793 83180411 Bernardo Dal Seno
  _AssertRecreateDisks([], instance)
794 83180411 Bernardo Dal Seno
  # Move disks away
795 e85be22a Bernardo Dal Seno
  if use_ialloc:
796 e85be22a Bernardo Dal Seno
    _AssertRecreateDisks(["-I", "hail"], instance)
797 e85be22a Bernardo Dal Seno
    # Move disks somewhere else
798 e85be22a Bernardo Dal Seno
    _AssertRecreateDisks(["-I", constants.DEFAULT_IALLOCATOR_SHORTCUT],
799 e85be22a Bernardo Dal Seno
                         instance)
800 e85be22a Bernardo Dal Seno
  else:
801 e85be22a Bernardo Dal Seno
    _AssertRecreateDisks(["-n", other_seq], instance)
802 83180411 Bernardo Dal Seno
  # Move disks back
803 83180411 Bernardo Dal Seno
  _AssertRecreateDisks(["-n", orig_seq], instance, check=False)
804 83180411 Bernardo Dal Seno
  # This and InstanceCheck decoration check that the disks are working
805 b5f33afa Michael Hanselmann
  AssertCommand(["gnt-instance", "reinstall", "-f", instance.name])
806 b5f33afa Michael Hanselmann
  AssertCommand(["gnt-instance", "start", instance.name])
807 83180411 Bernardo Dal Seno
808 83180411 Bernardo Dal Seno
809 5fa0375e Michael Hanselmann
@InstanceCheck(INST_UP, INST_UP, FIRST_ARG)
810 5d640672 Michael Hanselmann
def TestInstanceExport(instance, node):
811 bc696589 Michael Hanselmann
  """gnt-backup export -n ..."""
812 b5f33afa Michael Hanselmann
  name = instance.name
813 aecba21e Michael Hanselmann
  AssertCommand(["gnt-backup", "export", "-n", node.primary, name])
814 2f4b4f78 Iustin Pop
  return qa_utils.ResolveInstanceName(name)
815 5d640672 Michael Hanselmann
816 5d640672 Michael Hanselmann
817 51131cad Michael Hanselmann
@InstanceCheck(None, INST_DOWN, FIRST_ARG)
818 8d8d650c Michael Hanselmann
def TestInstanceExportWithRemove(instance, node):
819 8d8d650c Michael Hanselmann
  """gnt-backup export --remove-instance"""
820 aecba21e Michael Hanselmann
  AssertCommand(["gnt-backup", "export", "-n", node.primary,
821 b5f33afa Michael Hanselmann
                 "--remove-instance", instance.name])
822 8d8d650c Michael Hanselmann
823 8d8d650c Michael Hanselmann
824 5fa0375e Michael Hanselmann
@InstanceCheck(INST_UP, INST_UP, FIRST_ARG)
825 bc696589 Michael Hanselmann
def TestInstanceExportNoTarget(instance):
826 bc696589 Michael Hanselmann
  """gnt-backup export (without target node, should fail)"""
827 b5f33afa Michael Hanselmann
  AssertCommand(["gnt-backup", "export", instance.name], fail=True)
828 bc696589 Michael Hanselmann
829 bc696589 Michael Hanselmann
830 51131cad Michael Hanselmann
@InstanceCheck(None, INST_DOWN, FIRST_ARG)
831 5fa0375e Michael Hanselmann
def TestInstanceImport(newinst, node, expnode, name):
832 5d640672 Michael Hanselmann
  """gnt-backup import"""
833 906a0346 Bernardo Dal Seno
  templ = constants.DT_PLAIN
834 d0c8c01d Iustin Pop
  cmd = (["gnt-backup", "import",
835 906a0346 Bernardo Dal Seno
          "--disk-template=%s" % templ,
836 d0c8c01d Iustin Pop
          "--no-ip-check",
837 aecba21e Michael Hanselmann
          "--src-node=%s" % expnode.primary,
838 304d9f02 Michael Hanselmann
          "--src-dir=%s/%s" % (pathutils.EXPORT_DIR, name),
839 aecba21e Michael Hanselmann
          "--node=%s" % node.primary] +
840 59c75517 Michael Hanselmann
         _GetGenericAddParameters(newinst, templ,
841 59c75517 Michael Hanselmann
                                  force_mac=constants.VALUE_GENERATE))
842 b5f33afa Michael Hanselmann
  cmd.append(newinst.name)
843 2f4b4f78 Iustin Pop
  AssertCommand(cmd)
844 02a5fe0e Michael Hanselmann
  newinst.SetDiskTemplate(templ)
845 283f9d4c Michael Hanselmann
846 283f9d4c Michael Hanselmann
847 283f9d4c Michael Hanselmann
def TestBackupList(expnode):
848 283f9d4c Michael Hanselmann
  """gnt-backup list"""
849 aecba21e Michael Hanselmann
  AssertCommand(["gnt-backup", "list", "--node=%s" % expnode.primary])
850 e8ae0c20 Michael Hanselmann
851 0fdf247d Michael Hanselmann
  qa_utils.GenericQueryTest("gnt-backup", query.EXPORT_FIELDS.keys(),
852 0fdf247d Michael Hanselmann
                            namefield=None, test_unknown=False)
853 0fdf247d Michael Hanselmann
854 0fdf247d Michael Hanselmann
855 0fdf247d Michael Hanselmann
def TestBackupListFields():
856 0fdf247d Michael Hanselmann
  """gnt-backup list-fields"""
857 0fdf247d Michael Hanselmann
  qa_utils.GenericQueryFieldsTest("gnt-backup", query.EXPORT_FIELDS.keys())
858 f006f110 Bernardo Dal Seno
859 f006f110 Bernardo Dal Seno
860 f006f110 Bernardo Dal Seno
def TestRemoveInstanceOfflineNode(instance, snode, set_offline, set_online):
861 f006f110 Bernardo Dal Seno
  """gtn-instance remove with an off-line node
862 f006f110 Bernardo Dal Seno

863 f006f110 Bernardo Dal Seno
  @param instance: instance
864 f006f110 Bernardo Dal Seno
  @param snode: secondary node, to be set offline
865 f006f110 Bernardo Dal Seno
  @param set_offline: function to call to set the node off-line
866 f006f110 Bernardo Dal Seno
  @param set_online: function to call to set the node on-line
867 f006f110 Bernardo Dal Seno

868 f006f110 Bernardo Dal Seno
  """
869 b5f33afa Michael Hanselmann
  info = _GetInstanceInfo(instance.name)
870 f006f110 Bernardo Dal Seno
  set_offline(snode)
871 f006f110 Bernardo Dal Seno
  try:
872 f006f110 Bernardo Dal Seno
    TestInstanceRemove(instance)
873 f006f110 Bernardo Dal Seno
  finally:
874 f006f110 Bernardo Dal Seno
    set_online(snode)
875 f006f110 Bernardo Dal Seno
  # Clean up the disks on the offline node
876 aecba21e Michael Hanselmann
  for minor in info["drbd-minors"][snode.primary]:
877 f006f110 Bernardo Dal Seno
    AssertCommand(["drbdsetup", str(minor), "down"], node=snode)
878 f006f110 Bernardo Dal Seno
  AssertCommand(["lvremove", "-f"] + info["volumes"], node=snode)