qa_config.get(constants.BE_MAXMEM)))
if disk_template != constants.DT_DISKLESS:
- for idx, size in enumerate(qa_config.get("disk")):
- params.extend(["--disk", "%s:size=%s" % (idx, size)])
+ for idx, disk in enumerate(qa_config.GetDiskOptions()):
+ size = disk.get("size")
+ name = disk.get("name")
+ diskparams = "%s:size=%s" % (idx, size)
+ if name:
+ diskparams += ",name=%s" % name
+ params.extend(["--disk", diskparams])
# Set static MAC address if configured
if force_mac:
return params
-def _DiskTest(node, disk_template, fail=False):
+def _CreateInstanceByDiskTemplateRaw(nodes_spec, disk_template, fail=False):
+ """Creates an instance with the given disk template on the given nodes(s).
+ Note that this function does not check if enough nodes are given for
+ the respective disk template.
+
+ @type nodes_spec: string
+ @param nodes_spec: string specification of one node (by node name) or several
+ nodes according to the requirements of the disk template
+ @type disk_template: string
+ @param disk_template: the disk template to be used by the instance
+ @return: the created instance
+
+ """
instance = qa_config.AcquireInstance()
try:
cmd = (["gnt-instance", "add",
"--os-type=%s" % qa_config.get("os"),
"--disk-template=%s" % disk_template,
- "--node=%s" % node] +
+ "--node=%s" % nodes_spec] +
_GetGenericAddParameters(instance, disk_template))
cmd.append(instance.name)
return None
+def _CreateInstanceByDiskTemplateOneNode(nodes, disk_template, fail=False):
+ """Creates an instance using the given disk template for disk templates
+ for which one given node is sufficient. These templates are for example:
+ plain, diskless, file, sharedfile, blockdev, rados.
+
+ @type nodes: list of nodes
+ @param nodes: a list of nodes, whose first element is used to create the
+ instance
+ @type disk_template: string
+ @param disk_template: the disk template to be used by the instance
+ @return: the created instance
+
+ """
+ assert len(nodes) > 0
+ return _CreateInstanceByDiskTemplateRaw(nodes[0].primary, disk_template,
+ fail=fail)
+
+
+def _CreateInstanceDrbd8(nodes, fail=False):
+ """Creates an instance using disk template 'drbd' on the given nodes.
+
+ @type nodes: list of nodes
+ @param nodes: nodes to be used by the instance
+ @return: the created instance
+
+ """
+ assert len(nodes) > 1
+ return _CreateInstanceByDiskTemplateRaw(
+ ":".join(map(operator.attrgetter("primary"), nodes)),
+ constants.DT_DRBD8, fail=fail)
+
+
+def CreateInstanceByDiskTemplate(nodes, disk_template, fail=False):
+ """Given a disk template, this function creates an instance using
+ the template. It uses the required number of nodes depending on
+ the disk template. This function is intended to be used by tests
+ that don't care about the specifics of the instance other than
+ that it uses the given disk template.
+
+ Note: If you use this function, make sure to call
+ 'TestInstanceRemove' at the end of your tests to avoid orphaned
+ instances hanging around and interfering with the following tests.
+
+ @type nodes: list of nodes
+ @param nodes: the list of the nodes on which the instance will be placed;
+ it needs to have sufficiently many elements for the given
+ disk template
+ @type disk_template: string
+ @param disk_template: the disk template to be used by the instance
+ @return: the created instance
+
+ """
+ if disk_template == constants.DT_DRBD8:
+ return _CreateInstanceDrbd8(nodes, fail=fail)
+ elif disk_template in [constants.DT_DISKLESS, constants.DT_PLAIN,
+ constants.DT_FILE]:
+ return _CreateInstanceByDiskTemplateOneNode(nodes, disk_template, fail=fail)
+ else:
+ # FIXME: This assumes that for all other disk templates, we only need one
+ # node and no disk template specific parameters. This else-branch is
+ # currently only used in cases where we expect failure. Extend it when
+ # QA needs for these templates change.
+ return _CreateInstanceByDiskTemplateOneNode(nodes, disk_template, fail=fail)
+
+
def _GetInstanceInfo(instance):
"""Return information about the actual state of an instance.
@type instance: string
@param instance: Instance name
@type spec: string
- @param spec: one of the supported parameters: "mem-size", "cpu-count",
+ @param spec: one of the supported parameters: "memory-size", "cpu-count",
"disk-count", "disk-size", "nic-count"
@rtype: tuple
@return: (minspec, maxspec); minspec and maxspec can be different only for
"""
specmap = {
- "mem-size": ["be/minmem", "be/maxmem"],
+ "memory-size": ["be/minmem", "be/maxmem"],
"cpu-count": ["vcpus"],
"disk-count": ["disk.count"],
"disk-size": ["disk.size/ "],
return instance.disk_template == constants.DT_DRBD8
+def IsDiskSupported(instance):
+ return instance.disk_template != constants.DT_DISKLESS
+
+
def TestInstanceAddWithPlainDisk(nodes, fail=False):
"""gnt-instance add -t plain"""
- assert len(nodes) == 1
- instance = _DiskTest(nodes[0].primary, constants.DT_PLAIN, fail=fail)
- if not fail:
- qa_utils.RunInstanceCheck(instance, True)
- return instance
+ if constants.DT_PLAIN in qa_config.GetEnabledDiskTemplates():
+ instance = _CreateInstanceByDiskTemplateOneNode(nodes, constants.DT_PLAIN,
+ fail=fail)
+ if not fail:
+ qa_utils.RunInstanceCheck(instance, True)
+ return instance
@InstanceCheck(None, INST_UP, RETURN_VALUE)
def TestInstanceAddWithDrbdDisk(nodes):
"""gnt-instance add -t drbd"""
- assert len(nodes) == 2
- return _DiskTest(":".join(map(operator.attrgetter("primary"), nodes)),
- constants.DT_DRBD8)
+ if constants.DT_DRBD8 in qa_config.GetEnabledDiskTemplates():
+ return _CreateInstanceDrbd8(nodes)
@InstanceCheck(None, INST_UP, RETURN_VALUE)
def TestInstanceAddFile(nodes):
"""gnt-instance add -t file"""
assert len(nodes) == 1
- return _DiskTest(nodes[0].primary, constants.DT_FILE)
+ if constants.DT_FILE in qa_config.GetEnabledDiskTemplates():
+ return _CreateInstanceByDiskTemplateOneNode(nodes, constants.DT_FILE)
@InstanceCheck(None, INST_UP, RETURN_VALUE)
def TestInstanceAddDiskless(nodes):
"""gnt-instance add -t diskless"""
assert len(nodes) == 1
- return _DiskTest(nodes[0].primary, constants.DT_DISKLESS)
+ if constants.DT_FILE in qa_config.GetEnabledDiskTemplates():
+ return _CreateInstanceByDiskTemplateOneNode(nodes, constants.DT_DISKLESS)
@InstanceCheck(None, INST_DOWN, FIRST_ARG)
"-n", inodes[1].primary, name])
+@InstanceCheck(INST_UP, INST_UP, FIRST_ARG)
+def TestInstanceModifyDisks(instance):
+ """gnt-instance modify --disk"""
+ if not IsDiskSupported(instance):
+ print qa_utils.FormatInfo("Instance doesn't support disks, skipping test")
+ return
+
+ size = qa_config.GetDiskOptions()[-1].get("size")
+ name = instance.name
+ build_cmd = lambda arg: ["gnt-instance", "modify", "--disk", arg, name]
+ AssertCommand(build_cmd("add:size=%s" % size))
+ AssertCommand(build_cmd("remove"))
+
+
@InstanceCheck(INST_DOWN, INST_DOWN, FIRST_ARG)
def TestInstanceGrowDisk(instance):
"""gnt-instance grow-disk"""
return
name = instance.name
- all_size = qa_config.get("disk")
- all_grow = qa_config.get("disk-growth")
+ disks = qa_config.GetDiskOptions()
+ all_size = [d.get("size") for d in disks]
+ all_grow = [d.get("growth") for d in disks]
if not all_grow:
# missing disk sizes but instance grow disk has been enabled,
str(int_size + 2 * int_grow)])
+@InstanceCheck(INST_UP, INST_UP, FIRST_ARG)
+def TestInstanceDeviceNames(instance):
+ if instance.disk_template == constants.DT_DISKLESS:
+ print qa_utils.FormatInfo("Test not supported for diskless instances")
+ return
+
+ name = instance.name
+ for dev_type in ["disk", "net"]:
+ if dev_type == "disk":
+ options = ",size=512M"
+ else:
+ options = ""
+ # succeed in adding a device named 'test_device'
+ AssertCommand(["gnt-instance", "modify",
+ "--%s=-1:add,name=test_device%s" % (dev_type, options),
+ name])
+ # succeed in removing the 'test_device'
+ AssertCommand(["gnt-instance", "modify",
+ "--%s=test_device:remove" % dev_type,
+ name])
+ # fail to add two devices with the same name
+ AssertCommand(["gnt-instance", "modify",
+ "--%s=-1:add,name=test_device%s" % (dev_type, options),
+ "--%s=-1:add,name=test_device%s" % (dev_type, options),
+ name], fail=True)
+ # fail to add a device with invalid name
+ AssertCommand(["gnt-instance", "modify",
+ "--%s=-1:add,name=2%s" % (dev_type, options),
+ name], fail=True)
+ # Rename disks
+ disks = qa_config.GetDiskOptions()
+ disk_names = [d.get("name") for d in disks]
+ for idx, disk_name in enumerate(disk_names):
+ # Refer to disk by idx
+ AssertCommand(["gnt-instance", "modify",
+ "--disk=%s:modify,name=renamed" % idx,
+ name])
+ # Refer to by name and rename to original name
+ AssertCommand(["gnt-instance", "modify",
+ "--disk=renamed:modify,name=%s" % disk_name,
+ name])
+ if len(disks) >= 2:
+ # fail in renaming to disks to the same name
+ AssertCommand(["gnt-instance", "modify",
+ "--disk=0:modify,name=same_name",
+ "--disk=1:modify,name=same_name",
+ name], fail=True)
+
+
def TestInstanceList():
"""gnt-instance list"""
qa_utils.GenericQueryTest("gnt-instance", query.INSTANCE_FIELDS.keys())
else:
_AssertRecreateDisks(["-n", other_seq], instance)
# Move disks back
- _AssertRecreateDisks(["-n", orig_seq], instance, check=False)
+ _AssertRecreateDisks(["-n", orig_seq], instance)
+ # Recreate the disks one by one
+ for idx in range(0, len(qa_config.GetDiskOptions())):
+ # Only the first call should destroy all the disk
+ destroy = (idx == 0)
+ _AssertRecreateDisks(["--disk=%s" % idx], instance, destroy=destroy,
+ check=False)
# This and InstanceCheck decoration check that the disks are working
AssertCommand(["gnt-instance", "reinstall", "-f", instance.name])
AssertCommand(["gnt-instance", "start", instance.name])
filestorage = pathutils.DEFAULT_FILE_STORAGE_DIR
disk = os.path.join(filestorage, instance.name)
AssertCommand(["rm", "-rf", disk], node=snode)
+
+
+def TestInstanceCreationRestrictedByDiskTemplates():
+ """Test adding instances for disabled disk templates."""
+ enabled_disk_templates = qa_config.GetEnabledDiskTemplates()
+ nodes = qa_config.AcquireManyNodes(2)
+
+ # Setup the cluster with the enabled_disk_templates
+ AssertCommand(
+ ["gnt-cluster", "modify",
+ "--enabled-disk-template=%s" %
+ ",".join(enabled_disk_templates)],
+ fail=False)
+
+ # Test instance creation for enabled disk templates
+ for disk_template in enabled_disk_templates:
+ instance = CreateInstanceByDiskTemplate(nodes, disk_template, fail=False)
+ TestInstanceRemove(instance)
+ instance.Release()
+
+ # Test that instance creation fails for disabled disk templates
+ disabled_disk_templates = list(constants.DISK_TEMPLATES
+ - set(enabled_disk_templates))
+ for disk_template in disabled_disk_templates:
+ instance = CreateInstanceByDiskTemplate(nodes, disk_template, fail=True)
+
+ # Test instance creation for after disabling enabled disk templates
+ if (len(enabled_disk_templates) > 1):
+ # Partition the disk templates, enable them separately and check if the
+ # disabled ones cannot be used by instances.
+ middle = len(enabled_disk_templates) / 2
+ templates1 = enabled_disk_templates[:middle]
+ templates2 = enabled_disk_templates[middle:]
+
+ for (enabled, disabled) in [(templates1, templates2),
+ (templates2, templates1)]:
+ AssertCommand(["gnt-cluster", "modify",
+ "--enabled-disk-template=%s" %
+ ",".join(enabled)],
+ fail=False)
+ for disk_template in disabled:
+ CreateInstanceByDiskTemplate(nodes, disk_template, fail=True)
+ elif (len(enabled_disk_templates) == 1):
+ # If only one disk template is enabled in the QA config, we have to enable
+ # some of the disabled disk templates in order to test if the disabling the
+ # only enabled disk template prohibits creating instances of that template.
+ AssertCommand(["gnt-cluster", "modify",
+ "--enabled-disk-template=%s" %
+ ",".join(disabled_disk_templates)],
+ fail=False)
+ CreateInstanceByDiskTemplate(nodes, enabled_disk_templates[0], fail=True)
+ else:
+ raise qa_error.Error("Please enable at least one disk template"
+ " in your QA setup.")
+
+ # Restore initially enabled disk templates
+ AssertCommand(["gnt-cluster", "modify",
+ "--enabled-disk-template=%s" %
+ ",".join(enabled_disk_templates)],
+ fail=False)