Statistics
| Branch: | Tag: | Revision:

root / qa / qa_instance.py @ 1a732a74

History | View | Annotate | Download (38.9 kB)

1 c68d1f43 Michael Hanselmann
#
2 c68d1f43 Michael Hanselmann
#
3 c68d1f43 Michael Hanselmann
4 deaa347b Bernardo Dal Seno
# Copyright (C) 2007, 2011, 2012, 2013 Google Inc.
5 cec9845c Michael Hanselmann
#
6 cec9845c Michael Hanselmann
# This program is free software; you can redistribute it and/or modify
7 cec9845c Michael Hanselmann
# it under the terms of the GNU General Public License as published by
8 cec9845c Michael Hanselmann
# the Free Software Foundation; either version 2 of the License, or
9 cec9845c Michael Hanselmann
# (at your option) any later version.
10 cec9845c Michael Hanselmann
#
11 cec9845c Michael Hanselmann
# This program is distributed in the hope that it will be useful, but
12 cec9845c Michael Hanselmann
# WITHOUT ANY WARRANTY; without even the implied warranty of
13 cec9845c Michael Hanselmann
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 cec9845c Michael Hanselmann
# General Public License for more details.
15 cec9845c Michael Hanselmann
#
16 cec9845c Michael Hanselmann
# You should have received a copy of the GNU General Public License
17 cec9845c Michael Hanselmann
# along with this program; if not, write to the Free Software
18 cec9845c Michael Hanselmann
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 cec9845c Michael Hanselmann
# 02110-1301, USA.
20 cec9845c Michael Hanselmann
21 cec9845c Michael Hanselmann
22 cec9845c Michael Hanselmann
"""Instance related QA tests.
23 cec9845c Michael Hanselmann

24 cec9845c Michael Hanselmann
"""
25 cec9845c Michael Hanselmann
26 c99200a3 Bernardo Dal Seno
import operator
27 d0a44ec0 Klaus Aehlig
import os
28 e8ae0c20 Michael Hanselmann
import re
29 e8ae0c20 Michael Hanselmann
30 cec9845c Michael Hanselmann
from ganeti import utils
31 5d640672 Michael Hanselmann
from ganeti import constants
32 288d6440 Michael Hanselmann
from ganeti import query
33 304d9f02 Michael Hanselmann
from ganeti import pathutils
34 cec9845c Michael Hanselmann
35 cec9845c Michael Hanselmann
import qa_config
36 5d640672 Michael Hanselmann
import qa_utils
37 e8ae0c20 Michael Hanselmann
import qa_error
38 e8ae0c20 Michael Hanselmann
39 cc27265e René Nussbaumer
from qa_utils import AssertIn, AssertCommand, AssertEqual
40 5fa0375e Michael Hanselmann
from qa_utils import InstanceCheck, INST_DOWN, INST_UP, FIRST_ARG, RETURN_VALUE
41 cec9845c Michael Hanselmann
42 e8ae0c20 Michael Hanselmann
43 e8ae0c20 Michael Hanselmann
def _GetDiskStatePath(disk):
44 e8ae0c20 Michael Hanselmann
  return "/sys/block/%s/device/state" % disk
45 cec9845c Michael Hanselmann
46 cec9845c Michael Hanselmann
47 59c75517 Michael Hanselmann
def _GetGenericAddParameters(inst, disk_template, force_mac=None):
48 8ccbbe4b Guido Trotter
  params = ["-B"]
49 8ccbbe4b Guido Trotter
  params.append("%s=%s,%s=%s" % (constants.BE_MINMEM,
50 8ccbbe4b Guido Trotter
                                 qa_config.get(constants.BE_MINMEM),
51 8ccbbe4b Guido Trotter
                                 constants.BE_MAXMEM,
52 8ccbbe4b Guido Trotter
                                 qa_config.get(constants.BE_MAXMEM)))
53 59c75517 Michael Hanselmann
54 59c75517 Michael Hanselmann
  if disk_template != constants.DT_DISKLESS:
55 090128b6 Christos Stavrakakis
    for idx, disk in enumerate(qa_config.GetDiskOptions()):
56 090128b6 Christos Stavrakakis
      size = disk.get("size")
57 090128b6 Christos Stavrakakis
      name = disk.get("name")
58 0a6301ae Helga Velroyen
      diskparams = "%s:size=%s" % (idx, size)
59 0a6301ae Helga Velroyen
      if name:
60 0a6301ae Helga Velroyen
        diskparams += ",name=%s" % name
61 0a6301ae Helga Velroyen
      params.extend(["--disk", diskparams])
62 f346a7d9 Michael Hanselmann
63 f346a7d9 Michael Hanselmann
  # Set static MAC address if configured
64 1c573fb4 Iustin Pop
  if force_mac:
65 1c573fb4 Iustin Pop
    nic0_mac = force_mac
66 1c573fb4 Iustin Pop
  else:
67 0afce24e Michael Hanselmann
    nic0_mac = inst.GetNicMacAddr(0, None)
68 0afce24e Michael Hanselmann
69 f346a7d9 Michael Hanselmann
  if nic0_mac:
70 f346a7d9 Michael Hanselmann
    params.extend(["--net", "0:mac=%s" % nic0_mac])
71 f346a7d9 Michael Hanselmann
72 1d693311 Michael Hanselmann
  return params
73 5d640672 Michael Hanselmann
74 5d640672 Michael Hanselmann
75 f41dc024 Helga Velroyen
def _CreateInstanceByDiskTemplateRaw(nodes_spec, disk_template, fail=False):
76 f41dc024 Helga Velroyen
  """Creates an instance with the given disk template on the given nodes(s).
77 f41dc024 Helga Velroyen
     Note that this function does not check if enough nodes are given for
78 f41dc024 Helga Velroyen
     the respective disk template.
79 f41dc024 Helga Velroyen

80 f41dc024 Helga Velroyen
  @type nodes_spec: string
81 f41dc024 Helga Velroyen
  @param nodes_spec: string specification of one node (by node name) or several
82 f41dc024 Helga Velroyen
                     nodes according to the requirements of the disk template
83 f41dc024 Helga Velroyen
  @type disk_template: string
84 f41dc024 Helga Velroyen
  @param disk_template: the disk template to be used by the instance
85 f41dc024 Helga Velroyen
  @return: the created instance
86 f41dc024 Helga Velroyen

87 f41dc024 Helga Velroyen
  """
88 cec9845c Michael Hanselmann
  instance = qa_config.AcquireInstance()
89 cec9845c Michael Hanselmann
  try:
90 d0c8c01d Iustin Pop
    cmd = (["gnt-instance", "add",
91 d0c8c01d Iustin Pop
            "--os-type=%s" % qa_config.get("os"),
92 d0c8c01d Iustin Pop
            "--disk-template=%s" % disk_template,
93 f41dc024 Helga Velroyen
            "--node=%s" % nodes_spec] +
94 59c75517 Michael Hanselmann
           _GetGenericAddParameters(instance, disk_template))
95 b5f33afa Michael Hanselmann
    cmd.append(instance.name)
96 cec9845c Michael Hanselmann
97 fa84c8a4 Bernardo Dal Seno
    AssertCommand(cmd, fail=fail)
98 6a343475 Michael Hanselmann
99 fa84c8a4 Bernardo Dal Seno
    if not fail:
100 46d21495 Bernardo Dal Seno
      _CheckSsconfInstanceList(instance.name)
101 46d21495 Bernardo Dal Seno
      instance.SetDiskTemplate(disk_template)
102 6a343475 Michael Hanselmann
103 fa84c8a4 Bernardo Dal Seno
      return instance
104 cec9845c Michael Hanselmann
  except:
105 6f88e076 Michael Hanselmann
    instance.Release()
106 cec9845c Michael Hanselmann
    raise
107 cec9845c Michael Hanselmann
108 fa84c8a4 Bernardo Dal Seno
  # Handle the case where creation is expected to fail
109 fa84c8a4 Bernardo Dal Seno
  assert fail
110 46d21495 Bernardo Dal Seno
  instance.Release()
111 fa84c8a4 Bernardo Dal Seno
  return None
112 fa84c8a4 Bernardo Dal Seno
113 cec9845c Michael Hanselmann
114 f41dc024 Helga Velroyen
def _CreateInstanceByDiskTemplateOneNode(nodes, disk_template, fail=False):
115 f41dc024 Helga Velroyen
  """Creates an instance using the given disk template for disk templates
116 f41dc024 Helga Velroyen
     for which one given node is sufficient. These templates are for example:
117 f41dc024 Helga Velroyen
     plain, diskless, file, sharedfile, blockdev, rados.
118 f41dc024 Helga Velroyen

119 f41dc024 Helga Velroyen
  @type nodes: list of nodes
120 f41dc024 Helga Velroyen
  @param nodes: a list of nodes, whose first element is used to create the
121 f41dc024 Helga Velroyen
                instance
122 f41dc024 Helga Velroyen
  @type disk_template: string
123 f41dc024 Helga Velroyen
  @param disk_template: the disk template to be used by the instance
124 f41dc024 Helga Velroyen
  @return: the created instance
125 f41dc024 Helga Velroyen

126 f41dc024 Helga Velroyen
  """
127 f41dc024 Helga Velroyen
  assert len(nodes) > 0
128 f41dc024 Helga Velroyen
  return _CreateInstanceByDiskTemplateRaw(nodes[0].primary, disk_template,
129 f41dc024 Helga Velroyen
                                          fail=fail)
130 f41dc024 Helga Velroyen
131 f41dc024 Helga Velroyen
132 f41dc024 Helga Velroyen
def _CreateInstanceDrbd8(nodes, fail=False):
133 f41dc024 Helga Velroyen
  """Creates an instance using disk template 'drbd' on the given nodes.
134 f41dc024 Helga Velroyen

135 f41dc024 Helga Velroyen
  @type nodes: list of nodes
136 f41dc024 Helga Velroyen
  @param nodes: nodes to be used by the instance
137 f41dc024 Helga Velroyen
  @return: the created instance
138 f41dc024 Helga Velroyen

139 f41dc024 Helga Velroyen
  """
140 f41dc024 Helga Velroyen
  assert len(nodes) > 1
141 f41dc024 Helga Velroyen
  return _CreateInstanceByDiskTemplateRaw(
142 f41dc024 Helga Velroyen
    ":".join(map(operator.attrgetter("primary"), nodes)),
143 f41dc024 Helga Velroyen
    constants.DT_DRBD8, fail=fail)
144 f41dc024 Helga Velroyen
145 f41dc024 Helga Velroyen
146 f41dc024 Helga Velroyen
def CreateInstanceByDiskTemplate(nodes, disk_template, fail=False):
147 f41dc024 Helga Velroyen
  """Given a disk template, this function creates an instance using
148 f41dc024 Helga Velroyen
     the template. It uses the required number of nodes depending on
149 f41dc024 Helga Velroyen
     the disk template. This function is intended to be used by tests
150 f41dc024 Helga Velroyen
     that don't care about the specifics of the instance other than
151 f41dc024 Helga Velroyen
     that it uses the given disk template.
152 f41dc024 Helga Velroyen

153 f41dc024 Helga Velroyen
     Note: If you use this function, make sure to call
154 f41dc024 Helga Velroyen
     'TestInstanceRemove' at the end of your tests to avoid orphaned
155 f41dc024 Helga Velroyen
     instances hanging around and interfering with the following tests.
156 f41dc024 Helga Velroyen

157 f41dc024 Helga Velroyen
  @type nodes: list of nodes
158 f41dc024 Helga Velroyen
  @param nodes: the list of the nodes on which the instance will be placed;
159 f41dc024 Helga Velroyen
                it needs to have sufficiently many elements for the given
160 f41dc024 Helga Velroyen
                disk template
161 f41dc024 Helga Velroyen
  @type disk_template: string
162 f41dc024 Helga Velroyen
  @param disk_template: the disk template to be used by the instance
163 f41dc024 Helga Velroyen
  @return: the created instance
164 f41dc024 Helga Velroyen

165 f41dc024 Helga Velroyen
  """
