Statistics
| Branch: | Tag: | Revision:

root / qa / qa_instance.py @ 2ef21e6e

History | View | Annotate | Download (36.8 kB)

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

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

75 f41dc024 Helga Velroyen
  @type nodes_spec: string
76 f41dc024 Helga Velroyen
  @param nodes_spec: string specification of one node (by node name) or several
77 f41dc024 Helga Velroyen
                     nodes according to the requirements of the disk template
78 f41dc024 Helga Velroyen
  @type disk_template: string
79 f41dc024 Helga Velroyen
  @param disk_template: the disk template to be used by the instance
80 f41dc024 Helga Velroyen
  @return: the created instance
81 f41dc024 Helga Velroyen

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

114 f41dc024 Helga Velroyen
  @type nodes: list of nodes
115 f41dc024 Helga Velroyen
  @param nodes: a list of nodes, whose first element is used to create the
116 f41dc024 Helga Velroyen
                instance
117 f41dc024 Helga Velroyen
  @type disk_template: string
118 f41dc024 Helga Velroyen
  @param disk_template: the disk template to be used by the instance
119 f41dc024 Helga Velroyen
  @return: the created instance
120 f41dc024 Helga Velroyen

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

130 f41dc024 Helga Velroyen
  @type nodes: list of nodes
131 f41dc024 Helga Velroyen
  @param nodes: nodes to be used by the instance
132 f41dc024 Helga Velroyen
  @return: the created instance
133 f41dc024 Helga Velroyen

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

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

152 f41dc024 Helga Velroyen
  @type nodes: list of nodes
153 f41dc024 Helga Velroyen
  @param nodes: the list of the nodes on which the instance will be placed;
154 f41dc024 Helga Velroyen
                it needs to have sufficiently many elements for the given
155 f41dc024 Helga Velroyen
                disk template
156 f41dc024 Helga Velroyen
  @type disk_template: string
157 f41dc024 Helga Velroyen
  @param disk_template: the disk template to be used by the instance
158 f41dc024 Helga Velroyen
  @return: the created instance
159 f41dc024 Helga Velroyen

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

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

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

249 cc4b14f0 Bernardo Dal Seno
  This is used to simulate HW errors (dead nodes, broken disks...); the
250 cc4b14f0 Bernardo Dal Seno
  configuration of the instance is not affected.
251 cc4b14f0 Bernardo Dal Seno
  @type instance: dictionary
252 cc4b14f0 Bernardo Dal Seno
  @param instance: the instance
253 cc4b14f0 Bernardo Dal Seno

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

275 d55408b0 Bernardo Dal Seno
  @type instance: string
276 d55408b0 Bernardo Dal Seno
  @param instance: Instance name
277 d55408b0 Bernardo Dal Seno
  @type field: string
278 d55408b0 Bernardo Dal Seno
  @param field: Name of the field
279 ab4832d1 Bernardo Dal Seno
  @rtype: string
280 d55408b0 Bernardo Dal Seno

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

291 ab4832d1 Bernardo Dal Seno
  @type instance: string
292 ab4832d1 Bernardo Dal Seno
  @param instance: Instance name
293 ab4832d1 Bernardo Dal Seno
  @type field: string
294 ab4832d1 Bernardo Dal Seno
  @param field: Name of the field
295 ab4832d1 Bernardo Dal Seno
  @rtype: bool
296 ab4832d1 Bernardo Dal Seno

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

311 ab4832d1 Bernardo Dal Seno
  @type instance: string
312 ab4832d1 Bernardo Dal Seno
  @param instance: Instance name
313 ab4832d1 Bernardo Dal Seno
  @type field: string
314 ab4832d1 Bernardo Dal Seno
  @param field: Name of the field
315 ab4832d1 Bernardo Dal Seno
  @rtype: int or float
316 ab4832d1 Bernardo Dal Seno

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

333 ab4832d1 Bernardo Dal Seno
  @type instance: string
334 ab4832d1 Bernardo Dal Seno
  @param instance: Instance name
335 ab4832d1 Bernardo Dal Seno
  @type spec: string
336 ab4832d1 Bernardo Dal Seno
  @param spec: one of the supported parameters: "mem-size", "cpu-count",
337 ab4832d1 Bernardo Dal Seno
      "disk-count", "disk-size", "nic-count"
338 ab4832d1 Bernardo Dal Seno
  @rtype: tuple
339 ab4832d1 Bernardo Dal Seno
  @return: (minspec, maxspec); minspec and maxspec can be different only for
340 ab4832d1 Bernardo Dal Seno
      memory and disk size
341 ab4832d1 Bernardo Dal Seno

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

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

478 6a343475 Michael Hanselmann
  @type instance: string
479 6a343475 Michael Hanselmann
  @param instance: Instance name
