Statistics
| Branch: | Tag: | Revision:

root / qa / qa_instance.py @ dcedd81a

History | View | Annotate | Download (40.1 kB)

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

487 6a343475 Michael Hanselmann
  @type instance: string
488 6a343475 Michael Hanselmann
  @param instance: Instance name
489 6a343475 Michael Hanselmann

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

499 4c1a464b Iustin Pop
  This must leave the instance with the original name, not the target
500 4c1a464b Iustin Pop
  name.
501 4c1a464b Iustin Pop

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

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

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

953 83180411 Bernardo Dal Seno
  @param cmdargs: Arguments (instance name excluded)
954 83180411 Bernardo Dal Seno
  @param instance: Instance to operate on
955 83180411 Bernardo Dal Seno
  @param fail: True if the command is expected to fail
956 83180411 Bernardo Dal Seno
  @param check: If True and fail is False, check that the disks work
957 83180411 Bernardo Dal Seno
  @prama destroy: If True, destroy the old disks first
958 83180411 Bernardo Dal Seno

959 83180411 Bernardo Dal Seno
  """
960 83180411 Bernardo Dal Seno
  if destroy:
961 cc2a70b1 Guido Trotter
    _DestroyInstanceDisks(instance)
962 83180411 Bernardo Dal Seno
  AssertCommand((["gnt-instance", "recreate-disks"] + cmdargs +
963 b5f33afa Michael Hanselmann
                 [instance.name]), fail)
964 83180411 Bernardo Dal Seno
  if not fail and check:
965 83180411 Bernardo Dal Seno
    # Quick check that the disks are there
966 b5f33afa Michael Hanselmann
    AssertCommand(["gnt-instance", "activate-disks", instance.name])
967 32da72f3 Iustin Pop
    AssertCommand(["gnt-instance", "activate-disks", "--wait-for-sync",
968 b5f33afa Michael Hanselmann
                   instance.name])
969 b5f33afa Michael Hanselmann
    AssertCommand(["gnt-instance", "deactivate-disks", instance.name])
970 83180411 Bernardo Dal Seno
971 a1cd2ecf Bernardo Dal Seno
972 83180411 Bernardo Dal Seno
@InstanceCheck(INST_UP, INST_UP, FIRST_ARG)
973 c99200a3 Bernardo Dal Seno
def TestRecreateDisks(instance, inodes, othernodes):
974 83180411 Bernardo Dal Seno
  """gnt-instance recreate-disks
975 83180411 Bernardo Dal Seno

976 83180411 Bernardo Dal Seno
  @param instance: Instance to work on
977 c99200a3 Bernardo Dal Seno
  @param inodes: List of the current nodes of the instance
978 83180411 Bernardo Dal Seno
  @param othernodes: list/tuple of nodes where to temporarily recreate disks
979 83180411 Bernardo Dal Seno

