Statistics
| Branch: | Tag: | Revision:

root / qa / qa_instance.py @ c632d3a5

History | View | Annotate | Download (38.1 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 cc4b14f0 Bernardo Dal Seno
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 b5f33afa Michael Hanselmann
  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
    # FIXME: file storage dir not configurable in qa
140 cc2a70b1 Guido Trotter
    # Note that this works for both file and sharedfile, and this is intended.
141 cc2a70b1 Guido Trotter
    filestorage = pathutils.DEFAULT_FILE_STORAGE_DIR
142 cc2a70b1 Guido Trotter
    idir = os.path.join(filestorage, 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 59c75517 Michael Hanselmann
def TestInstanceAddDiskless(nodes):
281 59c75517 Michael Hanselmann
  """gnt-instance add -t diskless"""
282 59c75517 Michael Hanselmann
  assert len(nodes) == 1
283 d06e7b3b Thomas Thrainer
  if constants.DT_DISKLESS in qa_config.GetEnabledDiskTemplates():
284 8fada090 Michele Tartara
    return CreateInstanceByDiskTemplateOneNode(nodes, constants.DT_DISKLESS)
285 59c75517 Michael Hanselmann
286 59c75517 Michael Hanselmann
287 5fa0375e Michael Hanselmann
@InstanceCheck(None, INST_DOWN, FIRST_ARG)
288 cec9845c Michael Hanselmann
def TestInstanceRemove(instance):
289 cec9845c Michael Hanselmann
  """gnt-instance remove"""
290 b5f33afa Michael Hanselmann
  AssertCommand(["gnt-instance", "remove", "-f", instance.name])
291 cec9845c Michael Hanselmann
292 cec9845c Michael Hanselmann
293 5fa0375e Michael Hanselmann
@InstanceCheck(INST_DOWN, INST_UP, FIRST_ARG)
294 cec9845c Michael Hanselmann
def TestInstanceStartup(instance):
295 cec9845c Michael Hanselmann
  """gnt-instance startup"""
296 b5f33afa Michael Hanselmann
  AssertCommand(["gnt-instance", "startup", instance.name])
297 cec9845c Michael Hanselmann
298 cec9845c Michael Hanselmann
299 5fa0375e Michael Hanselmann
@InstanceCheck(INST_UP, INST_DOWN, FIRST_ARG)
300 cec9845c Michael Hanselmann
def TestInstanceShutdown(instance):
301 cec9845c Michael Hanselmann
  """gnt-instance shutdown"""
302 b5f33afa Michael Hanselmann
  AssertCommand(["gnt-instance", "shutdown", instance.name])
303 cec9845c Michael Hanselmann
304 cec9845c Michael Hanselmann
305 5fa0375e Michael Hanselmann
@InstanceCheck(INST_UP, INST_UP, FIRST_ARG)
306 8a4e8898 Michael Hanselmann
def TestInstanceReboot(instance):
307 8a4e8898 Michael Hanselmann
  """gnt-instance reboot"""
308 d0c8c01d Iustin Pop
  options = qa_config.get("options", {})
309 1d103c02 Iustin Pop
  reboot_types = options.get("reboot-types", constants.REBOOT_TYPES)
310 b5f33afa Michael Hanselmann
  name = instance.name
311 1d103c02 Iustin Pop
  for rtype in reboot_types:
312 2f4b4f78 Iustin Pop
    AssertCommand(["gnt-instance", "reboot", "--type=%s" % rtype, name])
313 8a4e8898 Michael Hanselmann
314 cc27265e René Nussbaumer
  AssertCommand(["gnt-instance", "shutdown", name])
315 5fa0375e Michael Hanselmann
  qa_utils.RunInstanceCheck(instance, False)
316 cc27265e René Nussbaumer
  AssertCommand(["gnt-instance", "reboot", name])
317 cc27265e René Nussbaumer
318 cc27265e René Nussbaumer
  master = qa_config.GetMasterNode()
319 58ea8d17 Michael Hanselmann
  cmd = ["gnt-instance", "list", "--no-headers", "-o", "status", name]
320 aecba21e Michael Hanselmann
  result_output = qa_utils.GetCommandOutput(master.primary,
321 cc27265e René Nussbaumer
                                            utils.ShellQuoteArgs(cmd))
322 cc27265e René Nussbaumer
  AssertEqual(result_output.strip(), constants.INSTST_RUNNING)
323 cc27265e René Nussbaumer
324 8a4e8898 Michael Hanselmann
325 5fa0375e Michael Hanselmann
@InstanceCheck(INST_DOWN, INST_DOWN, FIRST_ARG)
326 283f9d4c Michael Hanselmann
def TestInstanceReinstall(instance):
327 283f9d4c Michael Hanselmann
  """gnt-instance reinstall"""
328 a90636b2 Michael Hanselmann
  if instance.disk_template == constants.DT_DISKLESS:
329 a90636b2 Michael Hanselmann
    print qa_utils.FormatInfo("Test not supported for diskless instances")
330 a90636b2 Michael Hanselmann
    return
331 a90636b2 Michael Hanselmann
332 b5f33afa Michael Hanselmann
  AssertCommand(["gnt-instance", "reinstall", "-f", instance.name])
333 283f9d4c Michael Hanselmann
334 64be07b1 Michael Hanselmann
  # Test with non-existant OS definition
335 64be07b1 Michael Hanselmann
  AssertCommand(["gnt-instance", "reinstall", "-f",
336 64be07b1 Michael Hanselmann
                 "--os-type=NonExistantOsForQa",
337 b5f33afa Michael Hanselmann
                 instance.name],
338 64be07b1 Michael Hanselmann
                fail=True)
339 64be07b1 Michael Hanselmann
340 283f9d4c Michael Hanselmann
341 51131cad Michael Hanselmann
@InstanceCheck(INST_DOWN, INST_DOWN, FIRST_ARG)
342 4c1a464b Iustin Pop
def TestInstanceRenameAndBack(rename_source, rename_target):
343 4c1a464b Iustin Pop
  """gnt-instance rename
344 4c1a464b Iustin Pop

345 4c1a464b Iustin Pop
  This must leave the instance with the original name, not the target
346 4c1a464b Iustin Pop
  name.
347 4c1a464b Iustin Pop

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

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

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

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

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

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

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

973 f006f110 Bernardo Dal Seno
  @param instance: instance
974 f006f110 Bernardo Dal Seno
  @param snode: secondary node, to be set offline
975 f006f110 Bernardo Dal Seno
  @param set_offline: function to call to set the node off-line
976 f006f110 Bernardo Dal Seno
  @param set_online: function to call to set the node on-line
977 f006f110 Bernardo Dal Seno

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