166 f41dc024 Helga Velroyen
  if disk_template == constants.DT_DRBD8:
167 f41dc024 Helga Velroyen
    return _CreateInstanceDrbd8(nodes, fail=fail)
168 6f665bf7 Helga Velroyen
  elif disk_template in [constants.DT_DISKLESS, constants.DT_PLAIN,
169 6f665bf7 Helga Velroyen
                         constants.DT_FILE]:
170 f41dc024 Helga Velroyen
    return _CreateInstanceByDiskTemplateOneNode(nodes, disk_template, fail=fail)
171 f41dc024 Helga Velroyen
  else:
172 6f665bf7 Helga Velroyen
    # FIXME: This assumes that for all other disk templates, we only need one
173 6f665bf7 Helga Velroyen
    # node and no disk template specific parameters. This else-branch is
174 6f665bf7 Helga Velroyen
    # currently only used in cases where we expect failure. Extend it when
175 6f665bf7 Helga Velroyen
    # QA needs for these templates change.
176 6f665bf7 Helga Velroyen
    return _CreateInstanceByDiskTemplateOneNode(nodes, disk_template, fail=fail)
177 f41dc024 Helga Velroyen
178 f41dc024 Helga Velroyen
179 cc4b14f0 Bernardo Dal Seno
def _GetInstanceInfo(instance):
180 cc4b14f0 Bernardo Dal Seno
  """Return information about the actual state of an instance.
181 82d2f3df Bernardo Dal Seno

182 b07afbb3 Iustin Pop
  @type instance: string
183 b07afbb3 Iustin Pop
  @param instance: the instance name
184 f006f110 Bernardo Dal Seno
  @return: a dictionary with the following keys:
185 b07afbb3 Iustin Pop
      - "nodes": instance nodes, a list of strings
186 b07afbb3 Iustin Pop
      - "volumes": instance volume IDs, a list of strings
187 f006f110 Bernardo Dal Seno
      - "drbd-minors": DRBD minors used by the instance, a dictionary where
188 f006f110 Bernardo Dal Seno
        keys are nodes, and values are lists of integers (or an empty
189 f006f110 Bernardo Dal Seno
        dictionary for non-DRBD instances)
190 1012ecf4 Guido Trotter
      - "disk-template": instance disk template
191 1012ecf4 Guido Trotter
      - "storage-type": storage type associated with the instance disk template
192 82d2f3df Bernardo Dal Seno

193 82d2f3df Bernardo Dal Seno
  """
194 82d2f3df Bernardo Dal Seno
  node_elem = r"([^,()]+)(?:\s+\([^)]+\))?"
195 82d2f3df Bernardo Dal Seno
  # re_nodelist matches a list of nodes returned by gnt-instance info, e.g.:
196 82d2f3df Bernardo Dal Seno
  #  node1.fqdn
197 82d2f3df Bernardo Dal Seno
  #  node2.fqdn,node3.fqdn
198 82d2f3df Bernardo Dal Seno
  #  node4.fqdn (group mygroup, group UUID 01234567-abcd-0123-4567-0123456789ab)
199 82d2f3df Bernardo Dal Seno
  # FIXME This works with no more than 2 secondaries
200 82d2f3df Bernardo Dal Seno
  re_nodelist = re.compile(node_elem + "(?:," + node_elem + ")?$")
201 2cbcf95d Bernardo Dal Seno
202 2cbcf95d Bernardo Dal Seno
  info = qa_utils.GetObjectInfo(["gnt-instance", "info", instance])[0]
203 82d2f3df Bernardo Dal Seno
  nodes = []
204 2cbcf95d Bernardo Dal Seno
  for nodeinfo in info["Nodes"]:
205 2cbcf95d Bernardo Dal Seno
    if "primary" in nodeinfo:
206 2cbcf95d Bernardo Dal Seno
      nodes.append(nodeinfo["primary"])
207 2cbcf95d Bernardo Dal Seno
    elif "secondaries" in nodeinfo:
208 2cbcf95d Bernardo Dal Seno
      nodestr = nodeinfo["secondaries"]
209 2cbcf95d Bernardo Dal Seno
      if nodestr:
210 2cbcf95d Bernardo Dal Seno
        m = re_nodelist.match(nodestr)
211 2cbcf95d Bernardo Dal Seno
        if m:
212 2cbcf95d Bernardo Dal Seno
          nodes.extend(filter(None, m.groups()))
213 2cbcf95d Bernardo Dal Seno
        else:
214 2cbcf95d Bernardo Dal Seno
          nodes.append(nodestr)
215 2cbcf95d Bernardo Dal Seno
216 1012ecf4 Guido Trotter
  disk_template = info["Disk template"]
217 1012ecf4 Guido Trotter
  if not disk_template:
218 1012ecf4 Guido Trotter
    raise qa_error.Error("Can't get instance disk template")
219 1012ecf4 Guido Trotter
  storage_type = constants.DISK_TEMPLATES_STORAGE_TYPE[disk_template]
220 1012ecf4 Guido Trotter
221 2cbcf95d Bernardo Dal Seno
  re_drbdnode = re.compile(r"^([^\s,]+),\s+minor=([0-9]+)$")
222 82d2f3df Bernardo Dal Seno
  vols = []
223 f006f110 Bernardo Dal Seno
  drbd_min = {}
224 2cbcf95d Bernardo Dal Seno
  for (count, diskinfo) in enumerate(info["Disks"]):
225 2cbcf95d Bernardo Dal Seno
    (dtype, _) = diskinfo["disk/%s" % count].split(",", 1)
226 2cbcf95d Bernardo Dal Seno
    if dtype == constants.LD_DRBD8:
227 2cbcf95d Bernardo Dal Seno
      for child in diskinfo["child devices"]:
228 2cbcf95d Bernardo Dal Seno
        vols.append(child["logical_id"])
229 2cbcf95d Bernardo Dal Seno
      for key in ["nodeA", "nodeB"]:
230 2cbcf95d Bernardo Dal Seno
        m = re_drbdnode.match(diskinfo[key])
231 2cbcf95d Bernardo Dal Seno
        if not m:
232 2cbcf95d Bernardo Dal Seno
          raise qa_error.Error("Cannot parse DRBD info: %s" % diskinfo[key])
233 2cbcf95d Bernardo Dal Seno
        node = m.group(1)
234 2cbcf95d Bernardo Dal Seno
        minor = int(m.group(2))
235 2cbcf95d Bernardo Dal Seno
        minorlist = drbd_min.setdefault(node, [])
236 2cbcf95d Bernardo Dal Seno
        minorlist.append(minor)
237 2cbcf95d Bernardo Dal Seno
    elif dtype == constants.LD_LV:
238 2cbcf95d Bernardo Dal Seno
      vols.append(diskinfo["logical_id"])
239 b296c810 Michael Hanselmann
240 82d2f3df Bernardo Dal Seno
  assert nodes
241 b296c810 Michael Hanselmann
  assert len(nodes) < 2 or vols
242 1a6db3df Michael Hanselmann
  return {
243 1a6db3df Michael Hanselmann
    "nodes": nodes,
244 1a6db3df Michael Hanselmann
    "volumes": vols,
245 1a6db3df Michael Hanselmann
    "drbd-minors": drbd_min,
246 1012ecf4 Guido Trotter
    "disk-template": disk_template,
247 1012ecf4 Guido Trotter
    "storage-type": storage_type,
248 1a6db3df Michael Hanselmann
    }
249 cc4b14f0 Bernardo Dal Seno
250 cc4b14f0 Bernardo Dal Seno
251 cc2a70b1 Guido Trotter
def _DestroyInstanceDisks(instance):
252 cc2a70b1 Guido Trotter
  """Remove all the backend disks of an instance.
253 cc4b14f0 Bernardo Dal Seno

254 cc4b14f0 Bernardo Dal Seno
  This is used to simulate HW errors (dead nodes, broken disks...); the
255 cc4b14f0 Bernardo Dal Seno
  configuration of the instance is not affected.
256 cc4b14f0 Bernardo Dal Seno
  @type instance: dictionary
257 cc4b14f0 Bernardo Dal Seno
  @param instance: the instance
258 cc4b14f0 Bernardo Dal Seno

259 cc4b14f0 Bernardo Dal Seno
  """
260 b5f33afa Michael Hanselmann
  info = _GetInstanceInfo(instance.name)
261 cc2a70b1 Guido Trotter
  # FIXME: destruction/removal should be part of the disk class
262 cc2a70b1 Guido Trotter
  if info["storage-type"] == constants.ST_LVM_VG:
263 cc2a70b1 Guido Trotter
    vols = info["volumes"]
264 cc2a70b1 Guido Trotter
    for node in info["nodes"]:
265 cc2a70b1 Guido Trotter
      AssertCommand(["lvremove", "-f"] + vols, node=node)
266 cc2a70b1 Guido Trotter
  elif info["storage-type"] == constants.ST_FILE:
267 cc2a70b1 Guido Trotter
    # FIXME: file storage dir not configurable in qa
268 cc2a70b1 Guido Trotter
    # Note that this works for both file and sharedfile, and this is intended.
269 cc2a70b1 Guido Trotter
    filestorage = pathutils.DEFAULT_FILE_STORAGE_DIR
270 cc2a70b1 Guido Trotter
    idir = os.path.join(filestorage, instance.name)
271 cc2a70b1 Guido Trotter
    for node in info["nodes"]:
272 b0b7bf8f Guido Trotter
      AssertCommand(["rm", "-rf", idir], node=node)
273 cc2a70b1 Guido Trotter
  elif info["storage-type"] == constants.ST_DISKLESS:
274 cc2a70b1 Guido Trotter
    pass
275 82d2f3df Bernardo Dal Seno
276 82d2f3df Bernardo Dal Seno
277 ab4832d1 Bernardo Dal Seno
def _GetInstanceField(instance, field):
278 ab4832d1 Bernardo Dal Seno
  """Get the value of a field of an instance.
279 d55408b0 Bernardo Dal Seno

280 d55408b0 Bernardo Dal Seno
  @type instance: string
281 d55408b0 Bernardo Dal Seno
  @param instance: Instance name
282 d55408b0 Bernardo Dal Seno
  @type field: string
283 d55408b0 Bernardo Dal Seno
  @param field: Name of the field
284 ab4832d1 Bernardo Dal Seno
  @rtype: string
285 d55408b0 Bernardo Dal Seno

286 d55408b0 Bernardo Dal Seno
  """
287 d55408b0 Bernardo Dal Seno
  master = qa_config.GetMasterNode()
288 d55408b0 Bernardo Dal Seno
  infocmd = utils.ShellQuoteArgs(["gnt-instance", "list", "--no-headers",
289 ab4832d1 Bernardo Dal Seno
                                  "--units", "m", "-o", field, instance])
290 46d21495 Bernardo Dal Seno
  return qa_utils.GetCommandOutput(master.primary, infocmd).strip()
