Statistics
| Branch: | Tag: | Revision:

root / qa / qa_instance.py @ f9b76ed4

History | View | Annotate | Download (38.8 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 d0a44ec0 Klaus Aehlig
import os
27 e8ae0c20 Michael Hanselmann
import re
28 e8ae0c20 Michael Hanselmann
29 cec9845c Michael Hanselmann
from ganeti import utils
30 5d640672 Michael Hanselmann
from ganeti import constants
31 288d6440 Michael Hanselmann
from ganeti import query
32 304d9f02 Michael Hanselmann
from ganeti import pathutils
33 cec9845c Michael Hanselmann
34 cec9845c Michael Hanselmann
import qa_config
35 5d640672 Michael Hanselmann
import qa_utils
36 e8ae0c20 Michael Hanselmann
import qa_error
37 e8ae0c20 Michael Hanselmann
38 8fada090 Michele Tartara
from qa_utils import AssertCommand, AssertEqual
39 5fa0375e Michael Hanselmann
from qa_utils import InstanceCheck, INST_DOWN, INST_UP, FIRST_ARG, RETURN_VALUE
40 8fada090 Michele Tartara
from qa_instance_utils import CheckSsconfInstanceList, \
41 8fada090 Michele Tartara
                              CreateInstanceDrbd8, \
42 8fada090 Michele Tartara
                              CreateInstanceByDiskTemplate, \
43 8fada090 Michele Tartara
                              CreateInstanceByDiskTemplateOneNode, \
44 8fada090 Michele Tartara
                              GetGenericAddParameters
45 cec9845c Michael Hanselmann
46 e8ae0c20 Michael Hanselmann
47 e8ae0c20 Michael Hanselmann
def _GetDiskStatePath(disk):
48 e8ae0c20 Michael Hanselmann
  return "/sys/block/%s/device/state" % disk
49 cec9845c Michael Hanselmann
50 cec9845c Michael Hanselmann
51 7af293d7 Thomas Thrainer
def GetInstanceInfo(instance):
52 cc4b14f0 Bernardo Dal Seno
  """Return information about the actual state of an instance.
53 82d2f3df Bernardo Dal Seno

54 b07afbb3 Iustin Pop
  @type instance: string
55 b07afbb3 Iustin Pop
  @param instance: the instance name
56 f006f110 Bernardo Dal Seno
  @return: a dictionary with the following keys:
57 b07afbb3 Iustin Pop
      - "nodes": instance nodes, a list of strings
58 b07afbb3 Iustin Pop
      - "volumes": instance volume IDs, a list of strings
59 f006f110 Bernardo Dal Seno
      - "drbd-minors": DRBD minors used by the instance, a dictionary where
60 f006f110 Bernardo Dal Seno
        keys are nodes, and values are lists of integers (or an empty
61 f006f110 Bernardo Dal Seno
        dictionary for non-DRBD instances)
62 1012ecf4 Guido Trotter
      - "disk-template": instance disk template
63 1012ecf4 Guido Trotter
      - "storage-type": storage type associated with the instance disk template
64 82d2f3df Bernardo Dal Seno

65 82d2f3df Bernardo Dal Seno
  """
66 82d2f3df Bernardo Dal Seno
  node_elem = r"([^,()]+)(?:\s+\([^)]+\))?"
67 82d2f3df Bernardo Dal Seno
  # re_nodelist matches a list of nodes returned by gnt-instance info, e.g.:
68 82d2f3df Bernardo Dal Seno
  #  node1.fqdn
69 82d2f3df Bernardo Dal Seno
  #  node2.fqdn,node3.fqdn
70 82d2f3df Bernardo Dal Seno
  #  node4.fqdn (group mygroup, group UUID 01234567-abcd-0123-4567-0123456789ab)
71 82d2f3df Bernardo Dal Seno
  # FIXME This works with no more than 2 secondaries
72 82d2f3df Bernardo Dal Seno
  re_nodelist = re.compile(node_elem + "(?:," + node_elem + ")?$")
73 2cbcf95d Bernardo Dal Seno
74 2cbcf95d Bernardo Dal Seno
  info = qa_utils.GetObjectInfo(["gnt-instance", "info", instance])[0]
75 82d2f3df Bernardo Dal Seno
  nodes = []
76 2cbcf95d Bernardo Dal Seno
  for nodeinfo in info["Nodes"]:
77 2cbcf95d Bernardo Dal Seno
    if "primary" in nodeinfo:
78 2cbcf95d Bernardo Dal Seno
      nodes.append(nodeinfo["primary"])
79 2cbcf95d Bernardo Dal Seno
    elif "secondaries" in nodeinfo:
80 2cbcf95d Bernardo Dal Seno
      nodestr = nodeinfo["secondaries"]
81 2cbcf95d Bernardo Dal Seno
      if nodestr:
82 2cbcf95d Bernardo Dal Seno
        m = re_nodelist.match(nodestr)
83 2cbcf95d Bernardo Dal Seno
        if m:
84 2cbcf95d Bernardo Dal Seno
          nodes.extend(filter(None, m.groups()))
85 2cbcf95d Bernardo Dal Seno
        else:
86 2cbcf95d Bernardo Dal Seno
          nodes.append(nodestr)
87 2cbcf95d Bernardo Dal Seno
88 1012ecf4 Guido Trotter
  disk_template = info["Disk template"]
89 1012ecf4 Guido Trotter
  if not disk_template:
90 1012ecf4 Guido Trotter
    raise qa_error.Error("Can't get instance disk template")
91 1012ecf4 Guido Trotter
  storage_type = constants.DISK_TEMPLATES_STORAGE_TYPE[disk_template]
92 1012ecf4 Guido Trotter
93 2cbcf95d Bernardo Dal Seno
  re_drbdnode = re.compile(r"^([^\s,]+),\s+minor=([0-9]+)$")
94 82d2f3df Bernardo Dal Seno
  vols = []
95 f006f110 Bernardo Dal Seno
  drbd_min = {}
96 2cbcf95d Bernardo Dal Seno
  for (count, diskinfo) in enumerate(info["Disks"]):
97 2cbcf95d Bernardo Dal Seno
    (dtype, _) = diskinfo["disk/%s" % count].split(",", 1)
98 2cbcf95d Bernardo Dal Seno
    if dtype == constants.LD_DRBD8:
99 2cbcf95d Bernardo Dal Seno
      for child in diskinfo["child devices"]:
100 2cbcf95d Bernardo Dal Seno
        vols.append(child["logical_id"])
101 2cbcf95d Bernardo Dal Seno
      for key in ["nodeA", "nodeB"]:
102 2cbcf95d Bernardo Dal Seno
        m = re_drbdnode.match(diskinfo[key])
103 2cbcf95d Bernardo Dal Seno
        if not m:
104 2cbcf95d Bernardo Dal Seno
          raise qa_error.Error("Cannot parse DRBD info: %s" % diskinfo[key])
105 2cbcf95d Bernardo Dal Seno
        node = m.group(1)
106 2cbcf95d Bernardo Dal Seno
        minor = int(m.group(2))
107 2cbcf95d Bernardo Dal Seno
        minorlist = drbd_min.setdefault(node, [])
108 2cbcf95d Bernardo Dal Seno
        minorlist.append(minor)
109 2cbcf95d Bernardo Dal Seno
    elif dtype == constants.LD_LV:
110 2cbcf95d Bernardo Dal Seno
      vols.append(diskinfo["logical_id"])
111 b296c810 Michael Hanselmann
112 82d2f3df Bernardo Dal Seno
  assert nodes
113 b296c810 Michael Hanselmann
  assert len(nodes) < 2 or vols
114 1a6db3df Michael Hanselmann
  return {
115 1a6db3df Michael Hanselmann
    "nodes": nodes,
116 1a6db3df Michael Hanselmann
    "volumes": vols,
117 1a6db3df Michael Hanselmann
    "drbd-minors": drbd_min,
118 1012ecf4 Guido Trotter
    "disk-template": disk_template,
119 1012ecf4 Guido Trotter
    "storage-type": storage_type,
120 1a6db3df Michael Hanselmann
    }
121 cc4b14f0 Bernardo Dal Seno
122 cc4b14f0 Bernardo Dal Seno
123 cc2a70b1 Guido Trotter
def _DestroyInstanceDisks(instance):
124 cc2a70b1 Guido Trotter
  """Remove all the backend disks of an instance.
125 cc4b14f0 Bernardo Dal Seno

126 cc4b14f0 Bernardo Dal Seno
  This is used to simulate HW errors (dead nodes, broken disks...); the
127 cc4b14f0 Bernardo Dal Seno
  configuration of the instance is not affected.
128 cc4b14f0 Bernardo Dal Seno
  @type instance: dictionary
129 cc4b14f0 Bernardo Dal Seno
  @param instance: the instance
130 cc4b14f0 Bernardo Dal Seno

131 cc4b14f0 Bernardo Dal Seno
  """
132 7af293d7 Thomas Thrainer
  info = GetInstanceInfo(instance.name)
133 cc2a70b1 Guido Trotter
  # FIXME: destruction/removal should be part of the disk class
134 cc2a70b1 Guido Trotter
  if info["storage-type"] == constants.ST_LVM_VG:
135 cc2a70b1 Guido Trotter
    vols = info["volumes"]
136 cc2a70b1 Guido Trotter
    for node in info["nodes"]:
137 cc2a70b1 Guido Trotter
      AssertCommand(["lvremove", "-f"] + vols, node=node)
138 cc2a70b1 Guido Trotter
  elif info["storage-type"] == constants.ST_FILE:
139 cc2a70b1 Guido Trotter
    # Note that this works for both file and sharedfile, and this is intended.
140 5949c31c Helga Velroyen
    storage_dir = qa_config.get("file-storage-dir",
141 5949c31c Helga Velroyen
                                pathutils.DEFAULT_FILE_STORAGE_DIR)
142 5949c31c Helga Velroyen
    idir = os.path.join(storage_dir, instance.name)
143 cc2a70b1 Guido Trotter
    for node in info["nodes"]:
144 b0b7bf8f Guido Trotter
      AssertCommand(["rm", "-rf", idir], node=node)
145 cc2a70b1 Guido Trotter
  elif info["storage-type"] == constants.ST_DISKLESS:
146 cc2a70b1 Guido Trotter
    pass
147 82d2f3df Bernardo Dal Seno
148 82d2f3df Bernardo Dal Seno
149 ab4832d1 Bernardo Dal Seno
def _GetInstanceField(instance, field):
150 ab4832d1 Bernardo Dal Seno
  """Get the value of a field of an instance.
151 d55408b0 Bernardo Dal Seno

152 d55408b0 Bernardo Dal Seno
  @type instance: string
153 d55408b0 Bernardo Dal Seno
  @param instance: Instance name
154 d55408b0 Bernardo Dal Seno
  @type field: string
155 d55408b0 Bernardo Dal Seno
  @param field: Name of the field
156 ab4832d1 Bernardo Dal Seno
  @rtype: string
157 d55408b0 Bernardo Dal Seno

158 d55408b0 Bernardo Dal Seno
  """
159 d55408b0 Bernardo Dal Seno
  master = qa_config.GetMasterNode()
160 d55408b0 Bernardo Dal Seno
  infocmd = utils.ShellQuoteArgs(["gnt-instance", "list", "--no-headers",
161 ab4832d1 Bernardo Dal Seno
                                  "--units", "m", "-o", field, instance])
162 46d21495 Bernardo Dal Seno
  return qa_utils.GetCommandOutput(master.primary, infocmd).strip()
163 ab4832d1 Bernardo Dal Seno
164 ab4832d1 Bernardo Dal Seno
165 ab4832d1 Bernardo Dal Seno
def _GetBoolInstanceField(instance, field):
166 ab4832d1 Bernardo Dal Seno
  """Get the Boolean value of a field of an instance.
167 ab4832d1 Bernardo Dal Seno

168 ab4832d1 Bernardo Dal Seno
  @type instance: string
169 ab4832d1 Bernardo Dal Seno
  @param instance: Instance name
170 ab4832d1 Bernardo Dal Seno
  @type field: string
171 ab4832d1 Bernardo Dal Seno
  @param field: Name of the field
172 ab4832d1 Bernardo Dal Seno
  @rtype: bool
173 ab4832d1 Bernardo Dal Seno

174 ab4832d1 Bernardo Dal Seno
  """
175 ab4832d1 Bernardo Dal Seno
  info_out = _GetInstanceField(instance, field)
176 d55408b0 Bernardo Dal Seno
  if info_out == "Y":
177 d55408b0 Bernardo Dal Seno
    return True
178 d55408b0 Bernardo Dal Seno
  elif info_out == "N":
179 d55408b0 Bernardo Dal Seno
    return False
180 d55408b0 Bernardo Dal Seno
  else:
181 d55408b0 Bernardo Dal Seno
    raise qa_error.Error("Field %s of instance %s has a non-Boolean value:"
182 d55408b0 Bernardo Dal Seno
                         " %s" % (field, instance, info_out))
183 d55408b0 Bernardo Dal Seno
184 d55408b0 Bernardo Dal Seno
185 ab4832d1 Bernardo Dal Seno
def _GetNumInstanceField(instance, field):
186 ab4832d1 Bernardo Dal Seno
  """Get a numeric value of a field of an instance.
187 ab4832d1 Bernardo Dal Seno

188 ab4832d1 Bernardo Dal Seno
  @type instance: string
189 ab4832d1 Bernardo Dal Seno
  @param instance: Instance name
190 ab4832d1 Bernardo Dal Seno
  @type field: string
191 ab4832d1 Bernardo Dal Seno
  @param field: Name of the field
192 ab4832d1 Bernardo Dal Seno
  @rtype: int or float
193 ab4832d1 Bernardo Dal Seno

194 ab4832d1 Bernardo Dal Seno
  """
195 ab4832d1 Bernardo Dal Seno
  info_out = _GetInstanceField(instance, field)
196 ab4832d1 Bernardo Dal Seno
  try:
197 ab4832d1 Bernardo Dal Seno
    ret = int(info_out)
198 ab4832d1 Bernardo Dal Seno
  except ValueError:
199 ab4832d1 Bernardo Dal Seno
    try:
200 ab4832d1 Bernardo Dal Seno
      ret = float(info_out)
201 ab4832d1 Bernardo Dal Seno
    except ValueError:
202 ab4832d1 Bernardo Dal Seno
      raise qa_error.Error("Field %s of instance %s has a non-numeric value:"
203 ab4832d1 Bernardo Dal Seno
                           " %s" % (field, instance, info_out))
204 ab4832d1 Bernardo Dal Seno
  return ret
205 ab4832d1 Bernardo Dal Seno
206 ab4832d1 Bernardo Dal Seno
207 ab4832d1 Bernardo Dal Seno
def GetInstanceSpec(instance, spec):
208 ab4832d1 Bernardo Dal Seno
  """Return the current spec for the given parameter.
209 ab4832d1 Bernardo Dal Seno

210 ab4832d1 Bernardo Dal Seno
  @type instance: string
211 ab4832d1 Bernardo Dal Seno
  @param instance: Instance name
212 ab4832d1 Bernardo Dal Seno
  @type spec: string
213 cb178a1e Bernardo Dal Seno
  @param spec: one of the supported parameters: "memory-size", "cpu-count",
214 ab4832d1 Bernardo Dal Seno
      "disk-count", "disk-size", "nic-count"
215 ab4832d1 Bernardo Dal Seno
  @rtype: tuple
216 ab4832d1 Bernardo Dal Seno
  @return: (minspec, maxspec); minspec and maxspec can be different only for
217 ab4832d1 Bernardo Dal Seno
      memory and disk size
218 ab4832d1 Bernardo Dal Seno

219 ab4832d1 Bernardo Dal Seno
  """
220 ab4832d1 Bernardo Dal Seno
  specmap = {
221 cb178a1e Bernardo Dal Seno
    "memory-size": ["be/minmem", "be/maxmem"],
222 ab4832d1 Bernardo Dal Seno
    "cpu-count": ["vcpus"],
223 ab4832d1 Bernardo Dal Seno
    "disk-count": ["disk.count"],
224 ab4832d1 Bernardo Dal Seno
    "disk-size": ["disk.size/ "],
225 ab4832d1 Bernardo Dal Seno
    "nic-count": ["nic.count"],
226 ab4832d1 Bernardo Dal Seno
    }
227 ab4832d1 Bernardo Dal Seno
  # For disks, first we need the number of disks
228 ab4832d1 Bernardo Dal Seno
  if spec == "disk-size":
229 ab4832d1 Bernardo Dal Seno
    (numdisk, _) = GetInstanceSpec(instance, "disk-count")
230 ab4832d1 Bernardo Dal Seno
    fields = ["disk.size/%s" % k for k in range(0, numdisk)]
231 ab4832d1 Bernardo Dal Seno
  else:
232 ab4832d1 Bernardo Dal Seno
    assert spec in specmap, "%s not in %s" % (spec, specmap)
233 ab4832d1 Bernardo Dal Seno
    fields = specmap[spec]
234 ab4832d1 Bernardo Dal Seno
  values = [_GetNumInstanceField(instance, f) for f in fields]
235 ab4832d1 Bernardo Dal Seno
  return (min(values), max(values))
236 ab4832d1 Bernardo Dal Seno
237 ab4832d1 Bernardo Dal Seno
238 5de31440 Bernardo Dal Seno
def IsFailoverSupported(instance):
239 02a5fe0e Michael Hanselmann
  return instance.disk_template in constants.DTS_MIRRORED
240 5de31440 Bernardo Dal Seno
241 5de31440 Bernardo Dal Seno
242 5de31440 Bernardo Dal Seno
def IsMigrationSupported(instance):
243 02a5fe0e Michael Hanselmann
  return instance.disk_template in constants.DTS_MIRRORED
244 5de31440 Bernardo Dal Seno
245 5de31440 Bernardo Dal Seno
246 5de31440 Bernardo Dal Seno
def IsDiskReplacingSupported(instance):
247 02a5fe0e Michael Hanselmann
  return instance.disk_template == constants.DT_DRBD8
248 5de31440 Bernardo Dal Seno
249 5de31440 Bernardo Dal Seno
250 8cd4f8cf Bernardo Dal Seno
def IsDiskSupported(instance):
251 a365b47f Bernardo Dal Seno
  return instance.disk_template != constants.DT_DISKLESS
252 8cd4f8cf Bernardo Dal Seno
253 8cd4f8cf Bernardo Dal Seno
254 fa84c8a4 Bernardo Dal Seno
def TestInstanceAddWithPlainDisk(nodes, fail=False):
255 cec9845c Michael Hanselmann
  """gnt-instance add -t plain"""
256 f41dc024 Helga Velroyen
  if constants.DT_PLAIN in qa_config.GetEnabledDiskTemplates():
257 8fada090 Michele Tartara
    instance = CreateInstanceByDiskTemplateOneNode(nodes, constants.DT_PLAIN,
258 f41dc024 Helga Velroyen
                                                    fail=fail)
259 f41dc024 Helga Velroyen
    if not fail:
260 f41dc024 Helga Velroyen
      qa_utils.RunInstanceCheck(instance, True)
261 f41dc024 Helga Velroyen
    return instance
262 cec9845c Michael Hanselmann
263 cec9845c Michael Hanselmann
264 5fa0375e Michael Hanselmann
@InstanceCheck(None, INST_UP, RETURN_VALUE)
265 c99200a3 Bernardo Dal Seno
def TestInstanceAddWithDrbdDisk(nodes):
266 7d7609a3 Michael Hanselmann
  """gnt-instance add -t drbd"""
267 f41dc024 Helga Velroyen
  if constants.DT_DRBD8 in qa_config.GetEnabledDiskTemplates():
268 8fada090 Michele Tartara
    return CreateInstanceDrbd8(nodes)
269 7d7609a3 Michael Hanselmann
270 7d7609a3 Michael Hanselmann
271 59c75517 Michael Hanselmann
@InstanceCheck(None, INST_UP, RETURN_VALUE)
272 6970c89c Klaus Aehlig
def TestInstanceAddFile(nodes):
273 6970c89c Klaus Aehlig
  """gnt-instance add -t file"""
274 6970c89c Klaus Aehlig
  assert len(nodes) == 1
275 f41dc024 Helga Velroyen
  if constants.DT_FILE in qa_config.GetEnabledDiskTemplates():
276 8fada090 Michele Tartara
    return CreateInstanceByDiskTemplateOneNode(nodes, constants.DT_FILE)
277 6970c89c Klaus Aehlig
278 6970c89c Klaus Aehlig
279 6970c89c Klaus Aehlig
@InstanceCheck(None, INST_UP, RETURN_VALUE)
280 f9b76ed4 Helga Velroyen
def TestInstanceAddSharedFile(nodes):
281 f9b76ed4 Helga Velroyen
  """gnt-instance add -t sharedfile"""
282 f9b76ed4 Helga Velroyen
  assert len(nodes) == 1
283 f9b76ed4 Helga Velroyen
  if constants.DT_SHARED_FILE in qa_config.GetEnabledDiskTemplates():
284 f9b76ed4 Helga Velroyen
    return CreateInstanceByDiskTemplateOneNode(nodes, constants.DT_SHARED_FILE)
285 f9b76ed4 Helga Velroyen
286 f9b76ed4 Helga Velroyen
287 f9b76ed4 Helga Velroyen
@InstanceCheck(None, INST_UP, RETURN_VALUE)
288 59c75517 Michael Hanselmann
def TestInstanceAddDiskless(nodes):
289 59c75517 Michael Hanselmann
  """gnt-instance add -t diskless"""
290 59c75517 Michael Hanselmann
  assert len(nodes) == 1
291 d06e7b3b Thomas Thrainer
  if constants.DT_DISKLESS in qa_config.GetEnabledDiskTemplates():
292 8fada090 Michele Tartara
    return CreateInstanceByDiskTemplateOneNode(nodes, constants.DT_DISKLESS)
293 59c75517 Michael Hanselmann
294 59c75517 Michael Hanselmann
295 5fa0375e Michael Hanselmann
@InstanceCheck(None, INST_DOWN, FIRST_ARG)
296 cec9845c Michael Hanselmann
def TestInstanceRemove(instance):
297 cec9845c Michael Hanselmann
  """gnt-instance remove"""
298 b5f33afa Michael Hanselmann
  AssertCommand(["gnt-instance", "remove", "-f", instance.name])
299 cec9845c Michael Hanselmann
300 cec9845c Michael Hanselmann
301 5fa0375e Michael Hanselmann
@InstanceCheck(INST_DOWN, INST_UP, FIRST_ARG)
302 cec9845c Michael Hanselmann
def TestInstanceStartup(instance):
303 cec9845c Michael Hanselmann
  """gnt-instance startup"""
304 b5f33afa Michael Hanselmann
  AssertCommand(["gnt-instance", "startup", instance.name])
305 cec9845c Michael Hanselmann
306 cec9845c Michael Hanselmann
307 5fa0375e Michael Hanselmann
@InstanceCheck(INST_UP, INST_DOWN, FIRST_ARG)
308 cec9845c Michael Hanselmann
def TestInstanceShutdown(instance):
309 cec9845c Michael Hanselmann
  """gnt-instance shutdown"""
310 b5f33afa Michael Hanselmann
  AssertCommand(["gnt-instance", "shutdown", instance.name])
311 cec9845c Michael Hanselmann
312 cec9845c Michael Hanselmann
313 5fa0375e Michael Hanselmann
@InstanceCheck(INST_UP, INST_UP, FIRST_ARG)
314 8a4e8898 Michael Hanselmann
def TestInstanceReboot(instance):
315 8a4e8898 Michael Hanselmann
  """gnt-instance reboot"""
316 d0c8c01d Iustin Pop
  options = qa_config.get("options", {})
317 1d103c02 Iustin Pop
  reboot_types = options.get("reboot-types", constants.REBOOT_TYPES)
318 b5f33afa Michael Hanselmann
  name = instance.name
319 1d103c02 Iustin Pop
  for rtype in reboot_types:
320 2f4b4f78 Iustin Pop
    AssertCommand(["gnt-instance", "reboot", "--type=%s" % rtype, name])
321 8a4e8898 Michael Hanselmann
322 cc27265e René Nussbaumer
  AssertCommand(["gnt-instance", "shutdown", name])
323 5fa0375e Michael Hanselmann
  qa_utils.RunInstanceCheck(instance, False)
324 cc27265e René Nussbaumer
  AssertCommand(["gnt-instance", "reboot", name])
325 cc27265e René Nussbaumer
326 cc27265e René Nussbaumer
  master = qa_config.GetMasterNode()
327 58ea8d17 Michael Hanselmann
  cmd = ["gnt-instance", "list", "--no-headers", "-o", "status", name]
328 aecba21e Michael Hanselmann
  result_output = qa_utils.GetCommandOutput(master.primary,
329 cc27265e René Nussbaumer
                                            utils.ShellQuoteArgs(cmd))
330 cc27265e René Nussbaumer
  AssertEqual(result_output.strip(), constants.INSTST_RUNNING)
331 cc27265e René Nussbaumer
332 8a4e8898 Michael Hanselmann
333 5fa0375e Michael Hanselmann
@InstanceCheck(INST_DOWN, INST_DOWN, FIRST_ARG)
334 283f9d4c Michael Hanselmann
def TestInstanceReinstall(instance):
335 283f9d4c Michael Hanselmann
  """gnt-instance reinstall"""
336 a90636b2 Michael Hanselmann
  if instance.disk_template == constants.DT_DISKLESS:
337 a90636b2 Michael Hanselmann
    print qa_utils.FormatInfo("Test not supported for diskless instances")
338 a90636b2 Michael Hanselmann
    return
339 a90636b2 Michael Hanselmann
340 b5f33afa Michael Hanselmann
  AssertCommand(["gnt-instance", "reinstall", "-f", instance.name])
341 283f9d4c Michael Hanselmann
342 64be07b1 Michael Hanselmann
  # Test with non-existant OS definition
343 64be07b1 Michael Hanselmann
  AssertCommand(["gnt-instance", "reinstall", "-f",
344 64be07b1 Michael Hanselmann
                 "--os-type=NonExistantOsForQa",
345 b5f33afa Michael Hanselmann
                 instance.name],
346 64be07b1 Michael Hanselmann
                fail=True)
347 64be07b1 Michael Hanselmann
348 283f9d4c Michael Hanselmann
349 51131cad Michael Hanselmann
@InstanceCheck(INST_DOWN, INST_DOWN, FIRST_ARG)
350 4c1a464b Iustin Pop
def TestInstanceRenameAndBack(rename_source, rename_target):
351 4c1a464b Iustin Pop
  """gnt-instance rename
352 4c1a464b Iustin Pop

353 4c1a464b Iustin Pop
  This must leave the instance with the original name, not the target
354 4c1a464b Iustin Pop
  name.
355 4c1a464b Iustin Pop

356 4c1a464b Iustin Pop
  """
357 8fada090 Michele Tartara
  CheckSsconfInstanceList(rename_source)
358 5fa0375e Michael Hanselmann
359 4c1a464b Iustin Pop
  # first do a rename to a different actual name, expecting it to fail
360 31fe5102 René Nussbaumer
  qa_utils.AddToEtcHosts(["meeeeh-not-exists", rename_target])
361 31fe5102 René Nussbaumer
  try:
362 31fe5102 René Nussbaumer
    AssertCommand(["gnt-instance", "rename", rename_source, rename_target],
363 31fe5102 René Nussbaumer
                  fail=True)
364 8fada090 Michele Tartara
    CheckSsconfInstanceList(rename_source)
365 31fe5102 René Nussbaumer
  finally:
366 31fe5102 René Nussbaumer
    qa_utils.RemoveFromEtcHosts(["meeeeh-not-exists", rename_target])
367 5fa0375e Michael Hanselmann
368 7af293d7 Thomas Thrainer
  info = GetInstanceInfo(rename_source)
369 1012ecf4 Guido Trotter
370 1012ecf4 Guido Trotter
  # Check instance volume tags correctly updated. Note that this check is lvm
371 1012ecf4 Guido Trotter
  # specific, so we skip it for non-lvm-based instances.
372 1012ecf4 Guido Trotter
  # FIXME: This will need updating when instances will be able to have
373 1012ecf4 Guido Trotter
  # different disks living on storage pools with etherogeneous storage types.
374 1012ecf4 Guido Trotter
  # FIXME: This check should be put inside the disk/storage class themselves,
375 1012ecf4 Guido Trotter
  # rather than explicitly called here.
376 1012ecf4 Guido Trotter
  if info["storage-type"] == constants.ST_LVM_VG:
377 1012ecf4 Guido Trotter
    # In the lvm world we can check for tags on the logical volume
378 1012ecf4 Guido Trotter
    tags_cmd = ("lvs -o tags --noheadings %s | grep " %
379 1012ecf4 Guido Trotter
                (" ".join(info["volumes"]), ))
380 1012ecf4 Guido Trotter
  else:
381 1012ecf4 Guido Trotter
    # Other storage types don't have tags, so we use an always failing command,
382 1012ecf4 Guido Trotter
    # to make sure it never gets executed
383 1012ecf4 Guido Trotter
    tags_cmd = "false"
384 b07afbb3 Iustin Pop
385 4c1a464b Iustin Pop
  # and now rename instance to rename_target...
386 31fe5102 René Nussbaumer
  AssertCommand(["gnt-instance", "rename", rename_source, rename_target])
387 8fada090 Michele Tartara
  CheckSsconfInstanceList(rename_target)
388 5fa0375e Michael Hanselmann
  qa_utils.RunInstanceCheck(rename_source, False)
389 51131cad Michael Hanselmann
  qa_utils.RunInstanceCheck(rename_target, False)
390 5fa0375e Michael Hanselmann
391 b07afbb3 Iustin Pop
  # NOTE: tags might not be the exactly as the instance name, due to
392 b07afbb3 Iustin Pop
  # charset restrictions; hence the test might be flaky
393 1012ecf4 Guido Trotter
  if (rename_source != rename_target and
394 1012ecf4 Guido Trotter
      info["storage-type"] == constants.ST_LVM_VG):
395 b07afbb3 Iustin Pop
    for node in info["nodes"]:
396 b07afbb3 Iustin Pop
      AssertCommand(tags_cmd + rename_source, node=node, fail=True)
397 b07afbb3 Iustin Pop
      AssertCommand(tags_cmd + rename_target, node=node, fail=False)
398 b07afbb3 Iustin Pop
399 4c1a464b Iustin Pop
  # and back
400 4c1a464b Iustin Pop
  AssertCommand(["gnt-instance", "rename", rename_target, rename_source])
401 8fada090 Michele Tartara
  CheckSsconfInstanceList(rename_source)
402 5fa0375e Michael Hanselmann
  qa_utils.RunInstanceCheck(rename_target, False)
403 18337ca9 Iustin Pop
404 1012ecf4 Guido Trotter
  if (rename_source != rename_target and
405 1012ecf4 Guido Trotter
      info["storage-type"] == constants.ST_LVM_VG):
406 b07afbb3 Iustin Pop
    for node in info["nodes"]:
407 b07afbb3 Iustin Pop
      AssertCommand(tags_cmd + rename_source, node=node, fail=False)
408 b07afbb3 Iustin Pop
      AssertCommand(tags_cmd + rename_target, node=node, fail=True)
409 b07afbb3 Iustin Pop
410 18337ca9 Iustin Pop
411 5fa0375e Michael Hanselmann
@InstanceCheck(INST_UP, INST_UP, FIRST_ARG)
412 cec9845c Michael Hanselmann
def TestInstanceFailover(instance):
413 cec9845c Michael Hanselmann
  """gnt-instance failover"""
414 5de31440 Bernardo Dal Seno
  if not IsFailoverSupported(instance):
415 5de31440 Bernardo Dal Seno
    print qa_utils.FormatInfo("Instance doesn't support failover, skipping"
416 5de31440 Bernardo Dal Seno
                              " test")
417 5de31440 Bernardo Dal Seno
    return
418 5de31440 Bernardo Dal Seno
419 b5f33afa Michael Hanselmann
  cmd = ["gnt-instance", "failover", "--force", instance.name]
420 5fa0375e Michael Hanselmann
421 2f4b4f78 Iustin Pop
  # failover ...
422 2f4b4f78 Iustin Pop
  AssertCommand(cmd)
423 5fa0375e Michael Hanselmann
  qa_utils.RunInstanceCheck(instance, True)
424 5fa0375e Michael Hanselmann
425 76f59a32 Michael Hanselmann
  # ... and back
426 2f4b4f78 Iustin Pop
  AssertCommand(cmd)
427 76f59a32 Michael Hanselmann
428 cec9845c Michael Hanselmann
429 5fa0375e Michael Hanselmann
@InstanceCheck(INST_UP, INST_UP, FIRST_ARG)
430 d55408b0 Bernardo Dal Seno
def TestInstanceMigrate(instance, toggle_always_failover=True):
431 938bde86 Michael Hanselmann
  """gnt-instance migrate"""
432 5de31440 Bernardo Dal Seno
  if not IsMigrationSupported(instance):
433 5de31440 Bernardo Dal Seno
    print qa_utils.FormatInfo("Instance doesn't support migration, skipping"
434 5de31440 Bernardo Dal Seno
                              " test")
435 5de31440 Bernardo Dal Seno
    return
436 5de31440 Bernardo Dal Seno
437 b5f33afa Michael Hanselmann
  cmd = ["gnt-instance", "migrate", "--force", instance.name]
438 d55408b0 Bernardo Dal Seno
  af_par = constants.BE_ALWAYS_FAILOVER
439 d55408b0 Bernardo Dal Seno
  af_field = "be/" + constants.BE_ALWAYS_FAILOVER
440 b5f33afa Michael Hanselmann
  af_init_val = _GetBoolInstanceField(instance.name, af_field)
441 5fa0375e Michael Hanselmann
442 2f4b4f78 Iustin Pop
  # migrate ...
443 2f4b4f78 Iustin Pop
  AssertCommand(cmd)
444 d55408b0 Bernardo Dal Seno
  # TODO: Verify the choice between failover and migration
445 5fa0375e Michael Hanselmann
  qa_utils.RunInstanceCheck(instance, True)
446 5fa0375e Michael Hanselmann
447 d55408b0 Bernardo Dal Seno
  # ... and back (possibly with always_failover toggled)
448 d55408b0 Bernardo Dal Seno
  if toggle_always_failover:
449 d55408b0 Bernardo Dal Seno
    AssertCommand(["gnt-instance", "modify", "-B",
450 d55408b0 Bernardo Dal Seno
                   ("%s=%s" % (af_par, not af_init_val)),
451 b5f33afa Michael Hanselmann
                   instance.name])
452 2f4b4f78 Iustin Pop
  AssertCommand(cmd)
453 d55408b0 Bernardo Dal Seno
  # TODO: Verify the choice between failover and migration
454 d55408b0 Bernardo Dal Seno
  qa_utils.RunInstanceCheck(instance, True)
455 d55408b0 Bernardo Dal Seno
  if toggle_always_failover:
456 d55408b0 Bernardo Dal Seno
    AssertCommand(["gnt-instance", "modify", "-B",
457 b5f33afa Michael Hanselmann
                   ("%s=%s" % (af_par, af_init_val)), instance.name])
458 5fa0375e Michael Hanselmann
459 5fa0375e Michael Hanselmann
  # TODO: Split into multiple tests
460 b5f33afa Michael Hanselmann
  AssertCommand(["gnt-instance", "shutdown", instance.name])
461 5fa0375e Michael Hanselmann
  qa_utils.RunInstanceCheck(instance, False)
462 e9c487be René Nussbaumer
  AssertCommand(cmd, fail=True)
463 e9c487be René Nussbaumer
  AssertCommand(["gnt-instance", "migrate", "--force", "--allow-failover",
464 b5f33afa Michael Hanselmann
                 instance.name])
465 b5f33afa Michael Hanselmann
  AssertCommand(["gnt-instance", "start", instance.name])
466 e9c487be René Nussbaumer
  AssertCommand(cmd)
467 d55408b0 Bernardo Dal Seno
  # @InstanceCheck enforces the check that the instance is running
468 5fa0375e Michael Hanselmann
  qa_utils.RunInstanceCheck(instance, True)
469 5fa0375e Michael Hanselmann
470 42a769f9 Bernardo Dal Seno
  AssertCommand(["gnt-instance", "modify", "-B",
471 42a769f9 Bernardo Dal Seno
                 ("%s=%s" %
472 42a769f9 Bernardo Dal Seno
                  (constants.BE_ALWAYS_FAILOVER, constants.VALUE_TRUE)),
473 b5f33afa Michael Hanselmann
                 instance.name])
474 5fa0375e Michael Hanselmann
475 320a5dae Bernardo Dal Seno
  AssertCommand(cmd)
476 5fa0375e Michael Hanselmann
  qa_utils.RunInstanceCheck(instance, True)
477 320a5dae Bernardo Dal Seno
  # TODO: Verify that a failover has been done instead of a migration
478 5fa0375e Michael Hanselmann
479 5fa0375e Michael Hanselmann
  # TODO: Verify whether the default value is restored here (not hardcoded)
480 42a769f9 Bernardo Dal Seno
  AssertCommand(["gnt-instance", "modify", "-B",
481 42a769f9 Bernardo Dal Seno
                 ("%s=%s" %
482 42a769f9 Bernardo Dal Seno
                  (constants.BE_ALWAYS_FAILOVER, constants.VALUE_FALSE)),
483 b5f33afa Michael Hanselmann
                 instance.name])
484 5fa0375e Michael Hanselmann
485 42a769f9 Bernardo Dal Seno
  AssertCommand(cmd)
486 5fa0375e Michael Hanselmann
  qa_utils.RunInstanceCheck(instance, True)
487 938bde86 Michael Hanselmann
488 938bde86 Michael Hanselmann
489 cec9845c Michael Hanselmann
def TestInstanceInfo(instance):
490 cec9845c Michael Hanselmann
  """gnt-instance info"""
491 b5f33afa Michael Hanselmann
  AssertCommand(["gnt-instance", "info", instance.name])
492 5d640672 Michael Hanselmann
493 5d640672 Michael Hanselmann
494 5fa0375e Michael Hanselmann
@InstanceCheck(INST_UP, INST_UP, FIRST_ARG)
495 c0f74c55 Iustin Pop
def TestInstanceModify(instance):
496 c0f74c55 Iustin Pop
  """gnt-instance modify"""
497 d488adb6 Michael Hanselmann
  default_hv = qa_config.GetDefaultHypervisor()
498 d488adb6 Michael Hanselmann
499 1d693311 Michael Hanselmann
  # Assume /sbin/init exists on all systems
500 1d693311 Michael Hanselmann
  test_kernel = "/sbin/init"
501 1d693311 Michael Hanselmann
  test_initrd = test_kernel
502 1d693311 Michael Hanselmann
503 8ccbbe4b Guido Trotter
  orig_maxmem = qa_config.get(constants.BE_MAXMEM)
504 8ccbbe4b Guido Trotter
  orig_minmem = qa_config.get(constants.BE_MINMEM)
505 2f4b4f78 Iustin Pop
  #orig_bridge = qa_config.get("bridge", "xen-br0")
506 d488adb6 Michael Hanselmann
507 c0f74c55 Iustin Pop
  args = [
508 8ccbbe4b Guido Trotter
    ["-B", "%s=128" % constants.BE_MINMEM],
509 8ccbbe4b Guido Trotter
    ["-B", "%s=128" % constants.BE_MAXMEM],
510 8ccbbe4b Guido Trotter
    ["-B", "%s=%s,%s=%s" % (constants.BE_MINMEM, orig_minmem,
511 8ccbbe4b Guido Trotter
                            constants.BE_MAXMEM, orig_maxmem)],
512 1d693311 Michael Hanselmann
    ["-B", "%s=2" % constants.BE_VCPUS],
513 1d693311 Michael Hanselmann
    ["-B", "%s=1" % constants.BE_VCPUS],
514 1d693311 Michael Hanselmann
    ["-B", "%s=%s" % (constants.BE_VCPUS, constants.VALUE_DEFAULT)],
515 42a769f9 Bernardo Dal Seno
    ["-B", "%s=%s" % (constants.BE_ALWAYS_FAILOVER, constants.VALUE_TRUE)],
516 42a769f9 Bernardo Dal Seno
    ["-B", "%s=%s" % (constants.BE_ALWAYS_FAILOVER, constants.VALUE_DEFAULT)],
517 1d693311 Michael Hanselmann
518 1d693311 Michael Hanselmann
    ["-H", "%s=%s" % (constants.HV_KERNEL_PATH, test_kernel)],
519 1d693311 Michael Hanselmann
    ["-H", "%s=%s" % (constants.HV_KERNEL_PATH, constants.VALUE_DEFAULT)],
520 1d693311 Michael Hanselmann
521 1d693311 Michael Hanselmann
    # TODO: bridge tests
522 1d693311 Michael Hanselmann
    #["--bridge", "xen-br1"],
523 1d693311 Michael Hanselmann
    #["--bridge", orig_bridge],
524 c0f74c55 Iustin Pop
    ]
525 d488adb6 Michael Hanselmann
526 d488adb6 Michael Hanselmann
  if default_hv == constants.HT_XEN_PVM:
527 d488adb6 Michael Hanselmann
    args.extend([
528 d488adb6 Michael Hanselmann
      ["-H", "%s=%s" % (constants.HV_INITRD_PATH, test_initrd)],
529 d488adb6 Michael Hanselmann
      ["-H", "no_%s" % (constants.HV_INITRD_PATH, )],
530 d488adb6 Michael Hanselmann
      ["-H", "%s=%s" % (constants.HV_INITRD_PATH, constants.VALUE_DEFAULT)],
531 d488adb6 Michael Hanselmann
      ])
532 d488adb6 Michael Hanselmann
  elif default_hv == constants.HT_XEN_HVM:
533 d488adb6 Michael Hanselmann
    args.extend([
534 d488adb6 Michael Hanselmann
      ["-H", "%s=acn" % constants.HV_BOOT_ORDER],
535 d488adb6 Michael Hanselmann
      ["-H", "%s=%s" % (constants.HV_BOOT_ORDER, constants.VALUE_DEFAULT)],
536 d488adb6 Michael Hanselmann
      ])
537 d488adb6 Michael Hanselmann
538 c0f74c55 Iustin Pop
  for alist in args:
539 b5f33afa Michael Hanselmann
    AssertCommand(["gnt-instance", "modify"] + alist + [instance.name])
540 c0f74c55 Iustin Pop
541 c0f74c55 Iustin Pop
  # check no-modify
542 b5f33afa Michael Hanselmann
  AssertCommand(["gnt-instance", "modify", instance.name], fail=True)
543 c0f74c55 Iustin Pop
544 1ba25bad Guido Trotter
  # Marking offline while instance is running must fail...
545 b5f33afa Michael Hanselmann
  AssertCommand(["gnt-instance", "modify", "--offline", instance.name],
546 1ba25bad Guido Trotter
                 fail=True)
547 1ba25bad Guido Trotter
548 1ba25bad Guido Trotter
  # ...while making it online is ok, and should work
549 b5f33afa Michael Hanselmann
  AssertCommand(["gnt-instance", "modify", "--online", instance.name])
550 3016bc1f Michael Hanselmann
551 3016bc1f Michael Hanselmann
552 d0a44ec0 Klaus Aehlig
@InstanceCheck(INST_UP, INST_UP, FIRST_ARG)
553 d0a44ec0 Klaus Aehlig
def TestInstanceModifyPrimaryAndBack(instance, currentnode, othernode):
554 d0a44ec0 Klaus Aehlig
  """gnt-instance modify --new-primary
555 d0a44ec0 Klaus Aehlig

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

558 d0a44ec0 Klaus Aehlig
  """
559 d0a44ec0 Klaus Aehlig
  if instance.disk_template != constants.DT_FILE:
560 d0a44ec0 Klaus Aehlig
    print qa_utils.FormatInfo("Test only supported for the file disk template")
561 d0a44ec0 Klaus Aehlig
    return
562 d0a44ec0 Klaus Aehlig
563 049a6c6b Guido Trotter
  cluster_name = qa_config.get("name")
564 049a6c6b Guido Trotter
565 d0a44ec0 Klaus Aehlig
  name = instance.name
566 d0a44ec0 Klaus Aehlig
  current = currentnode.primary
567 d0a44ec0 Klaus Aehlig
  other = othernode.primary
568 d0a44ec0 Klaus Aehlig
569 5949c31c Helga Velroyen
  filestorage = qa_config.get("file-storage-dir",
570 5949c31c Helga Velroyen
                              pathutils.DEFAULT_FILE_STORAGE_DIR)
571 d0a44ec0 Klaus Aehlig
  disk = os.path.join(filestorage, name)
572 d0a44ec0 Klaus Aehlig
573 d0a44ec0 Klaus Aehlig
  AssertCommand(["gnt-instance", "modify", "--new-primary=%s" % other, name],
574 d0a44ec0 Klaus Aehlig
                fail=True)
575 d0a44ec0 Klaus Aehlig
  AssertCommand(["gnt-instance", "shutdown", name])
576 049a6c6b Guido Trotter
  AssertCommand(["scp", "-oGlobalKnownHostsFile=%s" %
577 049a6c6b Guido Trotter
                 pathutils.SSH_KNOWN_HOSTS_FILE,
578 049a6c6b Guido Trotter
                 "-oCheckHostIp=no", "-oStrictHostKeyChecking=yes",
579 049a6c6b Guido Trotter
                 "-oHashKnownHosts=no", "-oHostKeyAlias=%s" % cluster_name,
580 f0ed67ed Guido Trotter
                 "-r", disk, "%s:%s" % (other, filestorage)], node=current)
581 d0a44ec0 Klaus Aehlig
  AssertCommand(["gnt-instance", "modify", "--new-primary=%s" % other, name])
582 d0a44ec0 Klaus Aehlig
  AssertCommand(["gnt-instance", "startup", name])
583 d0a44ec0 Klaus Aehlig
584 d0a44ec0 Klaus Aehlig
  # and back
585 d0a44ec0 Klaus Aehlig
  AssertCommand(["gnt-instance", "shutdown", name])
586 d0a44ec0 Klaus Aehlig
  AssertCommand(["rm", "-rf", disk], node=other)
587 d0a44ec0 Klaus Aehlig
  AssertCommand(["gnt-instance", "modify", "--new-primary=%s" % current, name])
588 d0a44ec0 Klaus Aehlig
  AssertCommand(["gnt-instance", "startup", name])
589 d0a44ec0 Klaus Aehlig
590 d0a44ec0 Klaus Aehlig
591 5fa0375e Michael Hanselmann
@InstanceCheck(INST_DOWN, INST_DOWN, FIRST_ARG)
592 3016bc1f Michael Hanselmann
def TestInstanceStoppedModify(instance):
593 3016bc1f Michael Hanselmann
  """gnt-instance modify (stopped instance)"""
594 b5f33afa Michael Hanselmann
  name = instance.name
595 3016bc1f Michael Hanselmann
596 58f0ce16 Michael Hanselmann
  # Instance was not marked offline; try marking it online once more
597 58f0ce16 Michael Hanselmann
  AssertCommand(["gnt-instance", "modify", "--online", name])
598 3016bc1f Michael Hanselmann
599 3016bc1f Michael Hanselmann
  # Mark instance as offline
600 3016bc1f Michael Hanselmann
  AssertCommand(["gnt-instance", "modify", "--offline", name])
601 3016bc1f Michael Hanselmann
602 1ba25bad Guido Trotter
  # When the instance is offline shutdown should only work with --force,
603 1ba25bad Guido Trotter
  # while start should never work
604 1ba25bad Guido Trotter
  AssertCommand(["gnt-instance", "shutdown", name], fail=True)
605 1ba25bad Guido Trotter
  AssertCommand(["gnt-instance", "shutdown", "--force", name])
606 1ba25bad Guido Trotter
  AssertCommand(["gnt-instance", "start", name], fail=True)
607 1ba25bad Guido Trotter
  AssertCommand(["gnt-instance", "start", "--force", name], fail=True)
608 1ba25bad Guido Trotter
609 1ba25bad Guido Trotter
  # Also do offline to offline
610 1ba25bad Guido Trotter
  AssertCommand(["gnt-instance", "modify", "--offline", name])
611 1ba25bad Guido Trotter
612 3016bc1f Michael Hanselmann
  # And online again
613 3016bc1f Michael Hanselmann
  AssertCommand(["gnt-instance", "modify", "--online", name])
614 3016bc1f Michael Hanselmann
615 c0f74c55 Iustin Pop
616 5fa0375e Michael Hanselmann
@InstanceCheck(INST_DOWN, INST_DOWN, FIRST_ARG)
617 c99200a3 Bernardo Dal Seno
def TestInstanceConvertDiskToPlain(instance, inodes):
618 7f69aabb Iustin Pop
  """gnt-instance modify -t"""
619 b5f33afa Michael Hanselmann
  name = instance.name
620 68c8c3df Michael Hanselmann
621 02a5fe0e Michael Hanselmann
  template = instance.disk_template
622 68c8c3df Michael Hanselmann
  if template != constants.DT_DRBD8:
623 5de31440 Bernardo Dal Seno
    print qa_utils.FormatInfo("Unsupported template %s, skipping conversion"
624 5de31440 Bernardo Dal Seno
                              " test" % template)
625 5de31440 Bernardo Dal Seno
    return
626 68c8c3df Michael Hanselmann
627 c99200a3 Bernardo Dal Seno
  assert len(inodes) == 2
628 68c8c3df Michael Hanselmann
  AssertCommand(["gnt-instance", "modify", "-t", constants.DT_PLAIN, name])
629 68c8c3df Michael Hanselmann
  AssertCommand(["gnt-instance", "modify", "-t", constants.DT_DRBD8,
630 aecba21e Michael Hanselmann
                 "-n", inodes[1].primary, name])
631 7f69aabb Iustin Pop
632 7f69aabb Iustin Pop
633 8cd4f8cf Bernardo Dal Seno
@InstanceCheck(INST_UP, INST_UP, FIRST_ARG)
634 8cd4f8cf Bernardo Dal Seno
def TestInstanceModifyDisks(instance):
635 8cd4f8cf Bernardo Dal Seno
  """gnt-instance modify --disk"""
636 8cd4f8cf Bernardo Dal Seno
  if not IsDiskSupported(instance):
637 8cd4f8cf Bernardo Dal Seno
    print qa_utils.FormatInfo("Instance doesn't support disks, skipping test")
638 8cd4f8cf Bernardo Dal Seno
    return
639 8cd4f8cf Bernardo Dal Seno
640 7c848a6a Bernardo Dal Seno
  disk_conf = qa_config.GetDiskOptions()[-1]
641 7c848a6a Bernardo Dal Seno
  size = disk_conf.get("size")
642 a365b47f Bernardo Dal Seno
  name = instance.name
643 8cd4f8cf Bernardo Dal Seno
  build_cmd = lambda arg: ["gnt-instance", "modify", "--disk", arg, name]
644 7c848a6a Bernardo Dal Seno
  if qa_config.AreSpindlesSupported():
645 7c848a6a Bernardo Dal Seno
    spindles = disk_conf.get("spindles")
646 7c848a6a Bernardo Dal Seno
    spindles_supported = True
647 7c848a6a Bernardo Dal Seno
  else:
648 7c848a6a Bernardo Dal Seno
    # Any number is good for spindles in this case
649 7c848a6a Bernardo Dal Seno
    spindles = 1
650 7c848a6a Bernardo Dal Seno
    spindles_supported = False
651 7c848a6a Bernardo Dal Seno
  AssertCommand(build_cmd("add:size=%s,spindles=%s" % (size, spindles)),
652 7c848a6a Bernardo Dal Seno
                fail=not spindles_supported)
653 7c848a6a Bernardo Dal Seno
  AssertCommand(build_cmd("add:size=%s" % size),
654 7c848a6a Bernardo Dal Seno
                fail=spindles_supported)
655 7c848a6a Bernardo Dal Seno
  # Exactly one of the above commands has succeded, so we need one remove
656 8cd4f8cf Bernardo Dal Seno
  AssertCommand(build_cmd("remove"))
657 8cd4f8cf Bernardo Dal Seno
658 8cd4f8cf Bernardo Dal Seno
659 5fa0375e Michael Hanselmann
@InstanceCheck(INST_DOWN, INST_DOWN, FIRST_ARG)
660 26a5056d Iustin Pop
def TestInstanceGrowDisk(instance):
661 26a5056d Iustin Pop
  """gnt-instance grow-disk"""
662 59c75517 Michael Hanselmann
  if instance.disk_template == constants.DT_DISKLESS:
663 59c75517 Michael Hanselmann
    print qa_utils.FormatInfo("Test not supported for diskless instances")
664 59c75517 Michael Hanselmann
    return
665 59c75517 Michael Hanselmann
666 b5f33afa Michael Hanselmann
  name = instance.name
667 090128b6 Christos Stavrakakis
  disks = qa_config.GetDiskOptions()
668 090128b6 Christos Stavrakakis
  all_size = [d.get("size") for d in disks]
669 090128b6 Christos Stavrakakis
  all_grow = [d.get("growth") for d in disks]
670 59c75517 Michael Hanselmann
671 26a5056d Iustin Pop
  if not all_grow:
672 26a5056d Iustin Pop
    # missing disk sizes but instance grow disk has been enabled,
673 26a5056d Iustin Pop
    # let's set fixed/nomimal growth
674 26a5056d Iustin Pop
    all_grow = ["128M" for _ in all_size]
675 59c75517 Michael Hanselmann
676 26a5056d Iustin Pop
  for idx, (size, grow) in enumerate(zip(all_size, all_grow)):
677 26a5056d Iustin Pop
    # succeed in grow by amount
678 26a5056d Iustin Pop
    AssertCommand(["gnt-instance", "grow-disk", name, str(idx), grow])
679 26a5056d Iustin Pop
    # fail in grow to the old size
680 26a5056d Iustin Pop
    AssertCommand(["gnt-instance", "grow-disk", "--absolute", name, str(idx),
681 26a5056d Iustin Pop
                   size], fail=True)
682 26a5056d Iustin Pop
    # succeed to grow to old size + 2 * growth
683 26a5056d Iustin Pop
    int_size = utils.ParseUnit(size)
684 26a5056d Iustin Pop
    int_grow = utils.ParseUnit(grow)
685 26a5056d Iustin Pop
    AssertCommand(["gnt-instance", "grow-disk", "--absolute", name, str(idx),
686 26a5056d Iustin Pop
                   str(int_size + 2 * int_grow)])
687 26a5056d Iustin Pop
688 26a5056d Iustin Pop
689 090128b6 Christos Stavrakakis
@InstanceCheck(INST_UP, INST_UP, FIRST_ARG)
690 090128b6 Christos Stavrakakis
def TestInstanceDeviceNames(instance):
691 090128b6 Christos Stavrakakis
  if instance.disk_template == constants.DT_DISKLESS:
692 090128b6 Christos Stavrakakis
    print qa_utils.FormatInfo("Test not supported for diskless instances")
693 090128b6 Christos Stavrakakis
    return
694 090128b6 Christos Stavrakakis
695 090128b6 Christos Stavrakakis
  name = instance.name
696 090128b6 Christos Stavrakakis
  for dev_type in ["disk", "net"]:
697 090128b6 Christos Stavrakakis
    if dev_type == "disk":
698 090128b6 Christos Stavrakakis
      options = ",size=512M"
699 7c848a6a Bernardo Dal Seno
      if qa_config.AreSpindlesSupported():
700 7c848a6a Bernardo Dal Seno
        options += ",spindles=1"
701 090128b6 Christos Stavrakakis
    else:
702 090128b6 Christos Stavrakakis
      options = ""
703 090128b6 Christos Stavrakakis
    # succeed in adding a device named 'test_device'
704 090128b6 Christos Stavrakakis
    AssertCommand(["gnt-instance", "modify",
705 090128b6 Christos Stavrakakis
                   "--%s=-1:add,name=test_device%s" % (dev_type, options),
706 090128b6 Christos Stavrakakis
                   name])
707 090128b6 Christos Stavrakakis
    # succeed in removing the 'test_device'
708 090128b6 Christos Stavrakakis
    AssertCommand(["gnt-instance", "modify",
709 090128b6 Christos Stavrakakis
                   "--%s=test_device:remove" % dev_type,
710 090128b6 Christos Stavrakakis
                   name])
711 090128b6 Christos Stavrakakis
    # fail to add two devices with the same name
712 090128b6 Christos Stavrakakis
    AssertCommand(["gnt-instance", "modify",
713 090128b6 Christos Stavrakakis
                   "--%s=-1:add,name=test_device%s" % (dev_type, options),
714 090128b6 Christos Stavrakakis
                   "--%s=-1:add,name=test_device%s" % (dev_type, options),
715 090128b6 Christos Stavrakakis
                   name], fail=True)
716 090128b6 Christos Stavrakakis
    # fail to add a device with invalid name
717 090128b6 Christos Stavrakakis
    AssertCommand(["gnt-instance", "modify",
718 090128b6 Christos Stavrakakis
                   "--%s=-1:add,name=2%s" % (dev_type, options),
719 090128b6 Christos Stavrakakis
                   name], fail=True)
720 090128b6 Christos Stavrakakis
  # Rename disks
721 090128b6 Christos Stavrakakis
  disks = qa_config.GetDiskOptions()
722 090128b6 Christos Stavrakakis
  disk_names = [d.get("name") for d in disks]
723 090128b6 Christos Stavrakakis
  for idx, disk_name in enumerate(disk_names):
724 090128b6 Christos Stavrakakis
    # Refer to disk by idx
725 090128b6 Christos Stavrakakis
    AssertCommand(["gnt-instance", "modify",
726 090128b6 Christos Stavrakakis
                   "--disk=%s:modify,name=renamed" % idx,
727 090128b6 Christos Stavrakakis
                   name])
728 090128b6 Christos Stavrakakis
    # Refer to by name and rename to original name
729 090128b6 Christos Stavrakakis
    AssertCommand(["gnt-instance", "modify",
730 090128b6 Christos Stavrakakis
                   "--disk=renamed:modify,name=%s" % disk_name,
731 090128b6 Christos Stavrakakis
                   name])
732 090128b6 Christos Stavrakakis
  if len(disks) >= 2:
733 090128b6 Christos Stavrakakis
    # fail in renaming to disks to the same name
734 090128b6 Christos Stavrakakis
    AssertCommand(["gnt-instance", "modify",
735 090128b6 Christos Stavrakakis
                   "--disk=0:modify,name=same_name",
736 090128b6 Christos Stavrakakis
                   "--disk=1:modify,name=same_name",
737 090128b6 Christos Stavrakakis
                   name], fail=True)
738 090128b6 Christos Stavrakakis
739 090128b6 Christos Stavrakakis
740 283f9d4c Michael Hanselmann
def TestInstanceList():
741 283f9d4c Michael Hanselmann
  """gnt-instance list"""
742 288d6440 Michael Hanselmann
  qa_utils.GenericQueryTest("gnt-instance", query.INSTANCE_FIELDS.keys())
743 283f9d4c Michael Hanselmann
744 283f9d4c Michael Hanselmann
745 2214cf14 Michael Hanselmann
def TestInstanceListFields():
746 2214cf14 Michael Hanselmann
  """gnt-instance list-fields"""
747 2214cf14 Michael Hanselmann
  qa_utils.GenericQueryFieldsTest("gnt-instance", query.INSTANCE_FIELDS.keys())
748 2214cf14 Michael Hanselmann
749 2214cf14 Michael Hanselmann
750 5fa0375e Michael Hanselmann
@InstanceCheck(INST_UP, INST_UP, FIRST_ARG)
751 4379b1fa Michael Hanselmann
def TestInstanceConsole(instance):
752 4379b1fa Michael Hanselmann
  """gnt-instance console"""
753 b5f33afa Michael Hanselmann
  AssertCommand(["gnt-instance", "console", "--show-cmd", instance.name])
754 4379b1fa Michael Hanselmann
755 4379b1fa Michael Hanselmann
756 5fa0375e Michael Hanselmann
@InstanceCheck(INST_UP, INST_UP, FIRST_ARG)
757 c99200a3 Bernardo Dal Seno
def TestReplaceDisks(instance, curr_nodes, other_nodes):
758 7910e7a5 Michael Hanselmann
  """gnt-instance replace-disks"""
759 7910e7a5 Michael Hanselmann
  def buildcmd(args):
760 d0c8c01d Iustin Pop
    cmd = ["gnt-instance", "replace-disks"]
761 7910e7a5 Michael Hanselmann
    cmd.extend(args)
762 b5f33afa Michael Hanselmann
    cmd.append(instance.name)
763 7910e7a5 Michael Hanselmann
    return cmd
764 7910e7a5 Michael Hanselmann
765 5de31440 Bernardo Dal Seno
  if not IsDiskReplacingSupported(instance):
766 5de31440 Bernardo Dal Seno
    print qa_utils.FormatInfo("Instance doesn't support disk replacing,"
767 5de31440 Bernardo Dal Seno
                              " skipping test")
768 5de31440 Bernardo Dal Seno
    return
769 5de31440 Bernardo Dal Seno
770 c99200a3 Bernardo Dal Seno
  # Currently all supported templates have one primary and one secondary node
771 c99200a3 Bernardo Dal Seno
  assert len(curr_nodes) == 2
772 c99200a3 Bernardo Dal Seno
  snode = curr_nodes[1]
773 c99200a3 Bernardo Dal Seno
  assert len(other_nodes) == 1
774 c99200a3 Bernardo Dal Seno
  othernode = other_nodes[0]
775 c99200a3 Bernardo Dal Seno
776 e85be22a Bernardo Dal Seno
  options = qa_config.get("options", {})
777 e85be22a Bernardo Dal Seno
  use_ialloc = options.get("use-iallocators", True)
778 2f4b4f78 Iustin Pop
  for data in [
779 2f4b4f78 Iustin Pop
    ["-p"],
780 2f4b4f78 Iustin Pop
    ["-s"],
781 e85be22a Bernardo Dal Seno
    # A placeholder; the actual command choice depends on use_ialloc
782 e85be22a Bernardo Dal Seno
    None,
783 e85be22a Bernardo Dal Seno
    # Restore the original secondary
784 aecba21e Michael Hanselmann
    ["--new-secondary=%s" % snode.primary],
785 2f4b4f78 Iustin Pop
    ]:
786 e85be22a Bernardo Dal Seno
    if data is None:
787 e85be22a Bernardo Dal Seno
      if use_ialloc:
788 e85be22a Bernardo Dal Seno
        data = ["-I", constants.DEFAULT_IALLOCATOR_SHORTCUT]
789 e85be22a Bernardo Dal Seno
      else:
790 aecba21e Michael Hanselmann
        data = ["--new-secondary=%s" % othernode.primary]
791 2f4b4f78 Iustin Pop
    AssertCommand(buildcmd(data))
792 7910e7a5 Michael Hanselmann
793 9026e935 René Nussbaumer
  AssertCommand(buildcmd(["-a"]))
794 b5f33afa Michael Hanselmann
  AssertCommand(["gnt-instance", "stop", instance.name])
795 9026e935 René Nussbaumer
  AssertCommand(buildcmd(["-a"]), fail=True)
796 b5f33afa Michael Hanselmann
  AssertCommand(["gnt-instance", "activate-disks", instance.name])
797 32da72f3 Iustin Pop
  AssertCommand(["gnt-instance", "activate-disks", "--wait-for-sync",
798 b5f33afa Michael Hanselmann
                 instance.name])
799 9026e935 René Nussbaumer
  AssertCommand(buildcmd(["-a"]))
800 b5f33afa Michael Hanselmann
  AssertCommand(["gnt-instance", "start", instance.name])
801 9026e935 René Nussbaumer
802 7910e7a5 Michael Hanselmann
803 83180411 Bernardo Dal Seno
def _AssertRecreateDisks(cmdargs, instance, fail=False, check=True,
804 83180411 Bernardo Dal Seno
                         destroy=True):
805 83180411 Bernardo Dal Seno
  """Execute gnt-instance recreate-disks and check the result
806 83180411 Bernardo Dal Seno

807 83180411 Bernardo Dal Seno
  @param cmdargs: Arguments (instance name excluded)
808 83180411 Bernardo Dal Seno
  @param instance: Instance to operate on
809 83180411 Bernardo Dal Seno
  @param fail: True if the command is expected to fail
810 83180411 Bernardo Dal Seno
  @param check: If True and fail is False, check that the disks work
811 83180411 Bernardo Dal Seno
  @prama destroy: If True, destroy the old disks first
812 83180411 Bernardo Dal Seno

813 83180411 Bernardo Dal Seno
  """
814 83180411 Bernardo Dal Seno
  if destroy:
815 cc2a70b1 Guido Trotter
    _DestroyInstanceDisks(instance)
816 83180411 Bernardo Dal Seno
  AssertCommand((["gnt-instance", "recreate-disks"] + cmdargs +
817 b5f33afa Michael Hanselmann
                 [instance.name]), fail)
818 83180411 Bernardo Dal Seno
  if not fail and check:
819 83180411 Bernardo Dal Seno
    # Quick check that the disks are there
820 b5f33afa Michael Hanselmann
    AssertCommand(["gnt-instance", "activate-disks", instance.name])
821 32da72f3 Iustin Pop
    AssertCommand(["gnt-instance", "activate-disks", "--wait-for-sync",
822 b5f33afa Michael Hanselmann
                   instance.name])
823 b5f33afa Michael Hanselmann
    AssertCommand(["gnt-instance", "deactivate-disks", instance.name])
824 83180411 Bernardo Dal Seno
825 a1cd2ecf Bernardo Dal Seno
826 7c848a6a Bernardo Dal Seno
def _BuildRecreateDisksOpts(en_disks, with_spindles, with_growth,
827 7c848a6a Bernardo Dal Seno
                            spindles_supported):
828 7c848a6a Bernardo Dal Seno
  if with_spindles:
829 7c848a6a Bernardo Dal Seno
    if spindles_supported:
830 7c848a6a Bernardo Dal Seno
      if with_growth:
831 7c848a6a Bernardo Dal Seno
        build_spindles_opt = (lambda disk:
832 7c848a6a Bernardo Dal Seno
                              ",spindles=%s" %
833 7c848a6a Bernardo Dal Seno
                              (disk["spindles"] + disk["spindles-growth"]))
834 7c848a6a Bernardo Dal Seno
      else:
835 7c848a6a Bernardo Dal Seno
        build_spindles_opt = (lambda disk:
836 7c848a6a Bernardo Dal Seno
                              ",spindles=%s" % disk["spindles"])
837 7c848a6a Bernardo Dal Seno
    else:
838 7c848a6a Bernardo Dal Seno
      build_spindles_opt = (lambda _: ",spindles=1")
839 7c848a6a Bernardo Dal Seno
  else:
840 7c848a6a Bernardo Dal Seno
    build_spindles_opt = (lambda _: "")
841 7c848a6a Bernardo Dal Seno
  if with_growth:
842 7c848a6a Bernardo Dal Seno
    build_size_opt = (lambda disk:
843 7c848a6a Bernardo Dal Seno
                      "size=%s" % (utils.ParseUnit(disk["size"]) +
844 7c848a6a Bernardo Dal Seno
                                   utils.ParseUnit(disk["growth"])))
845 7c848a6a Bernardo Dal Seno
  else:
846 7c848a6a Bernardo Dal Seno
    build_size_opt = (lambda disk: "size=%s" % disk["size"])
847 7c848a6a Bernardo Dal Seno
  build_disk_opt = (lambda (idx, disk):
848 7c848a6a Bernardo Dal Seno
                    "--disk=%s:%s%s" % (idx, build_size_opt(disk),
849 7c848a6a Bernardo Dal Seno
                                        build_spindles_opt(disk)))
850 7c848a6a Bernardo Dal Seno
  return map(build_disk_opt, en_disks)
851 7c848a6a Bernardo Dal Seno
852 7c848a6a Bernardo Dal Seno
853 83180411 Bernardo Dal Seno
@InstanceCheck(INST_UP, INST_UP, FIRST_ARG)
854 c99200a3 Bernardo Dal Seno
def TestRecreateDisks(instance, inodes, othernodes):
855 83180411 Bernardo Dal Seno
  """gnt-instance recreate-disks
856 83180411 Bernardo Dal Seno

857 83180411 Bernardo Dal Seno
  @param instance: Instance to work on
858 c99200a3 Bernardo Dal Seno
  @param inodes: List of the current nodes of the instance
859 83180411 Bernardo Dal Seno
  @param othernodes: list/tuple of nodes where to temporarily recreate disks
860 83180411 Bernardo Dal Seno

861 83180411 Bernardo Dal Seno
  """
862 e85be22a Bernardo Dal Seno
  options = qa_config.get("options", {})
863 e85be22a Bernardo Dal Seno
  use_ialloc = options.get("use-iallocators", True)
864 aecba21e Michael Hanselmann
  other_seq = ":".join([n.primary for n in othernodes])
865 aecba21e Michael Hanselmann
  orig_seq = ":".join([n.primary for n in inodes])
866 a085d96d Bernardo Dal Seno
  # These fail because the instance is running
867 83180411 Bernardo Dal Seno
  _AssertRecreateDisks(["-n", other_seq], instance, fail=True, destroy=False)
868 e85be22a Bernardo Dal Seno
  if use_ialloc:
869 e85be22a Bernardo Dal Seno
    _AssertRecreateDisks(["-I", "hail"], instance, fail=True, destroy=False)
870 e85be22a Bernardo Dal Seno
  else:
871 e85be22a Bernardo Dal Seno
    _AssertRecreateDisks(["-n", other_seq], instance, fail=True, destroy=False)
872 b5f33afa Michael Hanselmann
  AssertCommand(["gnt-instance", "stop", instance.name])
873 83180411 Bernardo Dal Seno
  # Disks exist: this should fail
874 83180411 Bernardo Dal Seno
  _AssertRecreateDisks([], instance, fail=True, destroy=False)
875 345d395d Bernardo Dal Seno
  # Unsupported spindles parameters: fail
876 345d395d Bernardo Dal Seno
  if not qa_config.AreSpindlesSupported():
877 345d395d Bernardo Dal Seno
    _AssertRecreateDisks(["--disk=0:spindles=2"], instance,
878 345d395d Bernardo Dal Seno
                         fail=True, destroy=False)
879 83180411 Bernardo Dal Seno
  # Recreate disks in place
880 83180411 Bernardo Dal Seno
  _AssertRecreateDisks([], instance)
881 83180411 Bernardo Dal Seno
  # Move disks away
882 e85be22a Bernardo Dal Seno
  if use_ialloc:
883 e85be22a Bernardo Dal Seno
    _AssertRecreateDisks(["-I", "hail"], instance)
884 e85be22a Bernardo Dal Seno
    # Move disks somewhere else
885 e85be22a Bernardo Dal Seno
    _AssertRecreateDisks(["-I", constants.DEFAULT_IALLOCATOR_SHORTCUT],
886 e85be22a Bernardo Dal Seno
                         instance)
887 e85be22a Bernardo Dal Seno
  else:
888 e85be22a Bernardo Dal Seno
    _AssertRecreateDisks(["-n", other_seq], instance)
889 83180411 Bernardo Dal Seno
  # Move disks back
890 e2e98c6e Bernardo Dal Seno
  _AssertRecreateDisks(["-n", orig_seq], instance)
891 345d395d Bernardo Dal Seno
  # Recreate resized disks
892 7c848a6a Bernardo Dal Seno
  # One of the two commands fails because either spindles are given when they
893 7c848a6a Bernardo Dal Seno
  # should not or vice versa
894 345d395d Bernardo Dal Seno
  alldisks = qa_config.GetDiskOptions()
895 7c848a6a Bernardo Dal Seno
  spindles_supported = qa_config.AreSpindlesSupported()
896 7c848a6a Bernardo Dal Seno
  disk_opts = _BuildRecreateDisksOpts(enumerate(alldisks), True, True,
897 7c848a6a Bernardo Dal Seno
                                      spindles_supported)
898 7c848a6a Bernardo Dal Seno
  _AssertRecreateDisks(disk_opts, instance, destroy=True,
899 7c848a6a Bernardo Dal Seno
                       fail=not spindles_supported)
900 7c848a6a Bernardo Dal Seno
  disk_opts = _BuildRecreateDisksOpts(enumerate(alldisks), False, True,
901 7c848a6a Bernardo Dal Seno
                                      spindles_supported)
902 7c848a6a Bernardo Dal Seno
  _AssertRecreateDisks(disk_opts, instance, destroy=False,
903 7c848a6a Bernardo Dal Seno
                       fail=spindles_supported)
904 345d395d Bernardo Dal Seno
  # Recreate the disks one by one (with the original size)
905 345d395d Bernardo Dal Seno
  for (idx, disk) in enumerate(alldisks):
906 e2e98c6e Bernardo Dal Seno
    # Only the first call should destroy all the disk
907 e2e98c6e Bernardo Dal Seno
    destroy = (idx == 0)
908 7c848a6a Bernardo Dal Seno
    # Again, one of the two commands is expected to fail
909 7c848a6a Bernardo Dal Seno
    disk_opts = _BuildRecreateDisksOpts([(idx, disk)], True, False,
910 7c848a6a Bernardo Dal Seno
                                        spindles_supported)
911 7c848a6a Bernardo Dal Seno
    _AssertRecreateDisks(disk_opts, instance, destroy=destroy, check=False,
912 7c848a6a Bernardo Dal Seno
                         fail=not spindles_supported)
913 7c848a6a Bernardo Dal Seno
    disk_opts = _BuildRecreateDisksOpts([(idx, disk)], False, False,
914 7c848a6a Bernardo Dal Seno
                                        spindles_supported)
915 7c848a6a Bernardo Dal Seno
    _AssertRecreateDisks(disk_opts, instance, destroy=False, check=False,
916 7c848a6a Bernardo Dal Seno
                         fail=spindles_supported)
917 83180411 Bernardo Dal Seno
  # This and InstanceCheck decoration check that the disks are working
918 b5f33afa Michael Hanselmann
  AssertCommand(["gnt-instance", "reinstall", "-f", instance.name])
919 b5f33afa Michael Hanselmann
  AssertCommand(["gnt-instance", "start", instance.name])
920 83180411 Bernardo Dal Seno
921 83180411 Bernardo Dal Seno
922 5fa0375e Michael Hanselmann
@InstanceCheck(INST_UP, INST_UP, FIRST_ARG)
923 5d640672 Michael Hanselmann
def TestInstanceExport(instance, node):
924 bc696589 Michael Hanselmann
  """gnt-backup export -n ..."""
925 b5f33afa Michael Hanselmann
  name = instance.name
926 f9b76ed4 Helga Velroyen
  # Export does not work for file-based templates, thus we skip the test
927 f9b76ed4 Helga Velroyen
  if instance.disk_template in [constants.DT_FILE, constants.DT_SHARED_FILE]:
928 f9b76ed4 Helga Velroyen
    return
929 aecba21e Michael Hanselmann
  AssertCommand(["gnt-backup", "export", "-n", node.primary, name])
930 2f4b4f78 Iustin Pop
  return qa_utils.ResolveInstanceName(name)
931 5d640672 Michael Hanselmann
932 5d640672 Michael Hanselmann
933 51131cad Michael Hanselmann
@InstanceCheck(None, INST_DOWN, FIRST_ARG)
934 8d8d650c Michael Hanselmann
def TestInstanceExportWithRemove(instance, node):
935 8d8d650c Michael Hanselmann
  """gnt-backup export --remove-instance"""
936 aecba21e Michael Hanselmann
  AssertCommand(["gnt-backup", "export", "-n", node.primary,
937 b5f33afa Michael Hanselmann
                 "--remove-instance", instance.name])
938 8d8d650c Michael Hanselmann
939 8d8d650c Michael Hanselmann
940 5fa0375e Michael Hanselmann
@InstanceCheck(INST_UP, INST_UP, FIRST_ARG)
941 bc696589 Michael Hanselmann
def TestInstanceExportNoTarget(instance):
942 bc696589 Michael Hanselmann
  """gnt-backup export (without target node, should fail)"""
943 b5f33afa Michael Hanselmann
  AssertCommand(["gnt-backup", "export", instance.name], fail=True)
944 bc696589 Michael Hanselmann
945 bc696589 Michael Hanselmann
946 51131cad Michael Hanselmann
@InstanceCheck(None, INST_DOWN, FIRST_ARG)
947 5fa0375e Michael Hanselmann
def TestInstanceImport(newinst, node, expnode, name):
948 5d640672 Michael Hanselmann
  """gnt-backup import"""
949 906a0346 Bernardo Dal Seno
  templ = constants.DT_PLAIN
950 f9b76ed4 Helga Velroyen
  if not qa_config.IsTemplateSupported(templ):
951 f9b76ed4 Helga Velroyen
    return
952 d0c8c01d Iustin Pop
  cmd = (["gnt-backup", "import",
953 906a0346 Bernardo Dal Seno
          "--disk-template=%s" % templ,
954 d0c8c01d Iustin Pop
          "--no-ip-check",
955 aecba21e Michael Hanselmann
          "--src-node=%s" % expnode.primary,
956 304d9f02 Michael Hanselmann
          "--src-dir=%s/%s" % (pathutils.EXPORT_DIR, name),
957 aecba21e Michael Hanselmann
          "--node=%s" % node.primary] +
958 8fada090 Michele Tartara
         GetGenericAddParameters(newinst, templ,
959 59c75517 Michael Hanselmann
                                  force_mac=constants.VALUE_GENERATE))
960 b5f33afa Michael Hanselmann
  cmd.append(newinst.name)
961 2f4b4f78 Iustin Pop
  AssertCommand(cmd)
962 02a5fe0e Michael Hanselmann
  newinst.SetDiskTemplate(templ)
963 283f9d4c Michael Hanselmann
964 283f9d4c Michael Hanselmann
965 283f9d4c Michael Hanselmann
def TestBackupList(expnode):
966 283f9d4c Michael Hanselmann
  """gnt-backup list"""
967 aecba21e Michael Hanselmann
  AssertCommand(["gnt-backup", "list", "--node=%s" % expnode.primary])
968 e8ae0c20 Michael Hanselmann
969 0fdf247d Michael Hanselmann
  qa_utils.GenericQueryTest("gnt-backup", query.EXPORT_FIELDS.keys(),
970 0fdf247d Michael Hanselmann
                            namefield=None, test_unknown=False)
971 0fdf247d Michael Hanselmann
972 0fdf247d Michael Hanselmann
973 0fdf247d Michael Hanselmann
def TestBackupListFields():
974 0fdf247d Michael Hanselmann
  """gnt-backup list-fields"""
975 0fdf247d Michael Hanselmann
  qa_utils.GenericQueryFieldsTest("gnt-backup", query.EXPORT_FIELDS.keys())
976 f006f110 Bernardo Dal Seno
977 f006f110 Bernardo Dal Seno
978 f006f110 Bernardo Dal Seno
def TestRemoveInstanceOfflineNode(instance, snode, set_offline, set_online):
979 318bbaa9 Guido Trotter
  """gnt-instance remove with an off-line node
980 f006f110 Bernardo Dal Seno

981 f006f110 Bernardo Dal Seno
  @param instance: instance
982 f006f110 Bernardo Dal Seno
  @param snode: secondary node, to be set offline
983 f006f110 Bernardo Dal Seno
  @param set_offline: function to call to set the node off-line
984 f006f110 Bernardo Dal Seno
  @param set_online: function to call to set the node on-line
985 f006f110 Bernardo Dal Seno

986 f006f110 Bernardo Dal Seno
  """
987 7af293d7 Thomas Thrainer
  info = GetInstanceInfo(instance.name)
988 f006f110 Bernardo Dal Seno
  set_offline(snode)
989 f006f110 Bernardo Dal Seno
  try:
990 f006f110 Bernardo Dal Seno
    TestInstanceRemove(instance)
991 f006f110 Bernardo Dal Seno
  finally:
992 f006f110 Bernardo Dal Seno
    set_online(snode)
993 318bbaa9 Guido Trotter
994 318bbaa9 Guido Trotter
  # Clean up the disks on the offline node, if necessary
995 318bbaa9 Guido Trotter
  if instance.disk_template not in constants.DTS_EXT_MIRROR:
996 318bbaa9 Guido Trotter
    # FIXME: abstract the cleanup inside the disks
997 318bbaa9 Guido Trotter
    if info["storage-type"] == constants.ST_LVM_VG:
998 318bbaa9 Guido Trotter
      for minor in info["drbd-minors"][snode.primary]:
999 2e462e19 Thomas Thrainer
        # DRBD 8.3 syntax comes first, then DRBD 8.4 syntax. The 8.4 syntax
1000 2e462e19 Thomas Thrainer
        # relies on the fact that we always create a resources for each minor,
1001 2e462e19 Thomas Thrainer
        # and that this resources is always named resource{minor}.
1002 2e462e19 Thomas Thrainer
        # As 'drbdsetup 0 down' does return success (even though that's invalid
1003 2e462e19 Thomas Thrainer
        # syntax), we always have to perform both commands and ignore the
1004 2e462e19 Thomas Thrainer
        # output.
1005 2e462e19 Thomas Thrainer
        drbd_shutdown_cmd = \
1006 7af293d7 Thomas Thrainer
          "(drbdsetup %d down >/dev/null 2>&1;" \
1007 7af293d7 Thomas Thrainer
          " drbdsetup down resource%d >/dev/null 2>&1) || /bin/true" % \
1008 2e462e19 Thomas Thrainer
            (minor, minor)
1009 2e462e19 Thomas Thrainer
        AssertCommand(drbd_shutdown_cmd, node=snode)
1010 318bbaa9 Guido Trotter
      AssertCommand(["lvremove", "-f"] + info["volumes"], node=snode)
1011 318bbaa9 Guido Trotter
    elif info["storage-type"] == constants.ST_FILE:
1012 5949c31c Helga Velroyen
      filestorage = qa_config.get("file-storage-dir",
1013 5949c31c Helga Velroyen
                                  pathutils.DEFAULT_FILE_STORAGE_DIR)
1014 318bbaa9 Guido Trotter
      disk = os.path.join(filestorage, instance.name)
1015 318bbaa9 Guido Trotter
      AssertCommand(["rm", "-rf", disk], node=snode)
1016 6f665bf7 Helga Velroyen
1017 6f665bf7 Helga Velroyen
1018 6f665bf7 Helga Velroyen
def TestInstanceCreationRestrictedByDiskTemplates():
1019 e75f80b9 Bernardo Dal Seno
  """Test adding instances for disabled disk templates."""
1020 2b5b6da1 Helga Velroyen
  if qa_config.TestEnabled("cluster-exclusive-storage"):
1021 2b5b6da1 Helga Velroyen
    # These tests are valid only for non-exclusive storage
1022 2b5b6da1 Helga Velroyen
    return
1023 2b5b6da1 Helga Velroyen
1024 6f665bf7 Helga Velroyen
  enabled_disk_templates = qa_config.GetEnabledDiskTemplates()
1025 6f665bf7 Helga Velroyen
  nodes = qa_config.AcquireManyNodes(2)
1026 6f665bf7 Helga Velroyen
1027 6f665bf7 Helga Velroyen
  # Setup the cluster with the enabled_disk_templates
1028 6f665bf7 Helga Velroyen
  AssertCommand(
1029 6f665bf7 Helga Velroyen
    ["gnt-cluster", "modify",
1030 6f665bf7 Helga Velroyen
     "--enabled-disk-template=%s" %
1031 6f665bf7 Helga Velroyen
       ",".join(enabled_disk_templates)],
1032 6f665bf7 Helga Velroyen
    fail=False)
1033 6f665bf7 Helga Velroyen
1034 6f665bf7 Helga Velroyen
  # Test instance creation for enabled disk templates
1035 6f665bf7 Helga Velroyen
  for disk_template in enabled_disk_templates:
1036 e75f80b9 Bernardo Dal Seno
    instance = CreateInstanceByDiskTemplate(nodes, disk_template, fail=False)
1037 6f665bf7 Helga Velroyen
    TestInstanceRemove(instance)
1038 e75f80b9 Bernardo Dal Seno
    instance.Release()
1039 6f665bf7 Helga Velroyen
1040 6f665bf7 Helga Velroyen
  # Test that instance creation fails for disabled disk templates
1041 6f665bf7 Helga Velroyen
  disabled_disk_templates = list(constants.DISK_TEMPLATES
1042 6f665bf7 Helga Velroyen
                                 - set(enabled_disk_templates))
1043 6f665bf7 Helga Velroyen
  for disk_template in disabled_disk_templates:
1044 e75f80b9 Bernardo Dal Seno
    instance = CreateInstanceByDiskTemplate(nodes, disk_template, fail=True)
1045 6f665bf7 Helga Velroyen
1046 6f665bf7 Helga Velroyen
  # Test instance creation for after disabling enabled disk templates
1047 6f665bf7 Helga Velroyen
  if (len(enabled_disk_templates) > 1):
1048 6f665bf7 Helga Velroyen
    # Partition the disk templates, enable them separately and check if the
1049 6f665bf7 Helga Velroyen
    # disabled ones cannot be used by instances.
1050 6f665bf7 Helga Velroyen
    middle = len(enabled_disk_templates) / 2
1051 6f665bf7 Helga Velroyen
    templates1 = enabled_disk_templates[:middle]
1052 6f665bf7 Helga Velroyen
    templates2 = enabled_disk_templates[middle:]
1053 6f665bf7 Helga Velroyen
1054 6f665bf7 Helga Velroyen
    for (enabled, disabled) in [(templates1, templates2),
1055 6f665bf7 Helga Velroyen
                                (templates2, templates1)]:
1056 6f665bf7 Helga Velroyen
      AssertCommand(["gnt-cluster", "modify",
1057 6f665bf7 Helga Velroyen
                     "--enabled-disk-template=%s" %
1058 6f665bf7 Helga Velroyen
                       ",".join(enabled)],
1059 6f665bf7 Helga Velroyen
                    fail=False)
1060 6f665bf7 Helga Velroyen
      for disk_template in disabled:
1061 e75f80b9 Bernardo Dal Seno
        CreateInstanceByDiskTemplate(nodes, disk_template, fail=True)
1062 6f665bf7 Helga Velroyen
  elif (len(enabled_disk_templates) == 1):
1063 6f665bf7 Helga Velroyen
    # If only one disk template is enabled in the QA config, we have to enable
1064 d101b7be Thomas Thrainer
    # some other templates in order to test if the disabling the only enabled
1065 d101b7be Thomas Thrainer
    # disk template prohibits creating instances of that template.
1066 d101b7be Thomas Thrainer
    other_disk_templates = list(
1067 ec4341d7 Thomas Thrainer
                             set([constants.DT_DISKLESS, constants.DT_BLOCK]) -
1068 ec4341d7 Thomas Thrainer
                             set(enabled_disk_templates))
1069 6f665bf7 Helga Velroyen
    AssertCommand(["gnt-cluster", "modify",
1070 6f665bf7 Helga Velroyen
                   "--enabled-disk-template=%s" %
1071 d101b7be Thomas Thrainer
                     ",".join(other_disk_templates)],
1072 6f665bf7 Helga Velroyen
                  fail=False)
1073 e75f80b9 Bernardo Dal Seno
    CreateInstanceByDiskTemplate(nodes, enabled_disk_templates[0], fail=True)
1074 6f665bf7 Helga Velroyen
  else:
1075 6f665bf7 Helga Velroyen
    raise qa_error.Error("Please enable at least one disk template"
1076 6f665bf7 Helga Velroyen
                         " in your QA setup.")
1077 6f665bf7 Helga Velroyen
1078 6f665bf7 Helga Velroyen
  # Restore initially enabled disk templates
1079 6f665bf7 Helga Velroyen
  AssertCommand(["gnt-cluster", "modify",
1080 6f665bf7 Helga Velroyen
                 "--enabled-disk-template=%s" %
1081 6f665bf7 Helga Velroyen
                   ",".join(enabled_disk_templates)],
1082 6f665bf7 Helga Velroyen
                 fail=False)