980 83180411 Bernardo Dal Seno
  """
981 e85be22a Bernardo Dal Seno
  options = qa_config.get("options", {})
982 e85be22a Bernardo Dal Seno
  use_ialloc = options.get("use-iallocators", True)
983 aecba21e Michael Hanselmann
  other_seq = ":".join([n.primary for n in othernodes])
984 aecba21e Michael Hanselmann
  orig_seq = ":".join([n.primary for n in inodes])
985 a085d96d Bernardo Dal Seno
  # These fail because the instance is running
986 83180411 Bernardo Dal Seno
  _AssertRecreateDisks(["-n", other_seq], instance, fail=True, destroy=False)
987 e85be22a Bernardo Dal Seno
  if use_ialloc:
988 e85be22a Bernardo Dal Seno
    _AssertRecreateDisks(["-I", "hail"], instance, fail=True, destroy=False)
989 e85be22a Bernardo Dal Seno
  else:
990 e85be22a Bernardo Dal Seno
    _AssertRecreateDisks(["-n", other_seq], instance, fail=True, destroy=False)
991 b5f33afa Michael Hanselmann
  AssertCommand(["gnt-instance", "stop", instance.name])
992 83180411 Bernardo Dal Seno
  # Disks exist: this should fail
993 83180411 Bernardo Dal Seno
  _AssertRecreateDisks([], instance, fail=True, destroy=False)
994 83180411 Bernardo Dal Seno
  # Recreate disks in place
995 83180411 Bernardo Dal Seno
  _AssertRecreateDisks([], instance)
996 83180411 Bernardo Dal Seno
  # Move disks away
997 e85be22a Bernardo Dal Seno
  if use_ialloc:
998 e85be22a Bernardo Dal Seno
    _AssertRecreateDisks(["-I", "hail"], instance)
999 e85be22a Bernardo Dal Seno
    # Move disks somewhere else
1000 e85be22a Bernardo Dal Seno
    _AssertRecreateDisks(["-I", constants.DEFAULT_IALLOCATOR_SHORTCUT],
1001 e85be22a Bernardo Dal Seno
                         instance)
1002 e85be22a Bernardo Dal Seno
  else:
1003 e85be22a Bernardo Dal Seno
    _AssertRecreateDisks(["-n", other_seq], instance)
1004 83180411 Bernardo Dal Seno
  # Move disks back
1005 e2e98c6e Bernardo Dal Seno
  _AssertRecreateDisks(["-n", orig_seq], instance)
1006 e2e98c6e Bernardo Dal Seno
  # Recreate the disks one by one
1007 a365b47f Bernardo Dal Seno
  for idx in range(0, len(qa_config.GetDiskOptions())):
1008 e2e98c6e Bernardo Dal Seno
    # Only the first call should destroy all the disk
1009 e2e98c6e Bernardo Dal Seno
    destroy = (idx == 0)
1010 e2e98c6e Bernardo Dal Seno
    _AssertRecreateDisks(["--disk=%s" % idx], instance, destroy=destroy,
1011 e2e98c6e Bernardo Dal Seno
                         check=False)
1012 83180411 Bernardo Dal Seno
  # This and InstanceCheck decoration check that the disks are working
1013 b5f33afa Michael Hanselmann
  AssertCommand(["gnt-instance", "reinstall", "-f", instance.name])
1014 b5f33afa Michael Hanselmann
  AssertCommand(["gnt-instance", "start", instance.name])
1015 83180411 Bernardo Dal Seno
1016 83180411 Bernardo Dal Seno
1017 5fa0375e Michael Hanselmann
@InstanceCheck(INST_UP, INST_UP, FIRST_ARG)
1018 5d640672 Michael Hanselmann
def TestInstanceExport(instance, node):
1019 bc696589 Michael Hanselmann
  """gnt-backup export -n ..."""
1020 b5f33afa Michael Hanselmann
  name = instance.name
1021 aecba21e Michael Hanselmann
  AssertCommand(["gnt-backup", "export", "-n", node.primary, name])
1022 2f4b4f78 Iustin Pop
  return qa_utils.ResolveInstanceName(name)
1023 5d640672 Michael Hanselmann
1024 5d640672 Michael Hanselmann
1025 51131cad Michael Hanselmann
@InstanceCheck(None, INST_DOWN, FIRST_ARG)
1026 8d8d650c Michael Hanselmann
def TestInstanceExportWithRemove(instance, node):
1027 8d8d650c Michael Hanselmann
  """gnt-backup export --remove-instance"""
1028 aecba21e Michael Hanselmann
  AssertCommand(["gnt-backup", "export", "-n", node.primary,
1029 b5f33afa Michael Hanselmann
                 "--remove-instance", instance.name])
1030 8d8d650c Michael Hanselmann
1031 8d8d650c Michael Hanselmann
1032 5fa0375e Michael Hanselmann
@InstanceCheck(INST_UP, INST_UP, FIRST_ARG)
1033 bc696589 Michael Hanselmann
def TestInstanceExportNoTarget(instance):
1034 bc696589 Michael Hanselmann
  """gnt-backup export (without target node, should fail)"""
1035 b5f33afa Michael Hanselmann
  AssertCommand(["gnt-backup", "export", instance.name], fail=True)
1036 bc696589 Michael Hanselmann
1037 bc696589 Michael Hanselmann
1038 51131cad Michael Hanselmann
@InstanceCheck(None, INST_DOWN, FIRST_ARG)
1039 5fa0375e Michael Hanselmann
def TestInstanceImport(newinst, node, expnode, name):
1040 5d640672 Michael Hanselmann
  """gnt-backup import"""
1041 906a0346 Bernardo Dal Seno
  templ = constants.DT_PLAIN
1042 d0c8c01d Iustin Pop
  cmd = (["gnt-backup", "import",
1043 906a0346 Bernardo Dal Seno
          "--disk-template=%s" % templ,
1044 d0c8c01d Iustin Pop
          "--no-ip-check",
1045 aecba21e Michael Hanselmann
          "--src-node=%s" % expnode.primary,
1046 304d9f02 Michael Hanselmann
          "--src-dir=%s/%s" % (pathutils.EXPORT_DIR, name),
1047 aecba21e Michael Hanselmann
          "--node=%s" % node.primary] +
1048 59c75517 Michael Hanselmann
         _GetGenericAddParameters(newinst, templ,
1049 59c75517 Michael Hanselmann
                                  force_mac=constants.VALUE_GENERATE))
1050 b5f33afa Michael Hanselmann
  cmd.append(newinst.name)
1051 2f4b4f78 Iustin Pop
  AssertCommand(cmd)
1052 02a5fe0e Michael Hanselmann
  newinst.SetDiskTemplate(templ)
1053 283f9d4c Michael Hanselmann
1054 283f9d4c Michael Hanselmann
1055 283f9d4c Michael Hanselmann
def TestBackupList(expnode):
1056 283f9d4c Michael Hanselmann
  """gnt-backup list"""
1057 aecba21e Michael Hanselmann
  AssertCommand(["gnt-backup", "list", "--node=%s" % expnode.primary])
1058 e8ae0c20 Michael Hanselmann
1059 0fdf247d Michael Hanselmann
  qa_utils.GenericQueryTest("gnt-backup", query.EXPORT_FIELDS.keys(),
1060 0fdf247d Michael Hanselmann
                            namefield=None, test_unknown=False)
1061 0fdf247d Michael Hanselmann
1062 0fdf247d Michael Hanselmann
1063 0fdf247d Michael Hanselmann
def TestBackupListFields():
1064 0fdf247d Michael Hanselmann
  """gnt-backup list-fields"""
1065 0fdf247d Michael Hanselmann
  qa_utils.GenericQueryFieldsTest("gnt-backup", query.EXPORT_FIELDS.keys())
1066 f006f110 Bernardo Dal Seno
1067 f006f110 Bernardo Dal Seno
1068 f006f110 Bernardo Dal Seno
def TestRemoveInstanceOfflineNode(instance, snode, set_offline, set_online):
1069 318bbaa9 Guido Trotter
  """gnt-instance remove with an off-line node
