summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJenkins <jenkins@review.openstack.org>2016-09-02 00:07:48 +0000
committerGerrit Code Review <review@openstack.org>2016-09-02 00:07:48 +0000
commit8f35bb321d26bd7d296c57f4188ec12fcde897c3 (patch)
treef0daf2a77480399179a399e791bc108cc413fe3d
parente6543c20a4d81da4f087e0bc6cf47b5e458c0b52 (diff)
parent96926a8ee182550391c30b16b410da7f598c0f39 (diff)
downloadnova-8f35bb321d26bd7d296c57f4188ec12fcde897c3.tar.gz
Merge "Simple instance allocations from resource tracker"14.0.0.0b3
-rw-r--r--nova/compute/resource_tracker.py2
-rw-r--r--nova/scheduler/client/report.py67
-rw-r--r--nova/tests/unit/scheduler/client/test_report.py59
3 files changed, 128 insertions, 0 deletions
diff --git a/nova/compute/resource_tracker.py b/nova/compute/resource_tracker.py
index 82856196a0..972b0847f9 100644
--- a/nova/compute/resource_tracker.py
+++ b/nova/compute/resource_tracker.py
@@ -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)
diff --git a/nova/scheduler/client/report.py b/nova/scheduler/client/report.py
index a7b470881d..f97ef1a764 100644
--- a/nova/scheduler/client/report.py
+++ b/nova/scheduler/client/report.py
@@ -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)
diff --git a/nova/tests/unit/scheduler/client/test_report.py b/nova/tests/unit/scheduler/client/test_report.py
index bb16f2f914..1bba8c29a6 100644
--- a/nova/tests/unit/scheduler/client/test_report.py
+++ b/nova/tests/unit/scheduler/client/test_report.py
@@ -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)