480 6a343475 Michael Hanselmann

481 6a343475 Michael Hanselmann
  """
482 6a343475 Michael Hanselmann
  AssertIn(qa_utils.ResolveInstanceName(instance),
483 6a343475 Michael Hanselmann
           _ReadSsconfInstanceList())
484 6a343475 Michael Hanselmann
485 6a343475 Michael Hanselmann
486 51131cad Michael Hanselmann
@InstanceCheck(INST_DOWN, INST_DOWN, FIRST_ARG)
487 4c1a464b Iustin Pop
def TestInstanceRenameAndBack(rename_source, rename_target):
488 4c1a464b Iustin Pop
  """gnt-instance rename
489 4c1a464b Iustin Pop

490 4c1a464b Iustin Pop
  This must leave the instance with the original name, not the target
491 4c1a464b Iustin Pop
  name.
492 4c1a464b Iustin Pop

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

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

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

871 83180411 Bernardo Dal Seno
  @param cmdargs: Arguments (instance name excluded)
872 83180411 Bernardo Dal Seno
  @param instance: Instance to operate on
873 83180411 Bernardo Dal Seno
  @param fail: True if the command is expected to fail
874 83180411 Bernardo Dal Seno
  @param check: If True and fail is False, check that the disks work
875 83180411 Bernardo Dal Seno
  @prama destroy: If True, destroy the old disks first
876 83180411 Bernardo Dal Seno

877 83180411 Bernardo Dal Seno
  """
878 83180411 Bernardo Dal Seno
  if destroy:
879 cc2a70b1 Guido Trotter
    _DestroyInstanceDisks(instance)
880 83180411 Bernardo Dal Seno
  AssertCommand((["gnt-instance", "recreate-disks"] + cmdargs +
881 b5f33afa Michael Hanselmann
                 [instance.name]), fail)
882 83180411 Bernardo Dal Seno
  if not fail and check:
883 83180411 Bernardo Dal Seno
    # Quick check that the disks are there
884 b5f33afa Michael Hanselmann
    AssertCommand(["gnt-instance", "activate-disks", instance.name])
885 32da72f3 Iustin Pop
    AssertCommand(["gnt-instance", "activate-disks", "--wait-for-sync",
886 b5f33afa Michael Hanselmann
                   instance.name])
887 b5f33afa Michael Hanselmann
    AssertCommand(["gnt-instance", "deactivate-disks", instance.name])
888 83180411 Bernardo Dal Seno
889 a1cd2ecf Bernardo Dal Seno
890 83180411 Bernardo Dal Seno
@InstanceCheck(INST_UP, INST_UP, FIRST_ARG)
891 c99200a3 Bernardo Dal Seno
def TestRecreateDisks(instance, inodes, othernodes):
892 83180411 Bernardo Dal Seno
  """gnt-instance recreate-disks
893 83180411 Bernardo Dal Seno

894 83180411 Bernardo Dal Seno
  @param instance: Instance to work on
895 c99200a3 Bernardo Dal Seno
  @param inodes: List of the current nodes of the instance
896 83180411 Bernardo Dal Seno
  @param othernodes: list/tuple of nodes where to temporarily recreate disks
897 83180411 Bernardo Dal Seno