291 ab4832d1 Bernardo Dal Seno
292 ab4832d1 Bernardo Dal Seno
293 ab4832d1 Bernardo Dal Seno
def _GetBoolInstanceField(instance, field):
294 ab4832d1 Bernardo Dal Seno
  """Get the Boolean value of a field of an instance.
295 ab4832d1 Bernardo Dal Seno

296 ab4832d1 Bernardo Dal Seno
  @type instance: string
297 ab4832d1 Bernardo Dal Seno
  @param instance: Instance name
298 ab4832d1 Bernardo Dal Seno
  @type field: string
299 ab4832d1 Bernardo Dal Seno
  @param field: Name of the field
300 ab4832d1 Bernardo Dal Seno
  @rtype: bool
301 ab4832d1 Bernardo Dal Seno

302 ab4832d1 Bernardo Dal Seno
  """
303 ab4832d1 Bernardo Dal Seno
  info_out = _GetInstanceField(instance, field)
304 d55408b0 Bernardo Dal Seno
  if info_out == "Y":
305 d55408b0 Bernardo Dal Seno
    return True
306 d55408b0 Bernardo Dal Seno
  elif info_out == "N":
307 d55408b0 Bernardo Dal Seno
    return False
308 d55408b0 Bernardo Dal Seno
  else:
309 d55408b0 Bernardo Dal Seno
    raise qa_error.Error("Field %s of instance %s has a non-Boolean value:"
310 d55408b0 Bernardo Dal Seno
                         " %s" % (field, instance, info_out))
311 d55408b0 Bernardo Dal Seno
312 d55408b0 Bernardo Dal Seno
313 ab4832d1 Bernardo Dal Seno
def _GetNumInstanceField(instance, field):
314 ab4832d1 Bernardo Dal Seno
  """Get a numeric value of a field of an instance.
315 ab4832d1 Bernardo Dal Seno

316 ab4832d1 Bernardo Dal Seno
  @type instance: string
317 ab4832d1 Bernardo Dal Seno
  @param instance: Instance name
318 ab4832d1 Bernardo Dal Seno
  @type field: string
319 ab4832d1 Bernardo Dal Seno
  @param field: Name of the field
320 ab4832d1 Bernardo Dal Seno
  @rtype: int or float
321 ab4832d1 Bernardo Dal Seno

322 ab4832d1 Bernardo Dal Seno
  """
323 ab4832d1 Bernardo Dal Seno
  info_out = _GetInstanceField(instance, field)
324 ab4832d1 Bernardo Dal Seno
  try:
325 ab4832d1 Bernardo Dal Seno
    ret = int(info_out)
326 ab4832d1 Bernardo Dal Seno
  except ValueError:
327 ab4832d1 Bernardo Dal Seno
    try:
328 ab4832d1 Bernardo Dal Seno
      ret = float(info_out)
329 ab4832d1 Bernardo Dal Seno
    except ValueError:
330 ab4832d1 Bernardo Dal Seno
      raise qa_error.Error("Field %s of instance %s has a non-numeric value:"
331 ab4832d1 Bernardo Dal Seno
                           " %s" % (field, instance, info_out))
332 ab4832d1 Bernardo Dal Seno
  return ret
333 ab4832d1 Bernardo Dal Seno
334 ab4832d1 Bernardo Dal Seno
335 ab4832d1 Bernardo Dal Seno
def GetInstanceSpec(instance, spec):
336 ab4832d1 Bernardo Dal Seno
  """Return the current spec for the given parameter.
337 ab4832d1 Bernardo Dal Seno

338 ab4832d1 Bernardo Dal Seno
  @type instance: string
339 ab4832d1 Bernardo Dal Seno
  @param instance: Instance name
340 ab4832d1 Bernardo Dal Seno
  @type spec: string
341 cb178a1e Bernardo Dal Seno
  @param spec: one of the supported parameters: "memory-size", "cpu-count",
342 ab4832d1 Bernardo Dal Seno
      "disk-count", "disk-size", "nic-count"
343 ab4832d1 Bernardo Dal Seno
  @rtype: tuple
344 ab4832d1 Bernardo Dal Seno
  @return: (minspec, maxspec); minspec and maxspec can be different only for
345 ab4832d1 Bernardo Dal Seno
      memory and disk size
346 ab4832d1 Bernardo Dal Seno

347 ab4832d1 Bernardo Dal Seno
  """
348 ab4832d1 Bernardo Dal Seno
  specmap = {
349 cb178a1e Bernardo Dal Seno
    "memory-size": ["be/minmem", "be/maxmem"],
350 ab4832d1 Bernardo Dal Seno
    "cpu-count": ["vcpus"],
351 ab4832d1 Bernardo Dal Seno
    "disk-count": ["disk.count"],
352 ab4832d1 Bernardo Dal Seno
    "disk-size": ["disk.size/ "],
353 ab4832d1 Bernardo Dal Seno
    "nic-count": ["nic.count"],
354 ab4832d1 Bernardo Dal Seno
    }
355 ab4832d1 Bernardo Dal Seno
  # For disks, first we need the number of disks
356 ab4832d1 Bernardo Dal Seno
  if spec == "disk-size":
357 ab4832d1 Bernardo Dal Seno
    (numdisk, _) = GetInstanceSpec(instance, "disk-count")
358 ab4832d1 Bernardo Dal Seno
    fields = ["disk.size/%s" % k for k in range(0, numdisk)]
359 ab4832d1 Bernardo Dal Seno
  else:
360 ab4832d1 Bernardo Dal Seno
    assert spec in specmap, "%s not in %s" % (spec, specmap)
361 ab4832d1 Bernardo Dal Seno
    fields = specmap[spec]
362 ab4832d1 Bernardo Dal Seno
  values = [_GetNumInstanceField(instance, f) for f in fields]
363 ab4832d1 Bernardo Dal Seno
  return (min(values), max(values))
364 ab4832d1 Bernardo Dal Seno
365 ab4832d1 Bernardo Dal Seno
366 5de31440 Bernardo Dal Seno
def IsFailoverSupported(instance):
367 02a5fe0e Michael Hanselmann
  return instance.disk_template in constants.DTS_MIRRORED
368 5de31440 Bernardo Dal Seno
369 5de31440 Bernardo Dal Seno
370 5de31440 Bernardo Dal Seno
def IsMigrationSupported(instance):
371 02a5fe0e Michael Hanselmann
  return instance.disk_template in constants.DTS_MIRRORED
372 5de31440 Bernardo Dal Seno
373 5de31440 Bernardo Dal Seno
374 5de31440 Bernardo Dal Seno
def IsDiskReplacingSupported(instance):
375 02a5fe0e Michael Hanselmann
  return instance.disk_template == constants.DT_DRBD8
376 5de31440 Bernardo Dal Seno
377 5de31440 Bernardo Dal Seno
378 fa84c8a4 Bernardo Dal Seno
def TestInstanceAddWithPlainDisk(nodes, fail=False):
379 cec9845c Michael Hanselmann
  """gnt-instance add -t plain"""
380 f41dc024 Helga Velroyen
  if constants.DT_PLAIN in qa_config.GetEnabledDiskTemplates():
381 f41dc024 Helga Velroyen
    instance = _CreateInstanceByDiskTemplateOneNode(nodes, constants.DT_PLAIN,
382 f41dc024 Helga Velroyen
                                                    fail=fail)
383 f41dc024 Helga Velroyen
    if not fail:
384 f41dc024 Helga Velroyen
      qa_utils.RunInstanceCheck(instance, True)
385 f41dc024 Helga Velroyen
    return instance
386 cec9845c Michael Hanselmann
387 cec9845c Michael Hanselmann
388 5fa0375e Michael Hanselmann
@InstanceCheck(None, INST_UP, RETURN_VALUE)
389 c99200a3 Bernardo Dal Seno
def TestInstanceAddWithDrbdDisk(nodes):
390 7d7609a3 Michael Hanselmann
  """gnt-instance add -t drbd"""
391 f41dc024 Helga Velroyen
  if constants.DT_DRBD8 in qa_config.GetEnabledDiskTemplates():
392 f41dc024 Helga Velroyen
    return _CreateInstanceDrbd8(nodes)
393 7d7609a3 Michael Hanselmann
394 7d7609a3 Michael Hanselmann
395 59c75517 Michael Hanselmann
@InstanceCheck(None, INST_UP, RETURN_VALUE)
396 6970c89c Klaus Aehlig
def TestInstanceAddFile(nodes):
397 6970c89c Klaus Aehlig
  """gnt-instance add -t file"""
398 6970c89c Klaus Aehlig
  assert len(nodes) == 1
399 f41dc024 Helga Velroyen
  if constants.DT_FILE in qa_config.GetEnabledDiskTemplates():
400 f41dc024 Helga Velroyen
    return _CreateInstanceByDiskTemplateOneNode(nodes, constants.DT_FILE)
401 6970c89c Klaus Aehlig
402 6970c89c Klaus Aehlig
403 6970c89c Klaus Aehlig
@InstanceCheck(None, INST_UP, RETURN_VALUE)
404 59c75517 Michael Hanselmann
def TestInstanceAddDiskless(nodes):
405 59c75517 Michael Hanselmann
  """gnt-instance add -t diskless"""
406 59c75517 Michael Hanselmann
  assert len(nodes) == 1
407 f41dc024 Helga Velroyen
  if constants.DT_FILE in qa_config.GetEnabledDiskTemplates():
408 f41dc024 Helga Velroyen
    return _CreateInstanceByDiskTemplateOneNode(nodes, constants.DT_DISKLESS)
409 59c75517 Michael Hanselmann
410 59c75517 Michael Hanselmann
411 5fa0375e Michael Hanselmann
@InstanceCheck(None, INST_DOWN, FIRST_ARG)
412 cec9845c Michael Hanselmann
def TestInstanceRemove(instance):
413 cec9845c Michael Hanselmann
  """gnt-instance remove"""
414 b5f33afa Michael Hanselmann
  AssertCommand(["gnt-instance", "remove", "-f", instance.name])
415 cec9845c Michael Hanselmann
416 cec9845c Michael Hanselmann
417 5fa0375e Michael Hanselmann
@InstanceCheck(INST_DOWN, INST_UP, FIRST_ARG)
418 cec9845c Michael Hanselmann
def TestInstanceStartup(instance):
419 cec9845c Michael Hanselmann
  """gnt-instance startup"""
420 b5f33afa Michael Hanselmann
  AssertCommand(["gnt-instance", "startup", instance.name])
421 cec9845c Michael Hanselmann
422 cec9845c Michael Hanselmann
423 5fa0375e Michael Hanselmann
@InstanceCheck(INST_UP, INST_DOWN, FIRST_ARG)
424 cec9845c Michael Hanselmann
def TestInstanceShutdown(instance):
425 cec9845c Michael Hanselmann
  """gnt-instance shutdown"""
426 b5f33afa Michael Hanselmann
  AssertCommand(["gnt-instance", "shutdown", instance.name])
427 cec9845c Michael Hanselmann
428 cec9845c Michael Hanselmann
429 5fa0375e Michael Hanselmann
@InstanceCheck(INST_UP, INST_UP, FIRST_ARG)
430 8a4e8898 Michael Hanselmann
def TestInstanceReboot(instance):
431 8a4e8898 Michael Hanselmann
  """gnt-instance reboot"""
432 d0c8c01d Iustin Pop
  options = qa_config.get("options", {})
433 1d103c02 Iustin Pop
  reboot_types = options.get("reboot-types", constants.REBOOT_TYPES)
434 b5f33afa Michael Hanselmann
  name = instance.name
435 1d103c02 Iustin Pop
  for rtype in reboot_types:
