Statistics
| Branch: | Tag: | Revision:

root / qa / qa_instance.py @ 090128b6

History | View | Annotate | Download (38.8 kB)

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

24 cec9845c Michael Hanselmann
"""
25 cec9845c Michael Hanselmann
26 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 090128b6 Christos Stavrakakis
      params.extend(["--disk", "%s:size=%s,name=%s" % (idx, size, name)])
59 f346a7d9 Michael Hanselmann
60 f346a7d9 Michael Hanselmann
  # Set static MAC address if configured
61 1c573fb4 Iustin Pop
  if force_mac:
62 1c573fb4 Iustin Pop
    nic0_mac = force_mac
63 1c573fb4 Iustin Pop
  else:
64 0afce24e Michael Hanselmann
    nic0_mac = inst.GetNicMacAddr(0, None)
65 0afce24e Michael Hanselmann
66 f346a7d9 Michael Hanselmann
  if nic0_mac:
67 f346a7d9 Michael Hanselmann
    params.extend(["--net", "0:mac=%s" % nic0_mac])
68 f346a7d9 Michael Hanselmann
69 1d693311 Michael Hanselmann
  return params
70 5d640672 Michael Hanselmann
71 5d640672 Michael Hanselmann
72 f41dc024 Helga Velroyen
def _CreateInstanceByDiskTemplateRaw(nodes_spec, disk_template, fail=False):
73 f41dc024 Helga Velroyen
  """Creates an instance with the given disk template on the given nodes(s).
74 f41dc024 Helga Velroyen
     Note that this function does not check if enough nodes are given for
75 f41dc024 Helga Velroyen
     the respective disk template.
76 f41dc024 Helga Velroyen

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

480 6a343475 Michael Hanselmann
  @type instance: string
481 6a343475 Michael Hanselmann
  @param instance: Instance name
482 6a343475 Michael Hanselmann

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

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

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

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

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

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

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

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

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

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

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