898 83180411 Bernardo Dal Seno
  """
899 e85be22a Bernardo Dal Seno
  options = qa_config.get("options", {})
900 e85be22a Bernardo Dal Seno
  use_ialloc = options.get("use-iallocators", True)
901 aecba21e Michael Hanselmann
  other_seq = ":".join([n.primary for n in othernodes])
902 aecba21e Michael Hanselmann
  orig_seq = ":".join([n.primary for n in inodes])
903 a085d96d Bernardo Dal Seno
  # These fail because the instance is running
904 83180411 Bernardo Dal Seno
  _AssertRecreateDisks(["-n", other_seq], instance, fail=True, destroy=False)
905 e85be22a Bernardo Dal Seno
  if use_ialloc:
906 e85be22a Bernardo Dal Seno
    _AssertRecreateDisks(["-I", "hail"], instance, fail=True, destroy=False)
907 e85be22a Bernardo Dal Seno
  else:
908 e85be22a Bernardo Dal Seno
    _AssertRecreateDisks(["-n", other_seq], instance, fail=True, destroy=False)
909 b5f33afa Michael Hanselmann
  AssertCommand(["gnt-instance", "stop", instance.name])
910 83180411 Bernardo Dal Seno
  # Disks exist: this should fail
911 83180411 Bernardo Dal Seno
  _AssertRecreateDisks([], instance, fail=True, destroy=False)
912 83180411 Bernardo Dal Seno
  # Recreate disks in place
913 83180411 Bernardo Dal Seno
  _AssertRecreateDisks([], instance)
914 83180411 Bernardo Dal Seno
  # Move disks away
915 e85be22a Bernardo Dal Seno
  if use_ialloc:
916 e85be22a Bernardo Dal Seno
    _AssertRecreateDisks(["-I", "hail"], instance)
917 e85be22a Bernardo Dal Seno
    # Move disks somewhere else
918 e85be22a Bernardo Dal Seno
    _AssertRecreateDisks(["-I", constants.DEFAULT_IALLOCATOR_SHORTCUT],
919 e85be22a Bernardo Dal Seno
                         instance)
920 e85be22a Bernardo Dal Seno
  else:
921 e85be22a Bernardo Dal Seno
    _AssertRecreateDisks(["-n", other_seq], instance)
922 83180411 Bernardo Dal Seno
  # Move disks back
923 83180411 Bernardo Dal Seno
  _AssertRecreateDisks(["-n", orig_seq], instance, check=False)
924 83180411 Bernardo Dal Seno
  # This and InstanceCheck decoration check that the disks are working
925 b5f33afa Michael Hanselmann
  AssertCommand(["gnt-instance", "reinstall", "-f", instance.name])
926 b5f33afa Michael Hanselmann
  AssertCommand(["gnt-instance", "start", instance.name])
927 83180411 Bernardo Dal Seno
928 83180411 Bernardo Dal Seno
929 5fa0375e Michael Hanselmann
@InstanceCheck(INST_UP, INST_UP, FIRST_ARG)
930 5d640672 Michael Hanselmann
def TestInstanceExport(instance, node):
931 bc696589 Michael Hanselmann
  """gnt-backup export -n ..."""
932 b5f33afa Michael Hanselmann
  name = instance.name
933 aecba21e Michael Hanselmann
  AssertCommand(["gnt-backup", "export", "-n", node.primary, name])
934 2f4b4f78 Iustin Pop
  return qa_utils.ResolveInstanceName(name)
935 5d640672 Michael Hanselmann
936 5d640672 Michael Hanselmann
937 51131cad Michael Hanselmann
@InstanceCheck(None, INST_DOWN, FIRST_ARG)
938 8d8d650c Michael Hanselmann
def TestInstanceExportWithRemove(instance, node):
939 8d8d650c Michael Hanselmann
  """gnt-backup export --remove-instance"""
940 aecba21e Michael Hanselmann
  AssertCommand(["gnt-backup", "export", "-n", node.primary,
941 b5f33afa Michael Hanselmann
                 "--remove-instance", instance.name])
942 8d8d650c Michael Hanselmann
943 8d8d650c Michael Hanselmann
944 5fa0375e Michael Hanselmann
@InstanceCheck(INST_UP, INST_UP, FIRST_ARG)
945 bc696589 Michael Hanselmann
def TestInstanceExportNoTarget(instance):
946 bc696589 Michael Hanselmann
  """gnt-backup export (without target node, should fail)"""
947 b5f33afa Michael Hanselmann
  AssertCommand(["gnt-backup", "export", instance.name], fail=True)
948 bc696589 Michael Hanselmann
949 bc696589 Michael Hanselmann
950 51131cad Michael Hanselmann
@InstanceCheck(None, INST_DOWN, FIRST_ARG)
951 5fa0375e Michael Hanselmann
def TestInstanceImport(newinst, node, expnode, name):
952 5d640672 Michael Hanselmann
  """gnt-backup import"""
953 906a0346 Bernardo Dal Seno
  templ = constants.DT_PLAIN
954 d0c8c01d Iustin Pop
  cmd = (["gnt-backup", "import",
955 906a0346 Bernardo Dal Seno
          "--disk-template=%s" % templ,
956 d0c8c01d Iustin Pop
          "--no-ip-check",
957 aecba21e Michael Hanselmann
          "--src-node=%s" % expnode.primary,
958 304d9f02 Michael Hanselmann
          "--src-dir=%s/%s" % (pathutils.EXPORT_DIR, name),
959 aecba21e Michael Hanselmann
          "--node=%s" % node.primary] +
960 59c75517 Michael Hanselmann
         _GetGenericAddParameters(newinst, templ,
961 59c75517 Michael Hanselmann
                                  force_mac=constants.VALUE_GENERATE))
962 b5f33afa Michael Hanselmann
  cmd.append(newinst.name)
963 2f4b4f78 Iustin Pop
  AssertCommand(cmd)
964 02a5fe0e Michael Hanselmann
  newinst.SetDiskTemplate(templ)
965 283f9d4c Michael Hanselmann
966 283f9d4c Michael Hanselmann
967 283f9d4c Michael Hanselmann
def TestBackupList(expnode):
968 283f9d4c Michael Hanselmann
  """gnt-backup list"""
969 aecba21e Michael Hanselmann
  AssertCommand(["gnt-backup", "list", "--node=%s" % expnode.primary])
970 e8ae0c20 Michael Hanselmann
971 0fdf247d Michael Hanselmann
  qa_utils.GenericQueryTest("gnt-backup", query.EXPORT_FIELDS.keys(),
972 0fdf247d Michael Hanselmann
                            namefield=None, test_unknown=False)
973 0fdf247d Michael Hanselmann
974 0fdf247d Michael Hanselmann
975 0fdf247d Michael Hanselmann
def TestBackupListFields():
976 0fdf247d Michael Hanselmann
  """gnt-backup list-fields"""
977 0fdf247d Michael Hanselmann
  qa_utils.GenericQueryFieldsTest("gnt-backup", query.EXPORT_FIELDS.keys())
978 f006f110 Bernardo Dal Seno
979 f006f110 Bernardo Dal Seno
980 f006f110 Bernardo Dal Seno
def TestRemoveInstanceOfflineNode(instance, snode, set_offline, set_online):
981 318bbaa9 Guido Trotter
  """gnt-instance remove with an off-line node