436 2f4b4f78 Iustin Pop
    AssertCommand(["gnt-instance", "reboot", "--type=%s" % rtype, name])
437 8a4e8898 Michael Hanselmann
438 cc27265e René Nussbaumer
  AssertCommand(["gnt-instance", "shutdown", name])
439 5fa0375e Michael Hanselmann
  qa_utils.RunInstanceCheck(instance, False)
440 cc27265e René Nussbaumer
  AssertCommand(["gnt-instance", "reboot", name])
441 cc27265e René Nussbaumer
442 cc27265e René Nussbaumer
  master = qa_config.GetMasterNode()
443 58ea8d17 Michael Hanselmann
  cmd = ["gnt-instance", "list", "--no-headers", "-o", "status", name]
444 aecba21e Michael Hanselmann
  result_output = qa_utils.GetCommandOutput(master.primary,
445 cc27265e René Nussbaumer
                                            utils.ShellQuoteArgs(cmd))
446 cc27265e René Nussbaumer
  AssertEqual(result_output.strip(), constants.INSTST_RUNNING)
447 cc27265e René Nussbaumer
448 8a4e8898 Michael Hanselmann
449 5fa0375e Michael Hanselmann
@InstanceCheck(INST_DOWN, INST_DOWN, FIRST_ARG)
450 283f9d4c Michael Hanselmann
def TestInstanceReinstall(instance):
451 283f9d4c Michael Hanselmann
  """gnt-instance reinstall"""
452 a90636b2 Michael Hanselmann
  if instance.disk_template == constants.DT_DISKLESS:
453 a90636b2 Michael Hanselmann
    print qa_utils.FormatInfo("Test not supported for diskless instances")
454 a90636b2 Michael Hanselmann
    return
455 a90636b2 Michael Hanselmann
456 b5f33afa Michael Hanselmann
  AssertCommand(["gnt-instance", "reinstall", "-f", instance.name])
457 283f9d4c Michael Hanselmann
458 64be07b1 Michael Hanselmann
  # Test with non-existant OS definition
459 64be07b1 Michael Hanselmann
  AssertCommand(["gnt-instance", "reinstall", "-f",
460 64be07b1 Michael Hanselmann
                 "--os-type=NonExistantOsForQa",
461 b5f33afa Michael Hanselmann
                 instance.name],
462 64be07b1 Michael Hanselmann
                fail=True)
463 64be07b1 Michael Hanselmann
464 283f9d4c Michael Hanselmann
465 6a343475 Michael Hanselmann
def _ReadSsconfInstanceList():
466 6a343475 Michael Hanselmann
  """Reads ssconf_instance_list from the master node.
467 6a343475 Michael Hanselmann

468 6a343475 Michael Hanselmann
  """
469 6a343475 Michael Hanselmann
  master = qa_config.GetMasterNode()
470 6a343475 Michael Hanselmann
471 e35c341e Michael Hanselmann
  ssconf_path = utils.PathJoin(pathutils.DATA_DIR,
472 e35c341e Michael Hanselmann
                               "ssconf_%s" % constants.SS_INSTANCE_LIST)
473 e35c341e Michael Hanselmann
474 e35c341e Michael Hanselmann
  cmd = ["cat", qa_utils.MakeNodePath(master, ssconf_path)]
475 6a343475 Michael Hanselmann
476 aecba21e Michael Hanselmann
  return qa_utils.GetCommandOutput(master.primary,
477 6a343475 Michael Hanselmann
                                   utils.ShellQuoteArgs(cmd)).splitlines()
478 6a343475 Michael Hanselmann
479 6a343475 Michael Hanselmann
480 6a343475 Michael Hanselmann
def _CheckSsconfInstanceList(instance):
481 6a343475 Michael Hanselmann
  """Checks if a certain instance is in the ssconf instance list.
482 6a343475 Michael Hanselmann

483 6a343475 Michael Hanselmann
  @type instance: string
484 6a343475 Michael Hanselmann
  @param instance: Instance name
485 6a343475 Michael Hanselmann

486 6a343475 Michael Hanselmann
  """
487 6a343475 Michael Hanselmann
  AssertIn(qa_utils.ResolveInstanceName(instance),
488 6a343475 Michael Hanselmann
           _ReadSsconfInstanceList())
489 6a343475 Michael Hanselmann
490 6a343475 Michael Hanselmann
491 51131cad Michael Hanselmann
@InstanceCheck(INST_DOWN, INST_DOWN, FIRST_ARG)
492 4c1a464b Iustin Pop
def TestInstanceRenameAndBack(rename_source, rename_target):
493 4c1a464b Iustin Pop
  """gnt-instance rename
494 4c1a464b Iustin Pop

495 4c1a464b Iustin Pop
  This must leave the instance with the original name, not the target
496 4c1a464b Iustin Pop
  name.
497 4c1a464b Iustin Pop

498 4c1a464b Iustin Pop
  """
499 31fe5102 René Nussbaumer
  _CheckSsconfInstanceList(rename_source)
500 5fa0375e Michael Hanselmann
501 4c1a464b Iustin Pop
  # first do a rename to a different actual name, expecting it to fail
502 31fe5102 René Nussbaumer
  qa_utils.AddToEtcHosts(["meeeeh-not-exists", rename_target])
503 31fe5102 René Nussbaumer
  try:
504 31fe5102 René Nussbaumer
    AssertCommand(["gnt-instance", "rename", rename_source, rename_target],
505 31fe5102 René Nussbaumer
                  fail=True)
506 31fe5102 René Nussbaumer
    _CheckSsconfInstanceList(rename_source)
507 31fe5102 René Nussbaumer
  finally:
508 31fe5102 René Nussbaumer
    qa_utils.RemoveFromEtcHosts(["meeeeh-not-exists", rename_target])
509 5fa0375e Michael Hanselmann
510 b07afbb3 Iustin Pop
  info = _GetInstanceInfo(rename_source)
511 1012ecf4 Guido Trotter
512 1012ecf4 Guido Trotter
  # Check instance volume tags correctly updated. Note that this check is lvm
513 1012ecf4 Guido Trotter
  # specific, so we skip it for non-lvm-based instances.
514 1012ecf4 Guido Trotter
  # FIXME: This will need updating when instances will be able to have
515 1012ecf4 Guido Trotter
  # different disks living on storage pools with etherogeneous storage types.
516 1012ecf4 Guido Trotter
  # FIXME: This check should be put inside the disk/storage class themselves,
517 1012ecf4 Guido Trotter
  # rather than explicitly called here.
518 1012ecf4 Guido Trotter
  if info["storage-type"] == constants.ST_LVM_VG:
519 1012ecf4 Guido Trotter
    # In the lvm world we can check for tags on the logical volume
520 1012ecf4 Guido Trotter
    tags_cmd = ("lvs -o tags --noheadings %s | grep " %
521 1012ecf4 Guido Trotter
                (" ".join(info["volumes"]), ))
522 1012ecf4 Guido Trotter
  else:
523 1012ecf4 Guido Trotter
    # Other storage types don't have tags, so we use an always failing command,
524 1012ecf4 Guido Trotter
    # to make sure it never gets executed
525 1012ecf4 Guido Trotter
    tags_cmd = "false"
526 b07afbb3 Iustin Pop
527 4c1a464b Iustin Pop
  # and now rename instance to rename_target...
528 31fe5102 René Nussbaumer
  AssertCommand(["gnt-instance", "rename", rename_source, rename_target])
529 31fe5102 René Nussbaumer
  _CheckSsconfInstanceList(rename_target)
530 5fa0375e Michael Hanselmann
  qa_utils.RunInstanceCheck(rename_source, False)
531 51131cad Michael Hanselmann
  qa_utils.RunInstanceCheck(rename_target, False)
532 5fa0375e Michael Hanselmann
533 b07afbb3 Iustin Pop
  # NOTE: tags might not be the exactly as the instance name, due to
534 b07afbb3 Iustin Pop
  # charset restrictions; hence the test might be flaky
535 1012ecf4 Guido Trotter
  if (rename_source != rename_target and
536 1012ecf4 Guido Trotter
      info["storage-type"] == constants.ST_LVM_VG):
537 b07afbb3 Iustin Pop
    for node in info["nodes"]:
538 b07afbb3 Iustin Pop
      AssertCommand(tags_cmd + rename_source, node=node, fail=True)
539 b07afbb3 Iustin Pop
      AssertCommand(tags_cmd + rename_target, node=node, fail=False)
540 b07afbb3 Iustin Pop
541 4c1a464b Iustin Pop
  # and back
542 4c1a464b Iustin Pop
  AssertCommand(["gnt-instance", "rename", rename_target, rename_source])
543 4c1a464b Iustin Pop
  _CheckSsconfInstanceList(rename_source)
544 5fa0375e Michael Hanselmann
  qa_utils.RunInstanceCheck(rename_target, False)
545 18337ca9 Iustin Pop
546 1012ecf4 Guido Trotter
  if (rename_source != rename_target and
547 1012ecf4 Guido Trotter
      info["storage-type"] == constants.ST_LVM_VG):
548 b07afbb3 Iustin Pop
    for node in info["nodes"]:
549 b07afbb3 Iustin Pop
      AssertCommand(tags_cmd + rename_source, node=node, fail=False)
550 b07afbb3 Iustin Pop
      AssertCommand(tags_cmd + rename_target, node=node, fail=True)
551 b07afbb3 Iustin Pop
552 18337ca9 Iustin Pop
553 5fa0375e Michael Hanselmann
@InstanceCheck(INST_UP, INST_UP, FIRST_ARG)
554 cec9845c Michael Hanselmann
def TestInstanceFailover(instance):
555 cec9845c Michael Hanselmann
  """gnt-instance failover"""
556 5de31440 Bernardo Dal Seno
  if not IsFailoverSupported(instance):
557 5de31440 Bernardo Dal Seno
    print qa_utils.FormatInfo("Instance doesn't support failover, skipping"
558 5de31440 Bernardo Dal Seno
                              " test")
559 5de31440 Bernardo Dal Seno
    return
560 5de31440 Bernardo Dal Seno
561 b5f33afa Michael Hanselmann
  cmd = ["gnt-instance", "failover", "--force", instance.name]
562 5fa0375e Michael Hanselmann
563 2f4b4f78 Iustin Pop
  # failover ...
564 2f4b4f78 Iustin Pop
  AssertCommand(cmd)
565 5fa0375e Michael Hanselmann
  qa_utils.RunInstanceCheck(instance, True)
566 5fa0375e Michael Hanselmann
567 76f59a32 Michael Hanselmann
  # ... and back
568 2f4b4f78 Iustin Pop
  AssertCommand(cmd)
569 76f59a32 Michael Hanselmann
570 cec9845c Michael Hanselmann
571 5fa0375e Michael Hanselmann
@InstanceCheck(INST_UP, INST_UP, FIRST_ARG)
572 d55408b0 Bernardo Dal Seno
def TestInstanceMigrate(instance, toggle_always_failover=True):
573 938bde86 Michael Hanselmann
  """gnt-instance migrate"""
574 5de31440 Bernardo Dal Seno
  if not IsMigrationSupported(instance):
575 5de31440 Bernardo Dal Seno
    print qa_utils.FormatInfo("Instance doesn't support migration, skipping"
576 5de31440 Bernardo Dal Seno
                              " test")
577 5de31440 Bernardo Dal Seno
    return
578 5de31440 Bernardo Dal Seno
579 b5f33afa Michael Hanselmann
  cmd = ["gnt-instance", "migrate", "--force", instance.name]
