Commit 717ede37 authored by Aaron Karper's avatar Aaron Karper
Browse files

Remove disk_template option from IAReqInstanceAlloc



This made it impossible to use the ialloc for heterogeneous instances.
Signed-off-by: default avatarAaron Karper <akarper@google.com>
Reviewed-by: default avatarMichele Tartara <mtartara@google.com>
parent 7cde6d8c
......@@ -583,11 +583,16 @@ def ComputeIPolicySpecViolation(ipolicy, mem_size, cpu_count, disk_count,
(constants.ISPEC_SPINDLE_USE, "", spindle_use),
] + [(constants.ISPEC_DISK_SIZE, str(idx), d)
for idx, d in enumerate(disk_sizes)]
allowed_dts = set(ipolicy[constants.IPOLICY_DTS])
ret = []
if disk_count != 0:
# This check doesn't make sense for diskless instances
test_settings.append((constants.ISPEC_DISK_COUNT, "", disk_count))
ret = []
allowed_dts = set(ipolicy[constants.IPOLICY_DTS])
elif constants.DT_DISKLESS not in allowed_dts:
ret.append("Disk template %s is not allowed (allowed templates %s)" %
(constants.DT_DISKLESS, utils.CommaJoin(allowed_dts)))
forbidden_dts = set(disk_types) - allowed_dts
if forbidden_dts:
ret.append("Disk template %s is not allowed (allowed templates: %s)" %
......@@ -604,8 +609,7 @@ def ComputeIPolicySpecViolation(ipolicy, mem_size, cpu_count, disk_count,
return ret + min_errs
def ComputeIPolicyDiskSizesViolation(ipolicy, disk_sizes,
disk_template,
def ComputeIPolicyDiskSizesViolation(ipolicy, disk_sizes, disks,
_compute_fn=_ComputeMinMaxSpec):
"""Verifies ipolicy against provided disk sizes.
......@@ -616,21 +620,21 @@ def ComputeIPolicyDiskSizesViolation(ipolicy, disk_sizes,
@param ipolicy: The ipolicy
@type disk_sizes: list of ints
@param disk_sizes: Disk sizes of used disk (len must match C{disk_count})
@type disk_template: string
@param disk_template: The disk template of the instance
@type disks: list of L{Disk}
@param disks: The Disk objects of the instance
@param _compute_fn: The compute function (unittest only)
@return: A list of violations, or an empty list of no violations are found
"""
if disk_template != constants.DT_DISKLESS and disk_sizes == []:
if len(disk_sizes) != len(disks):
return [constants.ISPEC_DISK_COUNT]
disk_templates = map(lambda _: disk_template, disk_sizes)
dev_types = [d.dev_type for d in disks]
return ComputeIPolicySpecViolation(ipolicy,
# mem_size, cpu_count, disk_count
None, None, len(disk_sizes),
None, disk_sizes, # nic_count, disk_sizes
None, # spindle_use
disk_templates,
dev_types,
_compute_fn=_compute_fn)
......
......@@ -793,6 +793,7 @@ class LUInstanceRecreateDisks(LogicalUnit):
# reasons, then recreating the disks on the same nodes should be fine.
disk_template = self.instance.disk_template
spindle_use = be_full[constants.BE_SPINDLE_USE]
disk_template = self.cfg.GetInstanceDiskTemplate(self.instance.uuid)
disks = [{
constants.IDISK_SIZE: d.size,
constants.IDISK_MODE: d.mode,
......@@ -800,6 +801,7 @@ class LUInstanceRecreateDisks(LogicalUnit):
constants.IDISK_TYPE: d.dev_type
} for d in self.cfg.GetInstanceDisks(self.instance.uuid)]
req = iallocator.IAReqInstanceAlloc(name=self.op.instance_name,
disk_template=disk_template,
group_name=None,
tags=list(self.instance.GetTags()),
os=self.instance.os,
......@@ -1763,12 +1765,12 @@ class LUInstanceGrowDisk(LogicalUnit):
ipolicy = ganeti.masterd.instance.CalculateGroupIPolicy(cluster,
group_info)
disks = self.cfg.GetInstanceDisks(self.op.instance_uuid)
disk_sizes = [disk.size if disk.uuid != self.disk.uuid else target_size
for disk in self.cfg.GetInstanceDisks(self.op.instance_uuid)]
for disk in disks]
# The ipolicy checker below ignores None, so we only give it the disk size
res = ComputeIPolicyDiskSizesViolation(ipolicy, disk_sizes,
self.instance.disk_template)
res = ComputeIPolicyDiskSizesViolation(ipolicy, disk_sizes, disks)
if res:
msg = ("Growing disk %s violates policy: %s" %
(self.op.disk,
......
......@@ -1155,6 +1155,7 @@ def CreateInstanceAllocRequest(op, disks, nics, beparams, node_name_whitelist):
"""
spindle_use = beparams[constants.BE_SPINDLE_USE]
return iallocator.IAReqInstanceAlloc(name=op.instance_name,
disk_template=op.disk_template,
group_name=op.group_name,
tags=op.tags,
os=op.os_type,
......
......@@ -408,6 +408,7 @@ class LUTestAllocator(NoHooksLU):
req = iallocator.IAReqInstanceAlloc(name=self.op.name,
memory=self.op.memory,
disks=self.op.disks,
disk_template=self.op.disk_template,
group_name=self.op.group_name,
os=self.op.os,
tags=self.op.tags,
......@@ -428,9 +429,11 @@ class LUTestAllocator(NoHooksLU):
evac_mode=self.op.evac_mode,
ignore_soft_errors=False)
elif self.op.mode == constants.IALLOCATOR_MODE_MULTI_ALLOC:
disk_template = self.op.disk_template
insts = [iallocator.IAReqInstanceAlloc(name="%s%s" % (self.op.name, idx),
memory=self.op.memory,
disks=self.op.disks,
disk_template=disk_template,
group_name=self.op.group_name,
os=self.op.os,
tags=self.op.tags,
......
......@@ -172,6 +172,7 @@ class IAReqInstanceAlloc(IARequestBase):
("memory", ht.TNonNegativeInt),
("spindle_use", ht.TNonNegativeInt),
("disks", ht.TListOf(ht.TDict)),
("disk_template", ht.TString),
("group_name", ht.TMaybe(ht.TNonEmptyString)),
("os", ht.TString),
("tags", _STRING_LIST),
......@@ -186,8 +187,7 @@ class IAReqInstanceAlloc(IARequestBase):
"""Calculates the required nodes based on the disk_template.
"""
disk_types = [d[constants.IDISK_TYPE] for d in self.disks]
if any(d in constants.DTS_INT_MIRROR for d in disk_types):
if self.disk_template in constants.DTS_INT_MIRROR:
return 2
else:
return 1
......@@ -199,10 +199,13 @@ class IAReqInstanceAlloc(IARequestBase):
done.
"""
for d in self.disks:
d[constants.IDISK_TYPE] = self.disk_template
disk_space = gmi.ComputeDiskSize(self.disks)
return {
"name": self.name,
"disk_template": self.disk_template,
"group_name": self.group_name,
"tags": self.tags,
"os": self.os,
......@@ -514,7 +517,8 @@ class IAllocator(object):
assert len(data["nodes"]) == len(ninfo), \
"Incomplete node data computed"
data["instances"] = self._ComputeInstanceData(cfg, cluster_info, i_list)
data["instances"] = self._ComputeInstanceData(cfg, cluster_info, i_list,
disk_template)
self.in_data = data
......@@ -752,7 +756,7 @@ class IAllocator(object):
return node_results
@staticmethod
def _ComputeInstanceData(cfg, cluster_info, i_list):
def _ComputeInstanceData(cfg, cluster_info, i_list, disk_template):
"""Compute global instance data.
"""
......@@ -787,7 +791,7 @@ class IAllocator(object):
constants.IDISK_MODE: dsk.mode,
constants.IDISK_SPINDLES: dsk.spindles}
for dsk in inst_disks],
"disk_template": iinfo.disk_template,
"disk_template": disk_template,
"disks_active": iinfo.disks_active,
"hypervisor": iinfo.hypervisor,
}
......@@ -802,8 +806,12 @@ class IAllocator(object):
"""
request = req.GetRequest(self.cfg)
disk_template = None
if "disk_template" in request:
if request.get("disk_template") is not None:
disk_template = request["disk_template"]
else:
disk_template = self.cfg.GetInstanceDiskTemplate(self.req.inst_uuid)
if disk_template is None:
raise errors.ProgrammerError("disk template should not be none")
self._ComputeClusterData(disk_template=disk_template)
request["type"] = req.MODE
......
......@@ -1683,15 +1683,24 @@ def ComputeDiskSize(disks):
"""
# Required free disk space as a function of disk and swap space
size = 0
for d in disks:
def size_f(d):
dev_type = d[constants.IDISK_TYPE]
if dev_type != constants.DT_BLOCK:
size += d[constants.IDISK_SIZE]
# 128 MB are added for drbd metadata for each disk
if dev_type == constants.DT_DRBD8:
size += constants.DRBD_META_SIZE
return size
req_size_dict = {
constants.DT_DISKLESS: 0,
constants.DT_PLAIN: d[constants.IDISK_SIZE],
# Extra space for drbd metadata is added to each disk
constants.DT_DRBD8:
d[constants.IDISK_SIZE] + constants.DRBD_META_SIZE,
constants.DT_FILE: d[constants.IDISK_SIZE],
constants.DT_SHARED_FILE: d[constants.IDISK_SIZE],
constants.DT_GLUSTER: d[constants.IDISK_SIZE],
constants.DT_BLOCK: 0,
constants.DT_RBD: d[constants.IDISK_SIZE],
constants.DT_EXT: d[constants.IDISK_SIZE],
}
if dev_type not in req_size_dict:
raise errors.ProgrammerError("Disk template '%s' size requirement"
" is unknown" % dev_type)
return req_size_dict[dev_type]
return sum(map(size_f, disks))
......@@ -563,42 +563,57 @@ class TestComputeIPolicyDiskSizesViolation(unittest.TestCase):
# Minimal policy accepted by _ComputeIPolicyDiskSizesViolation()
_MICRO_IPOL = {
constants.IPOLICY_DTS: [constants.DT_PLAIN, constants.DT_DISKLESS],
constants.ISPECS_MINMAX: [NotImplemented],
constants.ISPECS_MINMAX: [None],
}
def MakeDisks(self, *dev_types):
return [mock.Mock(dev_type=d) for d in dev_types]
def test(self):
compute_fn = _ValidateComputeMinMaxSpec
ret = common.ComputeIPolicyDiskSizesViolation(self._MICRO_IPOL, [1024],
constants.DT_PLAIN,
_compute_fn=compute_fn)
ret = common.ComputeIPolicyDiskSizesViolation(
self._MICRO_IPOL, [1024], self.MakeDisks(constants.DT_PLAIN),
_compute_fn=compute_fn)
self.assertEqual(ret, [])
def testDiskFull(self):
compute_fn = _NoDiskComputeMinMaxSpec
ret = common.ComputeIPolicyDiskSizesViolation(self._MICRO_IPOL, [1024],
constants.DT_PLAIN,
_compute_fn=compute_fn)
ret = common.ComputeIPolicyDiskSizesViolation(
self._MICRO_IPOL, [1024], self.MakeDisks(constants.DT_PLAIN),
_compute_fn=compute_fn)
self.assertEqual(ret, [constants.ISPEC_DISK_COUNT])
def testDisksMixed(self):
compute_fn = _ValidateComputeMinMaxSpec
ipol = copy.deepcopy(self._MICRO_IPOL)
ipol[constants.IPOLICY_DTS].append(constants.DT_DRBD8)
ret = common.ComputeIPolicyDiskSizesViolation(
ipol, [1024, 1024],
self.MakeDisks(constants.DT_DRBD8, constants.DT_PLAIN),
_compute_fn=compute_fn)
self.assertEqual(ret, [])
def testDiskLess(self):
compute_fn = _NoDiskComputeMinMaxSpec
ret = common.ComputeIPolicyDiskSizesViolation(self._MICRO_IPOL, [],
constants.DT_DISKLESS,
[],
_compute_fn=compute_fn)
self.assertEqual(ret, [])
def testWrongTemplates(self):
compute_fn = _ValidateComputeMinMaxSpec
ret = common.ComputeIPolicyDiskSizesViolation(self._MICRO_IPOL, [1024],
constants.DT_DRBD8,
_compute_fn=compute_fn)
ret = common.ComputeIPolicyDiskSizesViolation(
self._MICRO_IPOL, [1024], self.MakeDisks(constants.DT_DRBD8),
_compute_fn=compute_fn)
self.assertEqual(len(ret), 1)
self.assertTrue("Disk template" in ret[0])
def _AssertComputeViolation(self, ipolicy, disk_sizes, disk_template,
def _AssertComputeViolation(self, ipolicy, disk_sizes, dev_types,
violations):
ret = common.ComputeIPolicyDiskSizesViolation(ipolicy, disk_sizes,
disk_template)
ret = common.ComputeIPolicyDiskSizesViolation(
ipolicy, disk_sizes, self.MakeDisks(*dev_types))
self.assertEqual(len(ret), violations)
def testWithIPolicy(self):
......@@ -626,11 +641,13 @@ class TestComputeIPolicyDiskSizesViolation(unittest.TestCase):
constants.IPOLICY_DTS: [disk_template],
}
self._AssertComputeViolation(ipolicy, [512], disk_template, 0)
self._AssertComputeViolation(ipolicy, [], disk_template, 1)
self._AssertComputeViolation(ipolicy, [512, 512], disk_template, 1)
self._AssertComputeViolation(ipolicy, [511], disk_template, 1)
self._AssertComputeViolation(ipolicy, [513], disk_template, 1)
self._AssertComputeViolation(ipolicy, [512], [disk_template], 0)
self._AssertComputeViolation(ipolicy, [], [disk_template], 1)
self._AssertComputeViolation(ipolicy, [], [], 1)
self._AssertComputeViolation(ipolicy, [512, 512],
[disk_template, disk_template], 1)
self._AssertComputeViolation(ipolicy, [511], [disk_template], 1)
self._AssertComputeViolation(ipolicy, [513], [disk_template], 1)
class _StubComputeIPolicySpecViolation:
......
......@@ -125,6 +125,7 @@ class TestLUTestAllocator(CmdlibTestCase):
name="new-instance.example.com",
nics=[],
disks=[],
disk_template=constants.DT_DISKLESS,
direction=constants.IALLOCATOR_DIR_OUT,
iallocator="test")
......@@ -132,6 +133,7 @@ class TestLUTestAllocator(CmdlibTestCase):
self.CopyOpCode(self.base_op,
mode=constants.IALLOCATOR_MODE_ALLOC,
memory=0,
disk_template=constants.DT_DISKLESS,
os="mock_os",
group_name="default",
vcpus=1)
......@@ -140,6 +142,7 @@ class TestLUTestAllocator(CmdlibTestCase):
mode=constants.IALLOCATOR_MODE_MULTI_ALLOC,
instances=["new-instance.example.com"],
memory=0,
disk_template=constants.DT_DISKLESS,
os="mock_os",
group_name="default",
vcpus=1)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment