From f5e35dcfe8ee586106438bcfa551426babc75bf6 Mon Sep 17 00:00:00 2001 From: Sylvain Bauza Date: Thu, 17 Sep 2015 17:51:06 +0200 Subject: [PATCH] Correct memory validation for live migration Since live migration has been moved to the conductor, there was no possibility for the conductor to verify if the destination had enough RAM just because it didn't know the allocation ratios given by the scheduler. Now that ComputeNodes provide a ram_allocation_field, we can fix that check and provide the same validation than RAMFilter to make sure that the destination is good. Closes-Bug: #1451831 Closes-Bug: #1214943 Change-Id: Ie6c768fc915553da73160ea51961078bfbacec77 --- nova/conductor/tasks/live_migrate.py | 10 +++++++++- .../unit/conductor/tasks/test_live_migrate.py | 20 +++++++++++++------ 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/nova/conductor/tasks/live_migrate.py b/nova/conductor/tasks/live_migrate.py index 13d2344d02f9..b46b37209c9e 100644 --- a/nova/conductor/tasks/live_migrate.py +++ b/nova/conductor/tasks/live_migrate.py @@ -110,9 +110,17 @@ class LiveMigrationTask(base.TaskBase): instance_id=self.instance.uuid, host=self.destination) def _check_destination_has_enough_memory(self): - avail = self._get_compute_info(self.destination)['free_ram_mb'] + compute = self._get_compute_info(self.destination) + free_ram_mb = compute.free_ram_mb + total_ram_mb = compute.memory_mb mem_inst = self.instance.memory_mb + # NOTE(sbauza): Now the ComputeNode object reports an allocation ratio + # that can be provided by the compute_node if new or by the controller + ram_ratio = compute.ram_allocation_ratio + # NOTE(sbauza): Mimic the RAMFilter logic in order to have the same + # ram validation + avail = total_ram_mb * ram_ratio - (total_ram_mb - free_ram_mb) if not mem_inst or avail <= mem_inst: instance_uuid = self.instance.uuid dest = self.destination diff --git a/nova/tests/unit/conductor/tasks/test_live_migrate.py b/nova/tests/unit/conductor/tasks/test_live_migrate.py index ca49966b74b9..a5f66d29d810 100644 --- a/nova/tests/unit/conductor/tasks/test_live_migrate.py +++ b/nova/tests/unit/conductor/tasks/test_live_migrate.py @@ -150,11 +150,13 @@ class LiveMigrationTaskTestCase(test.NoDBTestCase): objects.Service.get_by_compute_host( self.context, self.destination).AndReturn("service") self.task.servicegroup_api.service_is_up("service").AndReturn(True) - hypervisor_details = { - "hypervisor_type": "a", - "hypervisor_version": 6.1, - "free_ram_mb": 513 - } + hypervisor_details = objects.ComputeNode( + hypervisor_type="a", + hypervisor_version=6.1, + free_ram_mb=513, + memory_mb=512, + ram_allocation_ratio=1.0, + ) self.task._get_compute_info(self.destination)\ .AndReturn(hypervisor_details) self.task._get_compute_info(self.instance_host)\ @@ -194,9 +196,15 @@ class LiveMigrationTaskTestCase(test.NoDBTestCase): self.task._check_host_is_up(self.destination) objects.ComputeNode.get_first_node_by_host_for_old_compat(self.context, - self.destination).AndReturn({"free_ram_mb": 511}) + self.destination).AndReturn( + objects.ComputeNode(free_ram_mb=513, + memory_mb=1024, + ram_allocation_ratio=0.9, + )) self.mox.ReplayAll() + # free_ram is bigger than instance.ram (512) but the allocation ratio + # reduces the total available RAM to 410MB (1024 * 0.9 - (1024 - 513)) self.assertRaises(exception.MigrationPreCheckError, self.task._check_requested_destination)