Simple instance allocations from resource tracker
This adds simple update/delete of allocations to the resource tracker using existing places that determine our claim and tracking processes. Related to blueprint resource-providers-allocations Change-Id: Ia250e6b1b65b16b0ecb97f5cf21e161ff511cb2a
This commit is contained in:
parent
f441ee55c6
commit
96926a8ee1
@ -861,6 +861,8 @@ class ResourceTracker(object):
|
||||
self.pci_tracker.update_pci_for_instance(context,
|
||||
instance,
|
||||
sign=sign)
|
||||
self.scheduler_client.reportclient.update_instance_allocation(
|
||||
self.compute_node, instance, sign)
|
||||
# new instance, update compute node resource usage:
|
||||
self._update_usage(self._get_usage_dict(instance), sign=sign)
|
||||
|
||||
|
@ -20,6 +20,7 @@ from keystoneauth1 import loading as keystone
|
||||
from keystoneauth1 import session
|
||||
from oslo_log import log as logging
|
||||
|
||||
from nova.compute import utils as compute_utils
|
||||
import nova.conf
|
||||
from nova.i18n import _LE, _LI, _LW
|
||||
from nova import objects
|
||||
@ -94,6 +95,11 @@ class SchedulerReportClient(object):
|
||||
url, json=data,
|
||||
endpoint_filter=self.ks_filter, raise_exc=False)
|
||||
|
||||
def delete(self, url):
|
||||
return self._client.delete(
|
||||
url,
|
||||
endpoint_filter=self.ks_filter, raise_exc=False)
|
||||
|
||||
@safe_connect
|
||||
def _get_resource_provider(self, uuid):
|
||||
"""Queries the placement API for a resource provider record with the
|
||||
@ -293,3 +299,64 @@ class SchedulerReportClient(object):
|
||||
compute_node.hypervisor_hostname)
|
||||
if compute_node.uuid in self._resource_providers:
|
||||
self._update_inventory(compute_node)
|
||||
|
||||
def _allocations(self, instance):
|
||||
# NOTE(danms): Boot-from-volume instances consume no local disk
|
||||
is_bfv = compute_utils.is_volume_backed_instance(instance._context,
|
||||
instance)
|
||||
disk = ((0 if is_bfv else instance.flavor.root_gb) +
|
||||
instance.flavor.swap +
|
||||
instance.flavor.ephemeral_gb)
|
||||
return {
|
||||
'MEMORY_MB': instance.flavor.memory_mb,
|
||||
'VCPU': instance.flavor.vcpus,
|
||||
'DISK_GB': disk,
|
||||
}
|
||||
|
||||
@safe_connect
|
||||
def _allocate_for_instance(self, compute_node, instance):
|
||||
url = '/allocations/%s' % instance.uuid
|
||||
allocations = {
|
||||
'allocations': [
|
||||
{
|
||||
'resource_provider': {
|
||||
'uuid': compute_node.uuid,
|
||||
},
|
||||
'resources': self._allocations(instance),
|
||||
},
|
||||
],
|
||||
}
|
||||
LOG.debug('Sending allocation for instance %s: %s' % (
|
||||
instance.uuid, allocations))
|
||||
r = self.put(url, allocations)
|
||||
if not r:
|
||||
LOG.warning(
|
||||
_LW('Unable to submit allocation for instance '
|
||||
'%(uuid)s (%(code)i %(text)s)'),
|
||||
{'uuid': instance.uuid,
|
||||
'code': r.status_code,
|
||||
'text': r.text})
|
||||
else:
|
||||
LOG.info(_LI('Submitted allocation for instance %s'),
|
||||
instance.uuid)
|
||||
|
||||
@safe_connect
|
||||
def _delete_allocation_for_instance(self, instance):
|
||||
url = '/allocations/%s' % instance.uuid
|
||||
r = self.delete(url)
|
||||
if r:
|
||||
LOG.info(_LI('Deleted allocation for instance %s'),
|
||||
instance.uuid)
|
||||
else:
|
||||
LOG.warning(
|
||||
_LW('Unable to delete allocation for instance '
|
||||
'%(uuid)s: (%(code)i %(text)s)'),
|
||||
{'uuid': instance.uuid,
|
||||
'code': r.status_code,
|
||||
'text': r.text})
|
||||
|
||||
def update_instance_allocation(self, compute_node, instance, sign):
|
||||
if sign > 0:
|
||||
self._allocate_for_instance(compute_node, instance)
|
||||
else:
|
||||
self._delete_allocation_for_instance(instance)
|
||||
|
@ -535,3 +535,62 @@ class SchedulerReportClientTestCase(test.NoDBTestCase):
|
||||
self.client.update_resource_stats(cn)
|
||||
mock_save.assert_called_once_with()
|
||||
mock_ensure.assert_called_once_with(uuids.compute_node, 'host1')
|
||||
|
||||
@mock.patch('nova.compute.utils.is_volume_backed_instance')
|
||||
def test_allocations(self, mock_vbi):
|
||||
mock_vbi.return_value = False
|
||||
inst = objects.Instance(
|
||||
uuid=uuids.inst,
|
||||
flavor=objects.Flavor(root_gb=10,
|
||||
swap=1,
|
||||
ephemeral_gb=100,
|
||||
memory_mb=1024,
|
||||
vcpus=2))
|
||||
expected = {
|
||||
'MEMORY_MB': 1024,
|
||||
'VCPU': 2,
|
||||
'DISK_GB': 111,
|
||||
}
|
||||
self.assertEqual(expected, self.client._allocations(inst))
|
||||
|
||||
@mock.patch('nova.compute.utils.is_volume_backed_instance')
|
||||
def test_allocations_boot_from_volume(self, mock_vbi):
|
||||
mock_vbi.return_value = True
|
||||
inst = objects.Instance(
|
||||
uuid=uuids.inst,
|
||||
flavor=objects.Flavor(root_gb=10,
|
||||
swap=1,
|
||||
ephemeral_gb=100,
|
||||
memory_mb=1024,
|
||||
vcpus=2))
|
||||
expected = {
|
||||
'MEMORY_MB': 1024,
|
||||
'VCPU': 2,
|
||||
'DISK_GB': 101,
|
||||
}
|
||||
self.assertEqual(expected, self.client._allocations(inst))
|
||||
|
||||
@mock.patch('nova.scheduler.client.report.SchedulerReportClient.'
|
||||
'put')
|
||||
def test_update_instance_allocation_new(self, mock_put):
|
||||
cn = objects.ComputeNode(uuid=uuids.cn)
|
||||
inst = objects.Instance(uuid=uuids.inst)
|
||||
with mock.patch.object(self.client, '_allocations') as mock_a:
|
||||
expected = {
|
||||
'allocations': [
|
||||
{'resource_provider': {'uuid': cn.uuid},
|
||||
'resources': mock_a.return_value}]
|
||||
}
|
||||
self.client.update_instance_allocation(cn, inst, 1)
|
||||
mock_put.assert_called_once_with(
|
||||
'/allocations/%s' % inst.uuid,
|
||||
expected)
|
||||
|
||||
@mock.patch('nova.scheduler.client.report.SchedulerReportClient.'
|
||||
'delete')
|
||||
def test_update_instance_allocation_delete(self, mock_delete):
|
||||
cn = objects.ComputeNode(uuid=uuids.cn)
|
||||
inst = objects.Instance(uuid=uuids.inst)
|
||||
self.client.update_instance_allocation(cn, inst, -1)
|
||||
mock_delete.assert_called_once_with(
|
||||
'/allocations/%s' % inst.uuid)
|
||||
|
Loading…
Reference in New Issue
Block a user