580 d55408b0 Bernardo Dal Seno
  af_par = constants.BE_ALWAYS_FAILOVER
581 d55408b0 Bernardo Dal Seno
  af_field = "be/" + constants.BE_ALWAYS_FAILOVER
582 b5f33afa Michael Hanselmann
  af_init_val = _GetBoolInstanceField(instance.name, af_field)
583 5fa0375e Michael Hanselmann
584 2f4b4f78 Iustin Pop
  # migrate ...
585 2f4b4f78 Iustin Pop
  AssertCommand(cmd)
586 d55408b0 Bernardo Dal Seno
  # TODO: Verify the choice between failover and migration
587 5fa0375e Michael Hanselmann
  qa_utils.RunInstanceCheck(instance, True)
588 5fa0375e Michael Hanselmann
589 d55408b0 Bernardo Dal Seno
  # ... and back (possibly with always_failover toggled)
590 d55408b0 Bernardo Dal Seno
  if toggle_always_failover:
591 d55408b0 Bernardo Dal Seno
    AssertCommand(["gnt-instance", "modify", "-B",
592 d55408b0 Bernardo Dal Seno
                   ("%s=%s" % (af_par, not af_init_val)),
593 b5f33afa Michael Hanselmann
                   instance.name])
594 2f4b4f78 Iustin Pop
  AssertCommand(cmd)
595 d55408b0 Bernardo Dal Seno
  # TODO: Verify the choice between failover and migration
596 d55408b0 Bernardo Dal Seno
  qa_utils.RunInstanceCheck(instance, True)
597 d55408b0 Bernardo Dal Seno
  if toggle_always_failover:
598 d55408b0 Bernardo Dal Seno
    AssertCommand(["gnt-instance", "modify", "-B",
599 b5f33afa Michael Hanselmann
                   ("%s=%s" % (af_par, af_init_val)), instance.name])
600 5fa0375e Michael Hanselmann
601 5fa0375e Michael Hanselmann
  # TODO: Split into multiple tests
602 b5f33afa Michael Hanselmann
  AssertCommand(["gnt-instance", "shutdown", instance.name])
603 5fa0375e Michael Hanselmann
  qa_utils.RunInstanceCheck(instance, False)
604 e9c487be René Nussbaumer
  AssertCommand(cmd, fail=True)
605 e9c487be René Nussbaumer
  AssertCommand(["gnt-instance", "migrate", "--force", "--allow-failover",
606 b5f33afa Michael Hanselmann
                 instance.name])
607 b5f33afa Michael Hanselmann
  AssertCommand(["gnt-instance", "start", instance.name])
608 e9c487be René Nussbaumer
  AssertCommand(cmd)
609 d55408b0 Bernardo Dal Seno
  # @InstanceCheck enforces the check that the instance is running
610 5fa0375e Michael Hanselmann
  qa_utils.RunInstanceCheck(instance, True)
611 5fa0375e Michael Hanselmann
612 42a769f9 Bernardo Dal Seno
  AssertCommand(["gnt-instance", "modify", "-B",
613 42a769f9 Bernardo Dal Seno
                 ("%s=%s" %
614 42a769f9 Bernardo Dal Seno
                  (constants.BE_ALWAYS_FAILOVER, constants.VALUE_TRUE)),
615 b5f33afa Michael Hanselmann
                 instance.name])
616 5fa0375e Michael Hanselmann
617 320a5dae Bernardo Dal Seno
  AssertCommand(cmd)
618 5fa0375e Michael Hanselmann
  qa_utils.RunInstanceCheck(instance, True)
619 320a5dae Bernardo Dal Seno
  # TODO: Verify that a failover has been done instead of a migration
620 5fa0375e Michael Hanselmann
621 5fa0375e Michael Hanselmann
  # TODO: Verify whether the default value is restored here (not hardcoded)
622 42a769f9 Bernardo Dal Seno
  AssertCommand(["gnt-instance", "modify", "-B",
623 42a769f9 Bernardo Dal Seno
                 ("%s=%s" %
624 42a769f9 Bernardo Dal Seno
                  (constants.BE_ALWAYS_FAILOVER, constants.VALUE_FALSE)),
625 b5f33afa Michael Hanselmann
                 instance.name])
626 5fa0375e Michael Hanselmann
627 42a769f9 Bernardo Dal Seno
  AssertCommand(cmd)
628 5fa0375e Michael Hanselmann
  qa_utils.RunInstanceCheck(instance, True)
629 938bde86 Michael Hanselmann
630 938bde86 Michael Hanselmann
631 cec9845c Michael Hanselmann
def TestInstanceInfo(instance):
632 cec9845c Michael Hanselmann
  """gnt-instance info"""
633 b5f33afa Michael Hanselmann
  AssertCommand(["gnt-instance", "info", instance.name])
634 5d640672 Michael Hanselmann
635 5d640672 Michael Hanselmann
636 5fa0375e Michael Hanselmann
@InstanceCheck(INST_UP, INST_UP, FIRST_ARG)
637 c0f74c55 Iustin Pop
def TestInstanceModify(instance):
638 c0f74c55 Iustin Pop
  """gnt-instance modify"""
639 d488adb6 Michael Hanselmann
  default_hv = qa_config.GetDefaultHypervisor()
640 d488adb6 Michael Hanselmann
641 1d693311 Michael Hanselmann
  # Assume /sbin/init exists on all systems
642 1d693311 Michael Hanselmann
  test_kernel = "/sbin/init"
643 1d693311 Michael Hanselmann
  test_initrd = test_kernel
644 1d693311 Michael Hanselmann
645 8ccbbe4b Guido Trotter
  orig_maxmem = qa_config.get(constants.BE_MAXMEM)
646 8ccbbe4b Guido Trotter
  orig_minmem = qa_config.get(constants.BE_MINMEM)
647 2f4b4f78 Iustin Pop
  #orig_bridge = qa_config.get("bridge", "xen-br0")
648 d488adb6 Michael Hanselmann
649 c0f74c55 Iustin Pop
  args = [
650 8ccbbe4b Guido Trotter
    ["-B", "%s=128" % constants.BE_MINMEM],
651 8ccbbe4b Guido Trotter
    ["-B", "%s=128" % constants.BE_MAXMEM],
652 8ccbbe4b Guido Trotter
    ["-B", "%s=%s,%s=%s" % (constants.BE_MINMEM, orig_minmem,
653 8ccbbe4b Guido Trotter
                            constants.BE_MAXMEM, orig_maxmem)],
654 1d693311 Michael Hanselmann
    ["-B", "%s=2" % constants.BE_VCPUS],
655 1d693311 Michael Hanselmann
    ["-B", "%s=1" % constants.BE_VCPUS],
656 1d693311 Michael Hanselmann
    ["-B", "%s=%s" % (constants.BE_VCPUS, constants.VALUE_DEFAULT)],
657 42a769f9 Bernardo Dal Seno
    ["-B", "%s=%s" % (constants.BE_ALWAYS_FAILOVER, constants.VALUE_TRUE)],
658 42a769f9 Bernardo Dal Seno
    ["-B", "%s=%s" % (constants.BE_ALWAYS_FAILOVER, constants.VALUE_DEFAULT)],
659 1d693311 Michael Hanselmann
660 1d693311 Michael Hanselmann
    ["-H", "%s=%s" % (constants.HV_KERNEL_PATH, test_kernel)],
661 1d693311 Michael Hanselmann
    ["-H", "%s=%s" % (constants.HV_KERNEL_PATH, constants.VALUE_DEFAULT)],
662 1d693311 Michael Hanselmann
663 1d693311 Michael Hanselmann
    # TODO: bridge tests
664 1d693311 Michael Hanselmann
    #["--bridge", "xen-br1"],
665 1d693311 Michael Hanselmann
    #["--bridge", orig_bridge],
666 c0f74c55 Iustin Pop
    ]
667 d488adb6 Michael Hanselmann
668 d488adb6 Michael Hanselmann
  if default_hv == constants.HT_XEN_PVM:
669 d488adb6 Michael Hanselmann
    args.extend([
670 d488adb6 Michael Hanselmann
      ["-H", "%s=%s" % (constants.HV_INITRD_PATH, test_initrd)],
671 d488adb6 Michael Hanselmann
      ["-H", "no_%s" % (constants.HV_INITRD_PATH, )],
672 d488adb6 Michael Hanselmann
      ["-H", "%s=%s" % (constants.HV_INITRD_PATH, constants.VALUE_DEFAULT)],
673 d488adb6 Michael Hanselmann
      ])
674 d488adb6 Michael Hanselmann
  elif default_hv == constants.HT_XEN_HVM:
675 d488adb6 Michael Hanselmann
    args.extend([
676 d488adb6 Michael Hanselmann
      ["-H", "%s=acn" % constants.HV_BOOT_ORDER],
677 d488adb6 Michael Hanselmann
      ["-H", "%s=%s" % (constants.HV_BOOT_ORDER, constants.VALUE_DEFAULT)],
678 d488adb6 Michael Hanselmann
      ])
679 d488adb6 Michael Hanselmann
680 c0f74c55 Iustin Pop
  for alist in args:
681 b5f33afa Michael Hanselmann
    AssertCommand(["gnt-instance", "modify"] + alist + [instance.name])
682 c0f74c55 Iustin Pop
683 c0f74c55 Iustin Pop
  # check no-modify
684 b5f33afa Michael Hanselmann
  AssertCommand(["gnt-instance", "modify", instance.name], fail=True)
685 c0f74c55 Iustin Pop
686 1ba25bad Guido Trotter
  # Marking offline while instance is running must fail...
687 b5f33afa Michael Hanselmann
  AssertCommand(["gnt-instance", "modify", "--offline", instance.name],
688 1ba25bad Guido Trotter
                 fail=True)
689 1ba25bad Guido Trotter
690 1ba25bad Guido Trotter
  # ...while making it online is ok, and should work
691 b5f33afa Michael Hanselmann
  AssertCommand(["gnt-instance", "modify", "--online", instance.name])
692 3016bc1f Michael Hanselmann
693 3016bc1f Michael Hanselmann
694 d0a44ec0 Klaus Aehlig
@InstanceCheck(INST_UP, INST_UP, FIRST_ARG)
695 d0a44ec0 Klaus Aehlig
def TestInstanceModifyPrimaryAndBack(instance, currentnode, othernode):
696 d0a44ec0 Klaus Aehlig
  """gnt-instance modify --new-primary
697 d0a44ec0 Klaus Aehlig

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

700 d0a44ec0 Klaus Aehlig
  """
701 d0a44ec0 Klaus Aehlig
  if instance.disk_template != constants.DT_FILE:
702 d0a44ec0 Klaus Aehlig
    print qa_utils.FormatInfo("Test only supported for the file disk template")
703 d0a44ec0 Klaus Aehlig
    return
704 d0a44ec0 Klaus Aehlig
705 049a6c6b Guido Trotter
  cluster_name = qa_config.get("name")
706 049a6c6b Guido Trotter
707 d0a44ec0 Klaus Aehlig
  name = instance.name
708 d0a44ec0 Klaus Aehlig
  current = currentnode.primary
709 d0a44ec0 Klaus Aehlig
  other = othernode.primary
710 d0a44ec0 Klaus Aehlig
711 0b85e1bd Guido Trotter
  # FIXME: the qa doesn't have a customizable file storage dir parameter. As
712 0b85e1bd Guido Trotter
  # such for now we use the default.
713 0b85e1bd Guido Trotter
  filestorage = pathutils.DEFAULT_FILE_STORAGE_DIR
