Merge "Simple instance allocations from resource tracker"
This commit is contained in:
commit
8f35bb321d
@ -861,6 +861,8 @@ class ResourceTracker(object):
|
|||||||
self.pci_tracker.update_pci_for_instance(context,
|
self.pci_tracker.update_pci_for_instance(context,
|
||||||
instance,
|
instance,
|
||||||
sign=sign)
|
sign=sign)
|
||||||
|
self.scheduler_client.reportclient.update_instance_allocation(
|
||||||
|
self.compute_node, instance, sign)
|
||||||
# new instance, update compute node resource usage:
|
# new instance, update compute node resource usage:
|
||||||
self._update_usage(self._get_usage_dict(instance), sign=sign)
|
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 keystoneauth1 import session
|
||||||
from oslo_log import log as logging
|
from oslo_log import log as logging
|
||||||
|
|
||||||
|
from nova.compute import utils as compute_utils
|
||||||
import nova.conf
|
import nova.conf
|
||||||
from nova.i18n import _LE, _LI, _LW
|
from nova.i18n import _LE, _LI, _LW
|
||||||
from nova import objects
|
from nova import objects
|
||||||
@ -94,6 +95,11 @@ class SchedulerReportClient(object):
|
|||||||
url, json=data,
|
url, json=data,
|
||||||
endpoint_filter=self.ks_filter, raise_exc=False)
|
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
|
@safe_connect
|
||||||
def _get_resource_provider(self, uuid):
|
def _get_resource_provider(self, uuid):
|
||||||
"""Queries the placement API for a resource provider record with the
|
"""Queries the placement API for a resource provider record with the
|
||||||
@ -293,3 +299,64 @@ class SchedulerReportClient(object):
|
|||||||
compute_node.hypervisor_hostname)
|
compute_node.hypervisor_hostname)
|
||||||
if compute_node.uuid in self._resource_providers:
|
if compute_node.uuid in self._resource_providers:
|
||||||
self._update_inventory(compute_node)
|
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)
|
self.client.update_resource_stats(cn)
|
||||||
mock_save.assert_called_once_with()
|
mock_save.assert_called_once_with()
|
||||||
mock_ensure.assert_called_once_with(uuids.compute_node, 'host1')
|
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