1070 f006f110 Bernardo Dal Seno

1071 f006f110 Bernardo Dal Seno
  @param instance: instance
1072 f006f110 Bernardo Dal Seno
  @param snode: secondary node, to be set offline
1073 f006f110 Bernardo Dal Seno
  @param set_offline: function to call to set the node off-line
1074 f006f110 Bernardo Dal Seno
  @param set_online: function to call to set the node on-line
1075 f006f110 Bernardo Dal Seno

1076 f006f110 Bernardo Dal Seno
  """
1077 b5f33afa Michael Hanselmann
  info = _GetInstanceInfo(instance.name)
1078 f006f110 Bernardo Dal Seno
  set_offline(snode)
1079 f006f110 Bernardo Dal Seno
  try:
1080 f006f110 Bernardo Dal Seno
    TestInstanceRemove(instance)
1081 f006f110 Bernardo Dal Seno
  finally:
1082 f006f110 Bernardo Dal Seno
    set_online(snode)
1083 318bbaa9 Guido Trotter
1084 318bbaa9 Guido Trotter
  # Clean up the disks on the offline node, if necessary
1085 318bbaa9 Guido Trotter
  if instance.disk_template not in constants.DTS_EXT_MIRROR:
1086 318bbaa9 Guido Trotter
    # FIXME: abstract the cleanup inside the disks
1087 318bbaa9 Guido Trotter
    if info["storage-type"] == constants.ST_LVM_VG:
1088 318bbaa9 Guido Trotter
      for minor in info["drbd-minors"][snode.primary]:
1089 318bbaa9 Guido Trotter
        AssertCommand(["drbdsetup", str(minor), "down"], node=snode)
1090 318bbaa9 Guido Trotter
      AssertCommand(["lvremove", "-f"] + info["volumes"], node=snode)
1091 318bbaa9 Guido Trotter
    elif info["storage-type"] == constants.ST_FILE:
1092 318bbaa9 Guido Trotter
      filestorage = pathutils.DEFAULT_FILE_STORAGE_DIR
1093 318bbaa9 Guido Trotter
      disk = os.path.join(filestorage, instance.name)
1094 318bbaa9 Guido Trotter
      AssertCommand(["rm", "-rf", disk], node=snode)
1095 6f665bf7 Helga Velroyen
1096 6f665bf7 Helga Velroyen
1097 6f665bf7 Helga Velroyen
def TestInstanceCreationRestrictedByDiskTemplates():
1098 e75f80b9 Bernardo Dal Seno
  """Test adding instances for disabled disk templates."""
1099 6f665bf7 Helga Velroyen
  enabled_disk_templates = qa_config.GetEnabledDiskTemplates()
1100 6f665bf7 Helga Velroyen
  nodes = qa_config.AcquireManyNodes(2)
1101 6f665bf7 Helga Velroyen
1102 6f665bf7 Helga Velroyen
  # Setup the cluster with the enabled_disk_templates
1103 6f665bf7 Helga Velroyen
  AssertCommand(
1104 6f665bf7 Helga Velroyen
    ["gnt-cluster", "modify",
1105 6f665bf7 Helga Velroyen
     "--enabled-disk-template=%s" %
1106 6f665bf7 Helga Velroyen
       ",".join(enabled_disk_templates)],
1107 6f665bf7 Helga Velroyen
    fail=False)
1108 6f665bf7 Helga Velroyen
1109 6f665bf7 Helga Velroyen
  # Test instance creation for enabled disk templates
1110 6f665bf7 Helga Velroyen
  for disk_template in enabled_disk_templates:
1111 e75f80b9 Bernardo Dal Seno
    instance = CreateInstanceByDiskTemplate(nodes, disk_template, fail=False)
1112 6f665bf7 Helga Velroyen
    TestInstanceRemove(instance)
1113 e75f80b9 Bernardo Dal Seno
    instance.Release()
1114 6f665bf7 Helga Velroyen
1115 6f665bf7 Helga Velroyen
  # Test that instance creation fails for disabled disk templates
1116 6f665bf7 Helga Velroyen
  disabled_disk_templates = list(constants.DISK_TEMPLATES
1117 6f665bf7 Helga Velroyen
                                 - set(enabled_disk_templates))
1118 6f665bf7 Helga Velroyen
  for disk_template in disabled_disk_templates:
1119 e75f80b9 Bernardo Dal Seno
    instance = CreateInstanceByDiskTemplate(nodes, disk_template, fail=True)
1120 6f665bf7 Helga Velroyen
1121 6f665bf7 Helga Velroyen
  # Test instance creation for after disabling enabled disk templates
1122 6f665bf7 Helga Velroyen
  if (len(enabled_disk_templates) > 1):
1123 6f665bf7 Helga Velroyen
    # Partition the disk templates, enable them separately and check if the
1124 6f665bf7 Helga Velroyen
    # disabled ones cannot be used by instances.
1125 6f665bf7 Helga Velroyen
    middle = len(enabled_disk_templates) / 2
1126 6f665bf7 Helga Velroyen
    templates1 = enabled_disk_templates[:middle]
1127 6f665bf7 Helga Velroyen
    templates2 = enabled_disk_templates[middle:]
1128 6f665bf7 Helga Velroyen
1129 6f665bf7 Helga Velroyen
    for (enabled, disabled) in [(templates1, templates2),
1130 6f665bf7 Helga Velroyen
                                (templates2, templates1)]:
1131 6f665bf7 Helga Velroyen
      AssertCommand(["gnt-cluster", "modify",
1132 6f665bf7 Helga Velroyen
                     "--enabled-disk-template=%s" %
1133 6f665bf7 Helga Velroyen
                       ",".join(enabled)],
1134 6f665bf7 Helga Velroyen
                    fail=False)
1135 6f665bf7 Helga Velroyen
      for disk_template in disabled:
1136 e75f80b9 Bernardo Dal Seno
        CreateInstanceByDiskTemplate(nodes, disk_template, fail=True)
1137 6f665bf7 Helga Velroyen
  elif (len(enabled_disk_templates) == 1):
1138 6f665bf7 Helga Velroyen
    # If only one disk template is enabled in the QA config, we have to enable
1139 6f665bf7 Helga Velroyen
    # some of the disabled disk templates in order to test if the disabling the
1140 6f665bf7 Helga Velroyen
    # only enabled disk template prohibits creating instances of that template.
1141 6f665bf7 Helga Velroyen
    AssertCommand(["gnt-cluster", "modify",
1142 6f665bf7 Helga Velroyen
                   "--enabled-disk-template=%s" %
1143 6f665bf7 Helga Velroyen
                     ",".join(disabled_disk_templates)],
1144 6f665bf7 Helga Velroyen
                  fail=False)
1145 e75f80b9 Bernardo Dal Seno
    CreateInstanceByDiskTemplate(nodes, enabled_disk_templates[0], fail=True)
1146 6f665bf7 Helga Velroyen
  else:
1147 6f665bf7 Helga Velroyen
    raise qa_error.Error("Please enable at least one disk template"
1148 6f665bf7 Helga Velroyen
                         " in your QA setup.")
1149 6f665bf7 Helga Velroyen
1150 6f665bf7 Helga Velroyen
  # Restore initially enabled disk templates
1151 6f665bf7 Helga Velroyen
  AssertCommand(["gnt-cluster", "modify",
1152 6f665bf7 Helga Velroyen
                 "--enabled-disk-template=%s" %
1153 6f665bf7 Helga Velroyen
                   ",".join(enabled_disk_templates)],
1154 6f665bf7 Helga Velroyen
                 fail=False)