714 d0a44ec0 Klaus Aehlig
  disk = os.path.join(filestorage, name)
715 d0a44ec0 Klaus Aehlig
716 d0a44ec0 Klaus Aehlig
  AssertCommand(["gnt-instance", "modify", "--new-primary=%s" % other, name],
717 d0a44ec0 Klaus Aehlig
                fail=True)
718 d0a44ec0 Klaus Aehlig
  AssertCommand(["gnt-instance", "shutdown", name])
719 049a6c6b Guido Trotter
  AssertCommand(["scp", "-oGlobalKnownHostsFile=%s" %
720 049a6c6b Guido Trotter
                 pathutils.SSH_KNOWN_HOSTS_FILE,
721 049a6c6b Guido Trotter
                 "-oCheckHostIp=no", "-oStrictHostKeyChecking=yes",
722 049a6c6b Guido Trotter
                 "-oHashKnownHosts=no", "-oHostKeyAlias=%s" % cluster_name,
723 f0ed67ed Guido Trotter
                 "-r", disk, "%s:%s" % (other, filestorage)], node=current)
724 d0a44ec0 Klaus Aehlig
  AssertCommand(["gnt-instance", "modify", "--new-primary=%s" % other, name])
725 d0a44ec0 Klaus Aehlig
  AssertCommand(["gnt-instance", "startup", name])
726 d0a44ec0 Klaus Aehlig
727 d0a44ec0 Klaus Aehlig
  # and back
728 d0a44ec0 Klaus Aehlig
  AssertCommand(["gnt-instance", "shutdown", name])
729 d0a44ec0 Klaus Aehlig
  AssertCommand(["rm", "-rf", disk], node=other)
730 d0a44ec0 Klaus Aehlig
  AssertCommand(["gnt-instance", "modify", "--new-primary=%s" % current, name])
731 d0a44ec0 Klaus Aehlig
  AssertCommand(["gnt-instance", "startup", name])
732 d0a44ec0 Klaus Aehlig
733 d0a44ec0 Klaus Aehlig
734 5fa0375e Michael Hanselmann
@InstanceCheck(INST_DOWN, INST_DOWN, FIRST_ARG)
735 3016bc1f Michael Hanselmann
def TestInstanceStoppedModify(instance):
736 3016bc1f Michael Hanselmann
  """gnt-instance modify (stopped instance)"""
737 b5f33afa Michael Hanselmann
  name = instance.name
738 3016bc1f Michael Hanselmann
739 58f0ce16 Michael Hanselmann
  # Instance was not marked offline; try marking it online once more
740 58f0ce16 Michael Hanselmann
  AssertCommand(["gnt-instance", "modify", "--online", name])
741 3016bc1f Michael Hanselmann
742 3016bc1f Michael Hanselmann
  # Mark instance as offline
743 3016bc1f Michael Hanselmann
  AssertCommand(["gnt-instance", "modify", "--offline", name])
744 3016bc1f Michael Hanselmann
745 1ba25bad Guido Trotter
  # When the instance is offline shutdown should only work with --force,
746 1ba25bad Guido Trotter
  # while start should never work
747 1ba25bad Guido Trotter
  AssertCommand(["gnt-instance", "shutdown", name], fail=True)
748 1ba25bad Guido Trotter
  AssertCommand(["gnt-instance", "shutdown", "--force", name])
749 1ba25bad Guido Trotter
  AssertCommand(["gnt-instance", "start", name], fail=True)
750 1ba25bad Guido Trotter
  AssertCommand(["gnt-instance", "start", "--force", name], fail=True)
751 1ba25bad Guido Trotter
752 1ba25bad Guido Trotter
  # Also do offline to offline
753 1ba25bad Guido Trotter
  AssertCommand(["gnt-instance", "modify", "--offline", name])
754 1ba25bad Guido Trotter
755 3016bc1f Michael Hanselmann
  # And online again
756 3016bc1f Michael Hanselmann
  AssertCommand(["gnt-instance", "modify", "--online", name])
757 3016bc1f Michael Hanselmann
758 c0f74c55 Iustin Pop
759 5fa0375e Michael Hanselmann
@InstanceCheck(INST_DOWN, INST_DOWN, FIRST_ARG)
760 c99200a3 Bernardo Dal Seno
def TestInstanceConvertDiskToPlain(instance, inodes):
761 7f69aabb Iustin Pop
  """gnt-instance modify -t"""
762 b5f33afa Michael Hanselmann
  name = instance.name
763 68c8c3df Michael Hanselmann
764 02a5fe0e Michael Hanselmann
  template = instance.disk_template
765 68c8c3df Michael Hanselmann
  if template != constants.DT_DRBD8:
766 5de31440 Bernardo Dal Seno
    print qa_utils.FormatInfo("Unsupported template %s, skipping conversion"
767 5de31440 Bernardo Dal Seno
                              " test" % template)
768 5de31440 Bernardo Dal Seno
    return
769 68c8c3df Michael Hanselmann
770 c99200a3 Bernardo Dal Seno
  assert len(inodes) == 2
771 68c8c3df Michael Hanselmann
  AssertCommand(["gnt-instance", "modify", "-t", constants.DT_PLAIN, name])
772 68c8c3df Michael Hanselmann
  AssertCommand(["gnt-instance", "modify", "-t", constants.DT_DRBD8,
773 aecba21e Michael Hanselmann
                 "-n", inodes[1].primary, name])
774 7f69aabb Iustin Pop
775 7f69aabb Iustin Pop
776 5fa0375e Michael Hanselmann
@InstanceCheck(INST_DOWN, INST_DOWN, FIRST_ARG)
777 26a5056d Iustin Pop
def TestInstanceGrowDisk(instance):
778 26a5056d Iustin Pop
  """gnt-instance grow-disk"""
779 5de31440 Bernardo Dal Seno
  if qa_config.GetExclusiveStorage():
780 5de31440 Bernardo Dal Seno
    print qa_utils.FormatInfo("Test not supported with exclusive_storage")
781 5de31440 Bernardo Dal Seno
    return
782 59c75517 Michael Hanselmann
783 59c75517 Michael Hanselmann
  if instance.disk_template == constants.DT_DISKLESS:
784 59c75517 Michael Hanselmann
    print qa_utils.FormatInfo("Test not supported for diskless instances")
785 59c75517 Michael Hanselmann
    return
786 59c75517 Michael Hanselmann
787 b5f33afa Michael Hanselmann
  name = instance.name
788 090128b6 Christos Stavrakakis
  disks = qa_config.GetDiskOptions()
789 090128b6 Christos Stavrakakis
  all_size = [d.get("size") for d in disks]
790 090128b6 Christos Stavrakakis
  all_grow = [d.get("growth") for d in disks]
791 59c75517 Michael Hanselmann
792 26a5056d Iustin Pop
  if not all_grow:
793 26a5056d Iustin Pop
    # missing disk sizes but instance grow disk has been enabled,
794 26a5056d Iustin Pop
    # let's set fixed/nomimal growth
795 26a5056d Iustin Pop
    all_grow = ["128M" for _ in all_size]
796 59c75517 Michael Hanselmann
797 26a5056d Iustin Pop
  for idx, (size, grow) in enumerate(zip(all_size, all_grow)):
798 26a5056d Iustin Pop
    # succeed in grow by amount
799 26a5056d Iustin Pop
    AssertCommand(["gnt-instance", "grow-disk", name, str(idx), grow])
800 26a5056d Iustin Pop
    # fail in grow to the old size
801 26a5056d Iustin Pop
    AssertCommand(["gnt-instance", "grow-disk", "--absolute", name, str(idx),
802 26a5056d Iustin Pop
                   size], fail=True)
803 26a5056d Iustin Pop
    # succeed to grow to old size + 2 * growth
804 26a5056d Iustin Pop
    int_size = utils.ParseUnit(size)
805 26a5056d Iustin Pop
    int_grow = utils.ParseUnit(grow)
806 26a5056d Iustin Pop
    AssertCommand(["gnt-instance", "grow-disk", "--absolute", name, str(idx),
807 26a5056d Iustin Pop
                   str(int_size + 2 * int_grow)])
808 26a5056d Iustin Pop
809 26a5056d Iustin Pop
810 090128b6 Christos Stavrakakis
@InstanceCheck(INST_UP, INST_UP, FIRST_ARG)
811 090128b6 Christos Stavrakakis
def TestInstanceDeviceNames(instance):
812 090128b6 Christos Stavrakakis
  if instance.disk_template == constants.DT_DISKLESS:
813 090128b6 Christos Stavrakakis
    print qa_utils.FormatInfo("Test not supported for diskless instances")
814 090128b6 Christos Stavrakakis
    return
815 090128b6 Christos Stavrakakis
816 090128b6 Christos Stavrakakis
  name = instance.name
817 090128b6 Christos Stavrakakis
  for dev_type in ["disk", "net"]:
818 090128b6 Christos Stavrakakis
    if dev_type == "disk":
819 090128b6 Christos Stavrakakis
      options = ",size=512M"
820 090128b6 Christos Stavrakakis
    else:
821 090128b6 Christos Stavrakakis
      options = ""
822 090128b6 Christos Stavrakakis
    # succeed in adding a device named 'test_device'
823 090128b6 Christos Stavrakakis
    AssertCommand(["gnt-instance", "modify",
824 090128b6 Christos Stavrakakis
                   "--%s=-1:add,name=test_device%s" % (dev_type, options),
825 090128b6 Christos Stavrakakis
                   name])
826 090128b6 Christos Stavrakakis
    # succeed in removing the 'test_device'
827 090128b6 Christos Stavrakakis
    AssertCommand(["gnt-instance", "modify",
828 090128b6 Christos Stavrakakis
                   "--%s=test_device:remove" % dev_type,
829 090128b6 Christos Stavrakakis
                   name])
830 090128b6 Christos Stavrakakis
    # fail to add two devices with the same name
831 090128b6 Christos Stavrakakis
    AssertCommand(["gnt-instance", "modify",
832 090128b6 Christos Stavrakakis
                   "--%s=-1:add,name=test_device%s" % (dev_type, options),
833 090128b6 Christos Stavrakakis
                   "--%s=-1:add,name=test_device%s" % (dev_type, options),
834 090128b6 Christos Stavrakakis
                   name], fail=True)
835 090128b6 Christos Stavrakakis
    # fail to add a device with invalid name
836 090128b6 Christos Stavrakakis
    AssertCommand(["gnt-instance", "modify",
837 090128b6 Christos Stavrakakis
                   "--%s=-1:add,name=2%s" % (dev_type, options),
838 090128b6 Christos Stavrakakis
                   name], fail=True)
839 090128b6 Christos Stavrakakis
  # Rename disks
840 090128b6 Christos Stavrakakis
  disks = qa_config.GetDiskOptions()
841 090128b6 Christos Stavrakakis
  disk_names = [d.get("name") for d in disks]
842 090128b6 Christos Stavrakakis
  for idx, disk_name in enumerate(disk_names):
843 090128b6 Christos Stavrakakis
    # Refer to disk by idx
844 090128b6 Christos Stavrakakis
    AssertCommand(["gnt-instance", "modify",
845 090128b6 Christos Stavrakakis
                   "--disk=%s:modify,name=renamed" % idx,
846 090128b6 Christos Stavrakakis
                   name])
847 090128b6 Christos Stavrakakis
    # Refer to by name and rename to original name
848 090128b6 Christos Stavrakakis
    AssertCommand(["gnt-instance", "modify",
849 090128b6 Christos Stavrakakis
                   "--disk=renamed:modify,name=%s" % disk_name,
850 090128b6 Christos Stavrakakis
                   name])
