RT: Decrese usage for offloaded instances
Allow for update_usage to consider SHELVED_OFFLOADED instances as removed and update the resource usage accordingly. This means we want to make sure that the stats class does the same. We can now make sure that RT is updated immediately once the instance has been shelved offloaded. Change-Id: Ia22963021995c71758a18b21070dfdf6a950da09 Partial-bug: #1545675
This commit is contained in:
parent
dbdf27021c
commit
a54997c62f
|
@ -4291,6 +4291,9 @@ class ComputeManager(manager.Manager):
|
|||
instance.task_state = None
|
||||
instance.save(expected_task_state=[task_states.SHELVING,
|
||||
task_states.SHELVING_OFFLOADING])
|
||||
# NOTE(ndipanov): This frees the resources with the resource_tracker
|
||||
self._update_resource_tracker(context, instance)
|
||||
|
||||
self._delete_scheduler_instance_info(context, instance.uuid)
|
||||
self._notify_about_instance_usage(context, instance,
|
||||
'shelve_offload.end')
|
||||
|
|
|
@ -126,6 +126,9 @@ def _instance_in_resize_state(instance):
|
|||
return False
|
||||
|
||||
|
||||
_REMOVED_STATES = (vm_states.DELETED, vm_states.SHELVED_OFFLOADED)
|
||||
|
||||
|
||||
class ResourceTracker(object):
|
||||
"""Compute helper class for keeping track of resource usage as instances
|
||||
are built and destroyed.
|
||||
|
@ -853,20 +856,20 @@ class ResourceTracker(object):
|
|||
|
||||
uuid = instance['uuid']
|
||||
is_new_instance = uuid not in self.tracked_instances
|
||||
is_deleted_instance = instance['vm_state'] == vm_states.DELETED
|
||||
is_removed_instance = instance['vm_state'] in _REMOVED_STATES
|
||||
|
||||
if is_new_instance:
|
||||
self.tracked_instances[uuid] = obj_base.obj_to_primitive(instance)
|
||||
sign = 1
|
||||
|
||||
if is_deleted_instance:
|
||||
if is_removed_instance:
|
||||
self.tracked_instances.pop(uuid)
|
||||
sign = -1
|
||||
|
||||
self.stats.update_stats_for_instance(instance)
|
||||
|
||||
# if it's a new or deleted instance:
|
||||
if is_new_instance or is_deleted_instance:
|
||||
if is_new_instance or is_removed_instance:
|
||||
if self.pci_tracker:
|
||||
self.pci_tracker.update_pci_for_instance(context,
|
||||
instance,
|
||||
|
@ -905,7 +908,7 @@ class ResourceTracker(object):
|
|||
self.driver)
|
||||
|
||||
for instance in instances:
|
||||
if instance.vm_state != vm_states.DELETED:
|
||||
if instance.vm_state not in _REMOVED_STATES:
|
||||
self._update_usage_from_instance(context, instance)
|
||||
|
||||
def _find_orphaned_instances(self):
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from nova.compute import resource_tracker
|
||||
from nova.compute import task_states
|
||||
from nova.compute import vm_states
|
||||
from nova.i18n import _
|
||||
|
@ -105,7 +106,7 @@ class Stats(dict):
|
|||
(vm_state, task_state, os_type, project_id) = \
|
||||
self._extract_state_from_instance(instance)
|
||||
|
||||
if vm_state == vm_states.DELETED:
|
||||
if vm_state in resource_tracker._REMOVED_STATES:
|
||||
self._decrement("num_instances")
|
||||
self.states.pop(uuid)
|
||||
|
||||
|
|
|
@ -148,6 +148,7 @@ class ShelveComputeManagerTestCase(test_compute.BaseTestCase):
|
|||
self.mox.StubOutWithMock(self.compute, '_get_power_state')
|
||||
self.mox.StubOutWithMock(self.compute.network_api,
|
||||
'cleanup_instance_network_on_host')
|
||||
self.mox.StubOutWithMock(self.compute, '_update_resource_tracker')
|
||||
|
||||
self.compute._notify_about_instance_usage(self.context, instance,
|
||||
'shelve_offload.start')
|
||||
|
@ -161,6 +162,7 @@ class ShelveComputeManagerTestCase(test_compute.BaseTestCase):
|
|||
self.context, instance, instance.host)
|
||||
self.compute._get_power_state(self.context,
|
||||
instance).AndReturn(123)
|
||||
self.compute._update_resource_tracker(self.context, instance)
|
||||
self.compute._notify_about_instance_usage(self.context, instance,
|
||||
'shelve_offload.end')
|
||||
self.mox.ReplayAll()
|
||||
|
|
|
@ -195,6 +195,19 @@ class StatsTestCase(test.NoDBTestCase):
|
|||
self.assertEqual(0, self.stats.num_os_type("Linux"))
|
||||
self.assertEqual(0, self.stats["num_vm_" + vm_states.BUILDING])
|
||||
|
||||
def test_update_stats_for_instance_offloaded(self):
|
||||
instance = self._create_instance()
|
||||
self.stats.update_stats_for_instance(instance)
|
||||
self.assertEqual(1, self.stats["num_proj_1234"])
|
||||
|
||||
instance["vm_state"] = vm_states.SHELVED_OFFLOADED
|
||||
self.stats.update_stats_for_instance(instance)
|
||||
|
||||
self.assertEqual(0, self.stats.num_instances)
|
||||
self.assertEqual(0, self.stats.num_instances_for_project("1234"))
|
||||
self.assertEqual(0, self.stats.num_os_type("Linux"))
|
||||
self.assertEqual(0, self.stats["num_vm_" + vm_states.BUILDING])
|
||||
|
||||
def test_io_workload(self):
|
||||
vms = [vm_states.ACTIVE, vm_states.BUILDING, vm_states.PAUSED]
|
||||
tasks = [task_states.RESIZE_MIGRATING, task_states.REBUILDING,
|
||||
|
|
|
@ -1218,6 +1218,40 @@ class TestInstanceClaim(BaseTestCase):
|
|||
self.assertTrue(obj_base.obj_equal_prims(expected,
|
||||
self.rt.compute_node))
|
||||
|
||||
@mock.patch('nova.objects.InstancePCIRequests.get_by_instance_uuid')
|
||||
@mock.patch('nova.objects.MigrationList.get_in_progress_by_host_and_node')
|
||||
def test_update_usage_removed(self, migr_mock, pci_mock):
|
||||
# Test that RT.update_usage() removes the instance when update is
|
||||
# called in a removed state
|
||||
pci_mock.return_value = objects.InstancePCIRequests(requests=[])
|
||||
|
||||
expected = copy.deepcopy(_COMPUTE_NODE_FIXTURES[0])
|
||||
disk_used = self.instance.root_gb + self.instance.ephemeral_gb
|
||||
expected.update({
|
||||
'local_gb_used': disk_used,
|
||||
'memory_mb_used': self.instance.memory_mb,
|
||||
'free_disk_gb': expected['local_gb'] - disk_used,
|
||||
"free_ram_mb": expected['memory_mb'] - self.instance.memory_mb,
|
||||
'running_vms': 1,
|
||||
'vcpus_used': 1,
|
||||
'pci_device_pools': objects.PciDevicePoolList(),
|
||||
})
|
||||
with mock.patch.object(self.rt, '_update') as update_mock:
|
||||
with mock.patch.object(self.instance, 'save'):
|
||||
self.rt.instance_claim(self.ctx, self.instance, None)
|
||||
update_mock.assert_called_once_with(self.elevated)
|
||||
self.assertTrue(obj_base.obj_equal_prims(expected,
|
||||
self.rt.compute_node))
|
||||
|
||||
expected_updated = copy.deepcopy(_COMPUTE_NODE_FIXTURES[0])
|
||||
expected_updated['pci_device_pools'] = objects.PciDevicePoolList()
|
||||
|
||||
self.instance.vm_state = vm_states.SHELVED_OFFLOADED
|
||||
with mock.patch.object(self.rt, '_update') as update_mock:
|
||||
self.rt.update_usage(self.ctx, self.instance)
|
||||
self.assertTrue(obj_base.obj_equal_prims(expected_updated,
|
||||
self.rt.compute_node))
|
||||
|
||||
@mock.patch('nova.objects.InstancePCIRequests.get_by_instance_uuid')
|
||||
@mock.patch('nova.objects.MigrationList.get_in_progress_by_host_and_node')
|
||||
def test_claim(self, migr_mock, pci_mock):
|
||||
|
|
Loading…
Reference in New Issue