Skip to content

Commit

Permalink
Fix migrate single instance when it was created concurrently
Browse files Browse the repository at this point in the history
When a multiple-instance creation is requested by the user, we create a
single RequestSpec per instance (each of them having the corresponding
instance UUID) but we keep track of how many concurrent instances were
created at once by updating a field named 'num_instances' and we persist
it.

Unfortunately, due to Ifc5cf482209e4f6f4e3e39b24389bd3563d86444 we now
lookup that field in the scheduler for knowing how many allocations to
do. Since a move operation will only pass a single instance UUID to
migrate to the scheduler, there is a discrepancy that can lead to an
ugly IndexError. Defaulting that loop to be what is passed over RPC
unless we don't have it and then we default back to what we know from
the RequestSpec record.

Change-Id: If7da79356174be57481ef246618221e3b2ff8200
Closes-Bug: #1708961
  • Loading branch information
sbauza authored and EdLeafe committed Aug 7, 2017
1 parent 5971dde commit 2bd7df8
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 6 deletions.
11 changes: 8 additions & 3 deletions nova/scheduler/filter_scheduler.py
Expand Up @@ -117,8 +117,7 @@ def _schedule(self, context, spec_obj, instance_uuids,
:param context: The RequestContext object
:param spec_obj: The RequestSpec object
:param instance_uuids: List of UUIDs, one for each value of the spec
object's num_instances attribute
:param instance_uuids: List of instance UUIDs to place or move.
:param alloc_reqs_by_rp_uuid: Optional dict, keyed by resource provider
UUID, of the allocation requests that may
be used to claim resources against
Expand Down Expand Up @@ -159,7 +158,13 @@ def _schedule(self, context, spec_obj, instance_uuids,
claimed_instance_uuids = []

selected_hosts = []
num_instances = spec_obj.num_instances

# NOTE(sbauza): The RequestSpec.num_instances field contains the number
# of instances created when the RequestSpec was used to first boot some
# instances. This is incorrect when doing a move or resize operation,
# so prefer the length of instance_uuids unless it is None.
num_instances = (len(instance_uuids) if instance_uuids
else spec_obj.num_instances)
for num in range(num_instances):
hosts = self._get_sorted_hosts(spec_obj, hosts, num)
if not hosts:
Expand Down
16 changes: 13 additions & 3 deletions nova/tests/unit/scheduler/test_filter_scheduler.py
Expand Up @@ -147,10 +147,10 @@ def test_schedule_old_conductor(self, mock_get_hosts,
'_get_all_host_states')
@mock.patch('nova.scheduler.filter_scheduler.FilterScheduler.'
'_get_sorted_hosts')
def test_schedule_successful_claim(self, mock_get_hosts,
mock_get_all_states, mock_claim):
def _test_schedule_successful_claim(self, mock_get_hosts,
mock_get_all_states, mock_claim, num_instances=1):
spec_obj = objects.RequestSpec(
num_instances=1,
num_instances=num_instances,
flavor=objects.Flavor(memory_mb=512,
root_gb=512,
ephemeral_gb=0,
Expand Down Expand Up @@ -188,6 +188,16 @@ def test_schedule_successful_claim(self, mock_get_hosts,
# Ensure that we have consumed the resources on the chosen host states
host_state.consume_from_request.assert_called_once_with(spec_obj)

def test_schedule_successful_claim(self):
self._test_schedule_successful_claim()

def test_schedule_old_reqspec_and_move_operation(self):
"""This test is for verifying that in case of a move operation with an
original RequestSpec created for 3 concurrent instances, we only verify
the instance that is moved.
"""
self._test_schedule_successful_claim(num_instances=3)

@mock.patch('nova.scheduler.filter_scheduler.FilterScheduler.'
'_cleanup_allocations')
@mock.patch('nova.scheduler.filter_scheduler.FilterScheduler.'
Expand Down

0 comments on commit 2bd7df8

Please sign in to comment.