851 090128b6 Christos Stavrakakis
  if len(disks) >= 2:
852 090128b6 Christos Stavrakakis
    # fail in renaming to disks to the same name
853 090128b6 Christos Stavrakakis
    AssertCommand(["gnt-instance", "modify",
854 090128b6 Christos Stavrakakis
                   "--disk=0:modify,name=same_name",
855 090128b6 Christos Stavrakakis
                   "--disk=1:modify,name=same_name",
856 090128b6 Christos Stavrakakis
                   name], fail=True)
857 090128b6 Christos Stavrakakis
858 090128b6 Christos Stavrakakis
859 283f9d4c Michael Hanselmann
def TestInstanceList():
860 283f9d4c Michael Hanselmann
  """gnt-instance list"""
861 288d6440 Michael Hanselmann
  qa_utils.GenericQueryTest("gnt-instance", query.INSTANCE_FIELDS.keys())
862 283f9d4c Michael Hanselmann
863 283f9d4c Michael Hanselmann
864 2214cf14 Michael Hanselmann
def TestInstanceListFields():
865 2214cf14 Michael Hanselmann
  """gnt-instance list-fields"""
866 2214cf14 Michael Hanselmann
  qa_utils.GenericQueryFieldsTest("gnt-instance", query.INSTANCE_FIELDS.keys())
867 2214cf14 Michael Hanselmann
868 2214cf14 Michael Hanselmann
869 5fa0375e Michael Hanselmann
@InstanceCheck(INST_UP, INST_UP, FIRST_ARG)
870 4379b1fa Michael Hanselmann
def TestInstanceConsole(instance):
871 4379b1fa Michael Hanselmann
  """gnt-instance console"""
872 b5f33afa Michael Hanselmann
  AssertCommand(["gnt-instance", "console", "--show-cmd", instance.name])
873 4379b1fa Michael Hanselmann
874 4379b1fa Michael Hanselmann
875 5fa0375e Michael Hanselmann
@InstanceCheck(INST_UP, INST_UP, FIRST_ARG)
876 c99200a3 Bernardo Dal Seno
def TestReplaceDisks(instance, curr_nodes, other_nodes):
877 7910e7a5 Michael Hanselmann
  """gnt-instance replace-disks"""
878 7910e7a5 Michael Hanselmann
  def buildcmd(args):
879 d0c8c01d Iustin Pop
    cmd = ["gnt-instance", "replace-disks"]
880 7910e7a5 Michael Hanselmann
    cmd.extend(args)
881 b5f33afa Michael Hanselmann
    cmd.append(instance.name)
882 7910e7a5 Michael Hanselmann
    return cmd
883 7910e7a5 Michael Hanselmann
884 5de31440 Bernardo Dal Seno
  if not IsDiskReplacingSupported(instance):
885 5de31440 Bernardo Dal Seno
    print qa_utils.FormatInfo("Instance doesn't support disk replacing,"
886 5de31440 Bernardo Dal Seno
                              " skipping test")
887 5de31440 Bernardo Dal Seno
    return
888 5de31440 Bernardo Dal Seno
889 c99200a3 Bernardo Dal Seno
  # Currently all supported templates have one primary and one secondary node
890 c99200a3 Bernardo Dal Seno
  assert len(curr_nodes) == 2
891 c99200a3 Bernardo Dal Seno
  snode = curr_nodes[1]
892 c99200a3 Bernardo Dal Seno
  assert len(other_nodes) == 1
893 c99200a3 Bernardo Dal Seno
  othernode = other_nodes[0]
894 c99200a3 Bernardo Dal Seno
895 e85be22a Bernardo Dal Seno
  options = qa_config.get("options", {})
896 e85be22a Bernardo Dal Seno
  use_ialloc = options.get("use-iallocators", True)
897 2f4b4f78 Iustin Pop
  for data in [
898 2f4b4f78 Iustin Pop
    ["-p"],
899 2f4b4f78 Iustin Pop
    ["-s"],
900 e85be22a Bernardo Dal Seno
    # A placeholder; the actual command choice depends on use_ialloc
901 e85be22a Bernardo Dal Seno
    None,
902 e85be22a Bernardo Dal Seno
    # Restore the original secondary
903 aecba21e Michael Hanselmann
    ["--new-secondary=%s" % snode.primary],
904 2f4b4f78 Iustin Pop
    ]:
905 e85be22a Bernardo Dal Seno
    if data is None:
906 e85be22a Bernardo Dal Seno
      if use_ialloc:
907 e85be22a Bernardo Dal Seno
        data = ["-I", constants.DEFAULT_IALLOCATOR_SHORTCUT]
908 e85be22a Bernardo Dal Seno
      else:
909 aecba21e Michael Hanselmann
        data = ["--new-secondary=%s" % othernode.primary]
910 2f4b4f78 Iustin Pop
    AssertCommand(buildcmd(data))
911 7910e7a5 Michael Hanselmann
912 9026e935 René Nussbaumer
  AssertCommand(buildcmd(["-a"]))
913 b5f33afa Michael Hanselmann
  AssertCommand(["gnt-instance", "stop", instance.name])
914 9026e935 René Nussbaumer
  AssertCommand(buildcmd(["-a"]), fail=True)
915 b5f33afa Michael Hanselmann
  AssertCommand(["gnt-instance", "activate-disks", instance.name])
916 32da72f3 Iustin Pop
  AssertCommand(["gnt-instance", "activate-disks", "--wait-for-sync",
917 b5f33afa Michael Hanselmann
                 instance.name])
918 9026e935 René Nussbaumer
  AssertCommand(buildcmd(["-a"]))
919 b5f33afa Michael Hanselmann
  AssertCommand(["gnt-instance", "start", instance.name])
920 9026e935 René Nussbaumer
921 7910e7a5 Michael Hanselmann
922 83180411 Bernardo Dal Seno
def _AssertRecreateDisks(cmdargs, instance, fail=False, check=True,
923 83180411 Bernardo Dal Seno
                         destroy=True):
924 83180411 Bernardo Dal Seno
  """Execute gnt-instance recreate-disks and check the result
925 83180411 Bernardo Dal Seno

926 83180411 Bernardo Dal Seno
  @param cmdargs: Arguments (instance name excluded)
927 83180411 Bernardo Dal Seno
  @param instance: Instance to operate on
928 83180411 Bernardo Dal Seno
  @param fail: True if the command is expected to fail
929 83180411 Bernardo Dal Seno
  @param check: If True and fail is False, check that the disks work
930 83180411 Bernardo Dal Seno
  @prama destroy: If True, destroy the old disks first
931 83180411 Bernardo Dal Seno

932 83180411 Bernardo Dal Seno
  """
933 83180411 Bernardo Dal Seno
  if destroy:
934 cc2a70b1 Guido Trotter
    _DestroyInstanceDisks(instance)
935 83180411 Bernardo Dal Seno
  AssertCommand((["gnt-instance", "recreate-disks"] + cmdargs +
936 b5f33afa Michael Hanselmann
                 [instance.name]), fail)
937 83180411 Bernardo Dal Seno
  if not fail and check:
938 83180411 Bernardo Dal Seno
    # Quick check that the disks are there
939 b5f33afa Michael Hanselmann
    AssertCommand(["gnt-instance", "activate-disks", instance.name])
940 32da72f3 Iustin Pop
    AssertCommand(["gnt-instance", "activate-disks", "--wait-for-sync",
941 b5f33afa Michael Hanselmann
                   instance.name])
942 b5f33afa Michael Hanselmann
    AssertCommand(["gnt-instance", "deactivate-disks", instance.name])
943 83180411 Bernardo Dal Seno
944 a1cd2ecf Bernardo Dal Seno
945 83180411 Bernardo Dal Seno
@InstanceCheck(INST_UP, INST_UP, FIRST_ARG)
946 c99200a3 Bernardo Dal Seno
def TestRecreateDisks(instance, inodes, othernodes):
947 83180411 Bernardo Dal Seno
  """gnt-instance recreate-disks
948 83180411 Bernardo Dal Seno

949 83180411 Bernardo Dal Seno
  @param instance: Instance to work on
950 c99200a3 Bernardo Dal Seno
  @param inodes: List of the current nodes of the instance
951 83180411 Bernardo Dal Seno
  @param othernodes: list/tuple of nodes where to temporarily recreate disks
952 83180411 Bernardo Dal Seno

953 83180411 Bernardo Dal Seno
  """
954 e85be22a Bernardo Dal Seno
  options = qa_config.get("options", {})
955 e85be22a Bernardo Dal Seno
  use_ialloc = options.get("use-iallocators", True)
956 aecba21e Michael Hanselmann
  other_seq = ":".join([n.primary for n in othernodes])
957 aecba21e Michael Hanselmann
  orig_seq = ":".join([n.primary for n in inodes])
958 a085d96d Bernardo Dal Seno
  # These fail because the instance is running
959 83180411 Bernardo Dal Seno
  _AssertRecreateDisks(["-n", other_seq], instance, fail=True, destroy=False)
960 e85be22a Bernardo Dal Seno
  if use_ialloc:
961 e85be22a Bernardo Dal Seno
    _AssertRecreateDisks(["-I", "hail"], instance, fail=True, destroy=False)
962 e85be22a Bernardo Dal Seno
  else:
963 e85be22a Bernardo Dal Seno
    _AssertRecreateDisks(["-n", other_seq], instance, fail=True, destroy=False)
964 b5f33afa Michael Hanselmann
  AssertCommand(["gnt-instance", "stop", instance.name])
965 83180411 Bernardo Dal Seno
  # Disks exist: this should fail
966 83180411 Bernardo Dal Seno
  _AssertRecreateDisks([], instance, fail=True, destroy=False)
967 83180411 Bernardo Dal Seno
  # Recreate disks in place
968 83180411 Bernardo Dal Seno
  _AssertRecreateDisks([], instance)
969 83180411 Bernardo Dal Seno
  # Move disks away
970 e85be22a Bernardo Dal Seno
  if use_ialloc:
971 e85be22a Bernardo Dal Seno
    _AssertRecreateDisks(["-I", "hail"], instance)
972 e85be22a Bernardo Dal Seno
    # Move disks somewhere else
973 e85be22a Bernardo Dal Seno
    _AssertRecreateDisks(["-I", constants.DEFAULT_IALLOCATOR_SHORTCUT],
974 e85be22a Bernardo Dal Seno
                         instance)
975 e85be22a Bernardo Dal Seno
  else:
976 e85be22a Bernardo Dal Seno
    _AssertRecreateDisks(["-n", other_seq], instance)
977 83180411 Bernardo Dal Seno
  # Move disks back
978 83180411 Bernardo Dal Seno
  _AssertRecreateDisks(["-n", orig_seq], instance, check=False)
979 83180411 Bernardo Dal Seno
  # This and InstanceCheck decoration check that the disks are working
980 b5f33afa Michael Hanselmann
  AssertCommand(["gnt-instance", "reinstall", "-f", instance.name])
981 b5f33afa Michael Hanselmann
  AssertCommand(["gnt-instance", "start", instance.name])
982 83180411 Bernardo Dal Seno
983 83180411 Bernardo Dal Seno
984 5fa0375e Michael Hanselmann
@InstanceCheck(INST_UP, INST_UP, FIRST_ARG)
985 5d640672 Michael Hanselmann
def TestInstanceExport(instance, node):
986 bc696589 Michael Hanselmann
  """gnt-backup export -n ..."""
987 b5f33afa Michael Hanselmann
  name = instance.name
988 aecba21e Michael Hanselmann
  AssertCommand(["gnt-backup", "export", "-n", node.primary, name])
989 2f4b4f78 Iustin Pop
  return qa_utils.ResolveInstanceName(name)
990 5d640672 Michael Hanselmann
991 5d640672 Michael Hanselmann
992 51131cad Michael Hanselmann
@InstanceCheck(None, INST_DOWN, FIRST_ARG)
993 8d8d650c Michael Hanselmann
def TestInstanceExportWithRemove(instance, node):
994 8d8d650c Michael Hanselmann
  """gnt-backup export --remove-instance"""
995 aecba21e Michael Hanselmann
  AssertCommand(["gnt-backup", "export", "-n", node.primary,
996 b5f33afa Michael Hanselmann
                 "--remove-instance", instance.name])
997 8d8d650c Michael Hanselmann
998 8d8d650c Michael Hanselmann
999 5fa0375e Michael Hanselmann
@InstanceCheck(INST_UP, INST_UP, FIRST_ARG)
1000 bc696589 Michael Hanselmann
def TestInstanceExportNoTarget(instance):
1001 bc696589 Michael Hanselmann
  """gnt-backup export (without target node, should fail)"""
1002 b5f33afa Michael Hanselmann
  AssertCommand(["gnt-backup", "export", instance.name], fail=True)
1003 bc696589 Michael Hanselmann
1004 bc696589 Michael Hanselmann
1005 51131cad Michael Hanselmann
@InstanceCheck(None, INST_DOWN, FIRST_ARG)
1006 5fa0375e Michael Hanselmann
def TestInstanceImport(newinst, node, expnode, name):
1007 5d640672 Michael Hanselmann
  """gnt-backup import"""
1008 906a0346 Bernardo Dal Seno
  templ = constants.DT_PLAIN
1009 d0c8c01d Iustin Pop
  cmd = (["gnt-backup", "import",
1010 906a0346 Bernardo Dal Seno
          "--disk-template=%s" % templ,
1011 d0c8c01d Iustin Pop
          "--no-ip-check",
1012 aecba21e Michael Hanselmann
          "--src-node=%s" % expnode.primary,
1013 304d9f02 Michael Hanselmann
          "--src-dir=%s/%s" % (pathutils.EXPORT_DIR, name),
1014 aecba21e Michael Hanselmann
          "--node=%s" % node.primary] +
1015 59c75517 Michael Hanselmann
         _GetGenericAddParameters(newinst, templ,
1016 59c75517 Michael Hanselmann
                                  force_mac=constants.VALUE_GENERATE))
1017 b5f33afa Michael Hanselmann
  cmd.append(newinst.name)
1018 2f4b4f78 Iustin Pop
  AssertCommand(cmd)
1019 02a5fe0e Michael Hanselmann
  newinst.SetDiskTemplate(templ)
1020 283f9d4c Michael Hanselmann
1021 283f9d4c Michael Hanselmann
1022 283f9d4c Michael Hanselmann
def TestBackupList(expnode):
1023 283f9d4c Michael Hanselmann
  """gnt-backup list"""
1024 aecba21e Michael Hanselmann
  AssertCommand(["gnt-backup", "list", "--node=%s" % expnode.primary])
1025 e8ae0c20 Michael Hanselmann
1026 0fdf247d Michael Hanselmann
  qa_utils.GenericQueryTest("gnt-backup", query.EXPORT_FIELDS.keys(),
1027 0fdf247d Michael Hanselmann
                            namefield=None, test_unknown=False)
1028 0fdf247d Michael Hanselmann
1029 0fdf247d Michael Hanselmann
1030 0fdf247d Michael Hanselmann
def TestBackupListFields():
1031 0fdf247d Michael Hanselmann
  """gnt-backup list-fields"""
1032 0fdf247d Michael Hanselmann
  qa_utils.GenericQueryFieldsTest("gnt-backup", query.EXPORT_FIELDS.keys())
1033 f006f110 Bernardo Dal Seno
1034 f006f110 Bernardo Dal Seno
1035 f006f110 Bernardo Dal Seno
def TestRemoveInstanceOfflineNode(instance, snode, set_offline, set_online):
1036 318bbaa9 Guido Trotter
  """gnt-instance remove with an off-line node
1037 f006f110 Bernardo Dal Seno

1038 f006f110 Bernardo Dal Seno
  @param instance: instance
1039 f006f110 Bernardo Dal Seno
  @param snode: secondary node, to be set offline
1040 f006f110 Bernardo Dal Seno
  @param set_offline: function to call to set the node off-line
1041 f006f110 Bernardo Dal Seno
  @param set_online: function to call to set the node on-line
1042 f006f110 Bernardo Dal Seno

1043 f006f110 Bernardo Dal Seno
  """
1044 b5f33afa Michael Hanselmann
  info = _GetInstanceInfo(instance.name)
1045 f006f110 Bernardo Dal Seno
  set_offline(snode)
1046 f006f110 Bernardo Dal Seno
  try:
1047 f006f110 Bernardo Dal Seno
    TestInstanceRemove(instance)
1048 f006f110 Bernardo Dal Seno
  finally:
1049 f006f110 Bernardo Dal Seno
    set_online(snode)
1050 318bbaa9 Guido Trotter
1051 318bbaa9 Guido Trotter
  # Clean up the disks on the offline node, if necessary
1052 318bbaa9 Guido Trotter
  if instance.disk_template not in constants.DTS_EXT_MIRROR:
1053 318bbaa9 Guido Trotter
    # FIXME: abstract the cleanup inside the disks
1054 318bbaa9 Guido Trotter
    if info["storage-type"] == constants.ST_LVM_VG:
1055 318bbaa9 Guido Trotter
      for minor in info["drbd-minors"][snode.primary]:
1056 318bbaa9 Guido Trotter
        AssertCommand(["drbdsetup", str(minor), "down"], node=snode)
1057 318bbaa9 Guido Trotter
      AssertCommand(["lvremove", "-f"] + info["volumes"], node=snode)
1058 318bbaa9 Guido Trotter
    elif info["storage-type"] == constants.ST_FILE:
1059 318bbaa9 Guido Trotter
      filestorage = pathutils.DEFAULT_FILE_STORAGE_DIR
1060 318bbaa9 Guido Trotter
      disk = os.path.join(filestorage, instance.name)
1061 318bbaa9 Guido Trotter
      AssertCommand(["rm", "-rf", disk], node=snode)
1062 6f665bf7 Helga Velroyen
1063 6f665bf7 Helga Velroyen
1064 6f665bf7 Helga Velroyen
def TestInstanceCreationRestrictedByDiskTemplates():
1065 2ef21e6e Bernardo Dal Seno
  """Test adding instances for disbled disk templates."""
1066 6f665bf7 Helga Velroyen
  enabled_disk_templates = qa_config.GetEnabledDiskTemplates()
1067 6f665bf7 Helga Velroyen
  nodes = qa_config.AcquireManyNodes(2)
1068 6f665bf7 Helga Velroyen
1069 6f665bf7 Helga Velroyen
  # Setup the cluster with the enabled_disk_templates
1070 6f665bf7 Helga Velroyen
  AssertCommand(
1071 6f665bf7 Helga Velroyen
    ["gnt-cluster", "modify",
1072 6f665bf7 Helga Velroyen
     "--enabled-disk-template=%s" %
1073 6f665bf7 Helga Velroyen
       ",".join(enabled_disk_templates)],
1074 6f665bf7 Helga Velroyen
    fail=False)
1075 6f665bf7 Helga Velroyen
1076 6f665bf7 Helga Velroyen
  # Test instance creation for enabled disk templates
1077 6f665bf7 Helga Velroyen
  for disk_template in enabled_disk_templates:
1078 6f665bf7 Helga Velroyen
    instance = CreateInstanceByDiskTemplate(nodes, disk_template, False)
1079 6f665bf7 Helga Velroyen
    TestInstanceRemove(instance)
1080 6f665bf7 Helga Velroyen
1081 6f665bf7 Helga Velroyen
  # Test that instance creation fails for disabled disk templates
1082 6f665bf7 Helga Velroyen
  disabled_disk_templates = list(constants.DISK_TEMPLATES
1083 6f665bf7 Helga Velroyen
                                 - set(enabled_disk_templates))
1084 6f665bf7 Helga Velroyen
  for disk_template in disabled_disk_templates:
1085 6f665bf7 Helga Velroyen
    instance = CreateInstanceByDiskTemplate(nodes, disk_template, True)
1086 6f665bf7 Helga Velroyen
1087 6f665bf7 Helga Velroyen
  # Test instance creation for after disabling enabled disk templates
1088 6f665bf7 Helga Velroyen
  if (len(enabled_disk_templates) > 1):
1089 6f665bf7 Helga Velroyen
    # Partition the disk templates, enable them separately and check if the
1090 6f665bf7 Helga Velroyen
    # disabled ones cannot be used by instances.
1091 6f665bf7 Helga Velroyen
    middle = len(enabled_disk_templates) / 2
1092 6f665bf7 Helga Velroyen
    templates1 = enabled_disk_templates[:middle]
1093 6f665bf7 Helga Velroyen
    templates2 = enabled_disk_templates[middle:]
1094 6f665bf7 Helga Velroyen
1095 6f665bf7 Helga Velroyen
    for (enabled, disabled) in [(templates1, templates2),
1096 6f665bf7 Helga Velroyen
                                (templates2, templates1)]:
1097 6f665bf7 Helga Velroyen
      AssertCommand(["gnt-cluster", "modify",
1098 6f665bf7 Helga Velroyen
                     "--enabled-disk-template=%s" %
1099 6f665bf7 Helga Velroyen
                       ",".join(enabled)],
1100 6f665bf7 Helga Velroyen
                    fail=False)
1101 6f665bf7 Helga Velroyen
      for disk_template in disabled:
1102 6f665bf7 Helga Velroyen
        CreateInstanceByDiskTemplate(nodes, disk_template, True)
1103 6f665bf7 Helga Velroyen
  elif (len(enabled_disk_templates) == 1):
1104 6f665bf7 Helga Velroyen
    # If only one disk template is enabled in the QA config, we have to enable
1105 6f665bf7 Helga Velroyen
    # some of the disabled disk templates in order to test if the disabling the
1106 6f665bf7 Helga Velroyen
    # only enabled disk template prohibits creating instances of that template.
1107 6f665bf7 Helga Velroyen
    AssertCommand(["gnt-cluster", "modify",
1108 6f665bf7 Helga Velroyen
                   "--enabled-disk-template=%s" %
1109 6f665bf7 Helga Velroyen
                     ",".join(disabled_disk_templates)],
1110 6f665bf7 Helga Velroyen
                  fail=False)
1111 6f665bf7 Helga Velroyen
    CreateInstanceByDiskTemplate(nodes, enabled_disk_templates[0], True)
1112 6f665bf7 Helga Velroyen
  else:
1113 6f665bf7 Helga Velroyen
    raise qa_error.Error("Please enable at least one disk template"
1114 6f665bf7 Helga Velroyen
                         " in your QA setup.")
1115 6f665bf7 Helga Velroyen
1116 6f665bf7 Helga Velroyen
  # Restore initially enabled disk templates
1117 6f665bf7 Helga Velroyen
  AssertCommand(["gnt-cluster", "modify",
1118 6f665bf7 Helga Velroyen
                 "--enabled-disk-template=%s" %
1119 6f665bf7 Helga Velroyen
                   ",".join(enabled_disk_templates)],
1120 6f665bf7 Helga Velroyen
                 fail=False)