Parse vpmem related flavor extra spec

Support parsing extra specs properties as below:
   hw:pmem=4GB,SMALL

In the compute API layer, if the only vpmem is requested without
explicitly specifiy the instance NUMA topology, then one cell NUMA
topology will be added to instance.

And then translate it to placement resource request.

Change-Id: Ifeeb7710fb39befbd0d0693ca2b4c3aa79878127
Partially-Implements: blueprint virtual-persistent-memory
Co-Authored-By: He Jie Xu <hejie.xu@intel.com>
This commit is contained in:
LuyaoZhong 2019-09-02 12:34:18 +00:00
parent c39ad2383c
commit ae59c331cc
4 changed files with 62 additions and 4 deletions

View File

@ -124,6 +124,8 @@ class ResourceRequest(object):
self._translate_memory_encryption(request_spec.flavor, image)
self._translate_vpmems_request(request_spec.flavor)
self.strip_zeros()
def _process_extra_specs(self, flavor):
@ -179,6 +181,24 @@ class ResourceRequest(object):
LOG.debug("Added %s=1 to requested resources",
orc.MEM_ENCRYPTION_CONTEXT)
def _translate_vpmems_request(self, flavor):
"""When the hw:pmem extra spec is present, require hosts which can
provide enough vpmem resources.
"""
vpmem_labels = hw.get_vpmems(flavor)
if not vpmem_labels:
# No vpmems required
return
amount_by_rc = collections.defaultdict(int)
for vpmem_label in vpmem_labels:
resource_class = orc.normalize_name(
"PMEM_NAMESPACE_" + vpmem_label)
amount_by_rc[resource_class] += 1
for resource_class, amount in amount_by_rc.items():
self._add_resource(None, resource_class, amount)
LOG.debug("Added resource %s=%d to requested resources",
resource_class, amount)
@property
def group_policy(self):
return self._group_policy

View File

@ -945,6 +945,26 @@ class TestUtils(TestUtilsBase):
rr = utils.ResourceRequest(rs)
self.assertResourceRequestsEqual(expected, rr)
def test_resource_request_with_vpmems(self):
flavor = objects.Flavor(
vcpus=1, memory_mb=1024, root_gb=10, ephemeral_gb=5, swap=0,
extra_specs={'hw:pmem': '4GB, 4GB,SMALL'})
expected = FakeResourceRequest()
expected._rg_by_id[None] = objects.RequestGroup(
use_same_provider=False,
resources={
'VCPU': 1,
'MEMORY_MB': 1024,
'DISK_GB': 15,
'CUSTOM_PMEM_NAMESPACE_4GB': 2,
'CUSTOM_PMEM_NAMESPACE_SMALL': 1
},
)
rs = objects.RequestSpec(flavor=flavor, is_bfv=False)
rr = utils.ResourceRequest(rs)
self.assertResourceRequestsEqual(expected, rr)
def test_resource_request_add_group_inserts_the_group(self):
flavor = objects.Flavor(
vcpus=1, memory_mb=1024, root_gb=10, ephemeral_gb=5, swap=0)

View File

@ -1302,6 +1302,16 @@ class NUMATopologyTest(test.NoDBTestCase):
},
"expect": exception.ImageCPUPinningForbidden,
},
{
"flavor": objects.Flavor(vcpus=4, memory_mb=2048, extra_specs={
"hw:pmem": '2GB'}),
"image": {},
"expect": objects.InstanceNUMATopology(cells=
[
objects.InstanceNUMACell(
id=0, cpuset=set([0, 1, 2, 3]), memory=2048),
]),
},
]
for testitem in testdata:

View File

@ -1683,8 +1683,9 @@ def numa_get_constraints(flavor, image_meta):
nodes = _get_numa_node_count_constraint(flavor, image_meta)
pagesize = _get_numa_pagesize_constraint(flavor, image_meta)
vpmems = get_vpmems(flavor)
if nodes or pagesize:
if nodes or pagesize or vpmems:
nodes = nodes or 1
cpu_list = _get_numa_cpu_constraint(flavor, image_meta)
@ -2074,6 +2075,13 @@ def get_vpmems(flavor):
:param flavor: a flavor object to read extra specs from
:returns: a vpmem label list
"""
# TODO(Luyao) Return vpmem label list when the whole
# vpmem feature is supported.
return []
vpmems_info = flavor.get('extra_specs', {}).get('hw:pmem')
if not vpmems_info:
return []
vpmem_labels = vpmems_info.split(',')
formed_labels = []
for label in vpmem_labels:
formed_label = label.strip()
if formed_label:
formed_labels.append(formed_label)
return formed_labels