diff options
author | Jenkins <jenkins@review.openstack.org> | 2017-03-06 12:10:41 +0000 |
---|---|---|
committer | Gerrit Code Review <review@openstack.org> | 2017-03-06 12:10:41 +0000 |
commit | a5141e9aebab616fe42eb910a222d25b773b287c (patch) | |
tree | f895e08eae1b2f3ae49cb5da4b3df08c1aafe5cf /nova | |
parent | d9f9d297218b78a4f3a2437a9699634fa8a3f284 (diff) | |
parent | d8498aaad216297f04feea67935d06cfdd814fa5 (diff) | |
download | nova-a5141e9aebab616fe42eb910a222d25b773b287c.tar.gz |
Merge "placement: refactor translate from node to dict" into stable/newton
Diffstat (limited to 'nova')
-rw-r--r-- | nova/scheduler/client/report.py | 79 | ||||
-rw-r--r-- | nova/tests/unit/scheduler/client/test_report.py | 187 |
2 files changed, 159 insertions, 107 deletions
diff --git a/nova/scheduler/client/report.py b/nova/scheduler/client/report.py index 141ec37b80..f84f96e921 100644 --- a/nova/scheduler/client/report.py +++ b/nova/scheduler/client/report.py @@ -74,6 +74,40 @@ def safe_connect(f): return wrapper +def _compute_node_to_inventory_dict(compute_node): + """Given a supplied `objects.ComputeNode` object, return a dict, keyed + by resource class, of various inventory information. + + :param compute_node: `objects.ComputeNode` object to translate + """ + return { + VCPU: { + 'total': compute_node.vcpus, + 'reserved': 0, + 'min_unit': 1, + 'max_unit': 1, + 'step_size': 1, + 'allocation_ratio': compute_node.cpu_allocation_ratio, + }, + MEMORY_MB: { + 'total': compute_node.memory_mb, + 'reserved': CONF.reserved_host_memory_mb, + 'min_unit': 1, + 'max_unit': 1, + 'step_size': 1, + 'allocation_ratio': compute_node.ram_allocation_ratio, + }, + DISK_GB: { + 'total': compute_node.local_gb, + 'reserved': CONF.reserved_host_disk_mb * 1024, + 'min_unit': 1, + 'max_unit': 1, + 'step_size': 1, + 'allocation_ratio': compute_node.disk_allocation_ratio, + }, + } + + class SchedulerReportClient(object): """Client class for updating the scheduler.""" @@ -225,38 +259,6 @@ class SchedulerReportClient(object): self._resource_providers[uuid] = rp return rp - def _compute_node_inventory(self, compute_node): - inventories = { - 'VCPU': { - 'total': compute_node.vcpus, - 'reserved': 0, - 'min_unit': 1, - 'max_unit': 1, - 'step_size': 1, - 'allocation_ratio': compute_node.cpu_allocation_ratio, - }, - 'MEMORY_MB': { - 'total': compute_node.memory_mb, - 'reserved': CONF.reserved_host_memory_mb, - 'min_unit': 1, - 'max_unit': 1, - 'step_size': 1, - 'allocation_ratio': compute_node.ram_allocation_ratio, - }, - 'DISK_GB': { - 'total': compute_node.local_gb, - 'reserved': CONF.reserved_host_disk_mb * 1024, - 'min_unit': 1, - 'max_unit': 1, - 'step_size': 1, - 'allocation_ratio': compute_node.disk_allocation_ratio, - }, - } - data = { - 'inventories': inventories, - } - return data - def _get_inventory(self, compute_node): url = '/resource_providers/%s/inventories' % compute_node.uuid result = self.get(url) @@ -271,7 +273,7 @@ class SchedulerReportClient(object): :returns: True if the inventory was updated (or did not need to be), False otherwise. """ - data = self._compute_node_inventory(compute_node) + inv_data = _compute_node_to_inventory_dict(compute_node) curr = self._get_inventory(compute_node) # Update our generation immediately, if possible. Even if there @@ -288,13 +290,16 @@ class SchedulerReportClient(object): my_rp.generation = server_gen # Check to see if we need to update placement's view - if data['inventories'] == curr.get('inventories', {}): + if inv_data == curr.get('inventories', {}): return True - data['resource_provider_generation'] = ( - self._resource_providers[compute_node.uuid].generation) + cur_rp_gen = self._resource_providers[compute_node.uuid].generation + payload = { + 'resource_provider_generation': cur_rp_gen, + 'inventories': inv_data, + } url = '/resource_providers/%s/inventories' % compute_node.uuid - result = self.put(url, data) + result = self.put(url, payload) if result.status_code == 409: LOG.info(_LI('Inventory update conflict for %s'), compute_node.uuid) diff --git a/nova/tests/unit/scheduler/client/test_report.py b/nova/tests/unit/scheduler/client/test_report.py index a85bf823cd..5513fb3301 100644 --- a/nova/tests/unit/scheduler/client/test_report.py +++ b/nova/tests/unit/scheduler/client/test_report.py @@ -372,8 +372,6 @@ class SchedulerReportClientTestCase(test.NoDBTestCase): self.assertFalse(result) def test_compute_node_inventory(self): - # This is for making sure we only check once the I/O so we can directly - # call this helper method for the next tests. uuid = uuids.compute_node name = 'computehost' compute_node = objects.ComputeNode(uuid=uuid, @@ -384,15 +382,13 @@ class SchedulerReportClientTestCase(test.NoDBTestCase): ram_allocation_ratio=1.5, local_gb=10, disk_allocation_ratio=1.0) - rp = objects.ResourceProvider(uuid=uuid, name=name, generation=42) - self.client._resource_providers[uuid] = rp self.flags(reserved_host_memory_mb=1000) self.flags(reserved_host_disk_mb=2000) - result = self.client._compute_node_inventory(compute_node) + result = report._compute_node_to_inventory_dict(compute_node) - expected_inventories = { + expected = { 'VCPU': { 'total': compute_node.vcpus, 'reserved': 0, @@ -418,36 +414,75 @@ class SchedulerReportClientTestCase(test.NoDBTestCase): 'allocation_ratio': compute_node.disk_allocation_ratio, }, } - expected = { - 'inventories': expected_inventories, - } self.assertEqual(expected, result) @mock.patch('nova.scheduler.client.report.SchedulerReportClient.' + '_ensure_resource_provider') + @mock.patch('nova.scheduler.client.report.SchedulerReportClient.' + '_update_inventory_attempt') + def test_update_resource_stats_rp_fail(self, mock_ui, mock_erp): + cn = mock.MagicMock() + self.client.update_resource_stats(cn) + cn.save.assert_called_once_with() + mock_erp.assert_called_once_with(cn.uuid, cn.hypervisor_hostname) + self.assertFalse(mock_ui.called) + + @mock.patch('nova.scheduler.client.report.SchedulerReportClient.' + '_ensure_resource_provider') + @mock.patch.object(objects.ComputeNode, 'save') + def test_update_resource_stats_saves(self, mock_save, mock_ensure): + cn = objects.ComputeNode(context=self.context, + uuid=uuids.compute_node, + hypervisor_hostname='host1') + self.client.update_resource_stats(cn) + mock_save.assert_called_once_with() + mock_ensure.assert_called_once_with(uuids.compute_node, 'host1') + + +class TestInventory(SchedulerReportClientTestCase): + + def setUp(self): + super(TestInventory, self).setUp() + self.compute_node = objects.ComputeNode( + uuid=uuids.compute_node, + hypervisor_hostname='foo', + vcpus=8, + cpu_allocation_ratio=16.0, + memory_mb=1024, + ram_allocation_ratio=1.5, + local_gb=10, + disk_allocation_ratio=1.0, + ) + + @mock.patch('nova.scheduler.client.report.SchedulerReportClient.' 'get') @mock.patch('nova.scheduler.client.report.SchedulerReportClient.' 'put') - @mock.patch('nova.scheduler.client.report.SchedulerReportClient.' - '_compute_node_inventory') - def test_update_inventory(self, mock_inv, mock_put, mock_get): + def test_update_inventory(self, mock_put, mock_get): # Ensure _update_inventory() returns a list of Inventories objects # after creating or updating the existing values uuid = uuids.compute_node - compute_node = objects.ComputeNode(uuid=uuid, - hypervisor_hostname='foo') + compute_node = self.compute_node rp = objects.ResourceProvider(uuid=uuid, name='foo', generation=42) # Make sure the ResourceProvider exists for preventing to call the API self.client._resource_providers[uuid] = rp - mock_inv.return_value = {'inventories': []} mock_get.return_value.json.return_value = { 'resource_provider_generation': 43, - 'inventories': {'VCPU': {'total': 16}}, + 'inventories': { + 'VCPU': {'total': 16}, + 'MEMORY_MB': {'total': 1024}, + 'DISK_GB': {'total': 10}, + } } mock_put.return_value.status_code = 200 mock_put.return_value.json.return_value = { 'resource_provider_generation': 44, - 'inventories': {'VCPU': {'total': 16}}, + 'inventories': { + 'VCPU': {'total': 16}, + 'MEMORY_MB': {'total': 1024}, + 'DISK_GB': {'total': 10}, + } } result = self.client._update_inventory_attempt(compute_node) @@ -455,32 +490,77 @@ class SchedulerReportClientTestCase(test.NoDBTestCase): exp_url = '/resource_providers/%s/inventories' % uuid mock_get.assert_called_once_with(exp_url) - # Called with the newly-found generation from the existing inventory - self.assertEqual(43, - mock_inv.return_value['resource_provider_generation']) # Updated with the new inventory from the PUT call self.assertEqual(44, rp.generation) - mock_put.assert_called_once_with(exp_url, mock_inv.return_value) + expected = { + # Called with the newly-found generation from the existing + # inventory + 'resource_provider_generation': 43, + 'inventories': { + 'VCPU': { + 'total': 8, + 'reserved': 0, + 'min_unit': 1, + 'max_unit': 1, + 'step_size': 1, + 'allocation_ratio': compute_node.cpu_allocation_ratio, + }, + 'MEMORY_MB': { + 'total': 1024, + 'reserved': CONF.reserved_host_memory_mb, + 'min_unit': 1, + 'max_unit': 1, + 'step_size': 1, + 'allocation_ratio': compute_node.ram_allocation_ratio, + }, + 'DISK_GB': { + 'total': 10, + 'reserved': CONF.reserved_host_disk_mb * 1024, + 'min_unit': 1, + 'max_unit': 1, + 'step_size': 1, + 'allocation_ratio': compute_node.disk_allocation_ratio, + }, + } + } + mock_put.assert_called_once_with(exp_url, expected) @mock.patch('nova.scheduler.client.report.SchedulerReportClient.' 'get') @mock.patch('nova.scheduler.client.report.SchedulerReportClient.' 'put') - @mock.patch('nova.scheduler.client.report.SchedulerReportClient.' - '_compute_node_inventory') - def test_update_inventory_no_update(self, mock_inv, mock_put, mock_get): + def test_update_inventory_no_update(self, mock_put, mock_get): uuid = uuids.compute_node - compute_node = objects.ComputeNode(uuid=uuid, - hypervisor_hostname='foo') + compute_node = self.compute_node rp = objects.ResourceProvider(uuid=uuid, name='foo', generation=42) self.client._resource_providers[uuid] = rp - mock_inv.return_value = {'inventories': { - 'VCPU': {'total': 8}, - }} mock_get.return_value.json.return_value = { 'resource_provider_generation': 43, 'inventories': { - 'VCPU': {'total': 8} + 'VCPU': { + 'total': 8, + 'reserved': 0, + 'min_unit': 1, + 'max_unit': 1, + 'step_size': 1, + 'allocation_ratio': compute_node.cpu_allocation_ratio, + }, + 'MEMORY_MB': { + 'total': 1024, + 'reserved': CONF.reserved_host_memory_mb, + 'min_unit': 1, + 'max_unit': 1, + 'step_size': 1, + 'allocation_ratio': compute_node.ram_allocation_ratio, + }, + 'DISK_GB': { + 'total': 10, + 'reserved': CONF.reserved_host_disk_mb * 1024, + 'min_unit': 1, + 'max_unit': 1, + 'step_size': 1, + 'allocation_ratio': compute_node.disk_allocation_ratio, + }, } } result = self.client._update_inventory_attempt(compute_node) @@ -497,21 +577,17 @@ class SchedulerReportClientTestCase(test.NoDBTestCase): @mock.patch('nova.scheduler.client.report.SchedulerReportClient.' 'put') @mock.patch('nova.scheduler.client.report.SchedulerReportClient.' - '_compute_node_inventory') - @mock.patch('nova.scheduler.client.report.SchedulerReportClient.' '_ensure_resource_provider') - def test_update_inventory_conflicts(self, mock_ensure, mock_inv, + def test_update_inventory_conflicts(self, mock_ensure, mock_put, mock_get): # Ensure _update_inventory() returns a list of Inventories objects # after creating or updating the existing values uuid = uuids.compute_node - compute_node = objects.ComputeNode(uuid=uuid, - hypervisor_hostname='foo') + compute_node = self.compute_node rp = objects.ResourceProvider(uuid=uuid, name='foo', generation=42) # Make sure the ResourceProvider exists for preventing to call the API self.client._resource_providers[uuid] = rp - mock_inv.return_value = {'inventories': [{'resource_class': 'VCPU'}]} mock_get.return_value = {} mock_put.return_value.status_code = 409 @@ -527,20 +603,15 @@ class SchedulerReportClientTestCase(test.NoDBTestCase): '_get_inventory') @mock.patch('nova.scheduler.client.report.SchedulerReportClient.' 'put') - @mock.patch('nova.scheduler.client.report.SchedulerReportClient.' - '_compute_node_inventory') - def test_update_inventory_unknown_response(self, mock_inv, - mock_put, mock_get): + def test_update_inventory_unknown_response(self, mock_put, mock_get): # Ensure _update_inventory() returns a list of Inventories objects # after creating or updating the existing values uuid = uuids.compute_node - compute_node = objects.ComputeNode(uuid=uuid, - hypervisor_hostname='foo') + compute_node = self.compute_node rp = objects.ResourceProvider(uuid=uuid, name='foo', generation=42) # Make sure the ResourceProvider exists for preventing to call the API self.client._resource_providers[uuid] = rp - mock_inv.return_value = {'inventories': [{'resource_class': 'VCPU'}]} mock_get.return_value = {} mock_put.return_value.status_code = 234 @@ -554,20 +625,15 @@ class SchedulerReportClientTestCase(test.NoDBTestCase): '_get_inventory') @mock.patch('nova.scheduler.client.report.SchedulerReportClient.' 'put') - @mock.patch('nova.scheduler.client.report.SchedulerReportClient.' - '_compute_node_inventory') - def test_update_inventory_failed(self, mock_inv, - mock_put, mock_get): + def test_update_inventory_failed(self, mock_put, mock_get): # Ensure _update_inventory() returns a list of Inventories objects # after creating or updating the existing values uuid = uuids.compute_node - compute_node = objects.ComputeNode(uuid=uuid, - hypervisor_hostname='foo') + compute_node = self.compute_node rp = objects.ResourceProvider(uuid=uuid, name='foo', generation=42) # Make sure the ResourceProvider exists for preventing to call the API self.client._resource_providers[uuid] = rp - mock_inv.return_value = {'inventories': [{'resource_class': 'VCPU'}]} mock_get.return_value = {} try: mock_put.return_value.__nonzero__.return_value = False @@ -627,27 +693,8 @@ class SchedulerReportClientTestCase(test.NoDBTestCase): # Slept three times mock_sleep.assert_has_calls([mock.call(1), mock.call(1), mock.call(1)]) - @mock.patch('nova.scheduler.client.report.SchedulerReportClient.' - '_ensure_resource_provider') - @mock.patch('nova.scheduler.client.report.SchedulerReportClient.' - '_update_inventory_attempt') - def test_update_resource_stats_rp_fail(self, mock_ui, mock_erp): - cn = mock.MagicMock() - self.client.update_resource_stats(cn) - cn.save.assert_called_once_with() - mock_erp.assert_called_once_with(cn.uuid, cn.hypervisor_hostname) - self.assertFalse(mock_ui.called) - @mock.patch('nova.scheduler.client.report.SchedulerReportClient.' - '_ensure_resource_provider') - @mock.patch.object(objects.ComputeNode, 'save') - def test_update_resource_stats_saves(self, mock_save, mock_ensure): - cn = objects.ComputeNode(context=self.context, - uuid=uuids.compute_node, - hypervisor_hostname='host1') - self.client.update_resource_stats(cn) - mock_save.assert_called_once_with() - mock_ensure.assert_called_once_with(uuids.compute_node, 'host1') +class TestAllocations(SchedulerReportClientTestCase): @mock.patch('nova.compute.utils.is_volume_backed_instance') def test_allocations(self, mock_vbi): |