982 f006f110 Bernardo Dal Seno

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

988 f006f110 Bernardo Dal Seno
  """
989 b5f33afa Michael Hanselmann
  info = _GetInstanceInfo(instance.name)
990 f006f110 Bernardo Dal Seno
  set_offline(snode)
991 f006f110 Bernardo Dal Seno
  try:
992 f006f110 Bernardo Dal Seno
    TestInstanceRemove(instance)
993 f006f110 Bernardo Dal Seno
  finally:
994 f006f110 Bernardo Dal Seno
    set_online(snode)
995 318bbaa9 Guido Trotter
996 318bbaa9 Guido Trotter
  # Clean up the disks on the offline node, if necessary
997 318bbaa9 Guido Trotter
  if instance.disk_template not in constants.DTS_EXT_MIRROR:
998 318bbaa9 Guido Trotter
    # FIXME: abstract the cleanup inside the disks
999 318bbaa9 Guido Trotter
    if info["storage-type"] == constants.ST_LVM_VG:
1000 318bbaa9 Guido Trotter
      for minor in info["drbd-minors"][snode.primary]:
1001 318bbaa9 Guido Trotter
        AssertCommand(["drbdsetup", str(minor), "down"], node=snode)
1002 318bbaa9 Guido Trotter
      AssertCommand(["lvremove", "-f"] + info["volumes"], node=snode)
1003 318bbaa9 Guido Trotter
    elif info["storage-type"] == constants.ST_FILE:
1004 318bbaa9 Guido Trotter
      filestorage = pathutils.DEFAULT_FILE_STORAGE_DIR
1005 318bbaa9 Guido Trotter
      disk = os.path.join(filestorage, instance.name)
1006 318bbaa9 Guido Trotter
      AssertCommand(["rm", "-rf", disk], node=snode)
1007 6f665bf7 Helga Velroyen
1008 6f665bf7 Helga Velroyen
1009 6f665bf7 Helga Velroyen
def TestInstanceCreationRestrictedByDiskTemplates():
1010 2ef21e6e Bernardo Dal Seno
  """Test adding instances for disbled disk templates."""
1011 6f665bf7 Helga Velroyen
  enabled_disk_templates = qa_config.GetEnabledDiskTemplates()
1012 6f665bf7 Helga Velroyen
  nodes = qa_config.AcquireManyNodes(2)
1013 6f665bf7 Helga Velroyen
1014 6f665bf7 Helga Velroyen
  # Setup the cluster with the enabled_disk_templates
1015 6f665bf7 Helga Velroyen
  AssertCommand(
1016 6f665bf7 Helga Velroyen
    ["gnt-cluster", "modify",
1017 6f665bf7 Helga Velroyen
     "--enabled-disk-template=%s" %
1018 6f665bf7 Helga Velroyen
       ",".join(enabled_disk_templates)],
1019 6f665bf7 Helga Velroyen
    fail=False)
1020 6f665bf7 Helga Velroyen
1021 6f665bf7 Helga Velroyen
  # Test instance creation for enabled disk templates
1022 6f665bf7 Helga Velroyen
  for disk_template in enabled_disk_templates:
1023 6f665bf7 Helga Velroyen
    instance = CreateInstanceByDiskTemplate(nodes, disk_template, False)
1024 6f665bf7 Helga Velroyen
    TestInstanceRemove(instance)
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 6f665bf7 Helga Velroyen
    instance = CreateInstanceByDiskTemplate(nodes, disk_template, 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 6f665bf7 Helga Velroyen
        CreateInstanceByDiskTemplate(nodes, disk_template, 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 6f665bf7 Helga Velroyen
    CreateInstanceByDiskTemplate(nodes, enabled_disk_templates[0], 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)