diff --git a/nova/conductor/tasks/migrate.py b/nova/conductor/tasks/migrate.py index b2a8e08f2d90..9835774f2fab 100644 --- a/nova/conductor/tasks/migrate.py +++ b/nova/conductor/tasks/migrate.py @@ -9,6 +9,7 @@ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. +import functools from oslo_log import log as logging from oslo_serialization import jsonutils @@ -292,7 +293,17 @@ class MigrationTask(base.TaskBase): # oslo.messaging #1529084 to transform datetime values into strings. # tl;dr: datetimes in dicts are not accepted as correct values by the # rpc fake driver. - legacy_spec = jsonutils.loads(jsonutils.dumps(legacy_spec)) + # NOTE(gibi): convert_instances=True is needed as the legacy_spec might + # contain ovo instances in the numa_topology field and those are + # causing circular reference during serialization otherwise. + legacy_spec = jsonutils.loads( + jsonutils.dumps( + legacy_spec, + default=functools.partial( + jsonutils.to_primitive, convert_instances=True + ), + ) + ) LOG.debug("Calling prep_resize with selected host: %s; " "Selected node: %s; Alternates: %s", host, node, diff --git a/nova/tests/unit/conductor/tasks/test_migrate.py b/nova/tests/unit/conductor/tasks/test_migrate.py index ff10779c59ef..47bac4ae0a08 100644 --- a/nova/tests/unit/conductor/tasks/test_migrate.py +++ b/nova/tests/unit/conductor/tasks/test_migrate.py @@ -10,8 +10,11 @@ # License for the specific language governing permissions and limitations # under the License. +import functools import mock +from oslo_serialization import jsonutils + from nova.compute import rpcapi as compute_rpcapi from nova.conductor.tasks import migrate from nova import context @@ -123,7 +126,14 @@ class MigrationTaskTestCase(test.NoDBTestCase): self.request_spec.requested_destination) task = self._generate_task() - legacy_request_spec = self.request_spec.to_legacy_request_spec_dict() + legacy_request_spec = jsonutils.loads( + jsonutils.dumps( + self.request_spec.to_legacy_request_spec_dict(), + default=functools.partial( + jsonutils.to_primitive, convert_instances=True + ), + ) + ) gmv_mock.return_value = 23 # We just need this hook point to set a uuid on the @@ -230,6 +240,18 @@ class MigrationTaskTestCase(test.NoDBTestCase): task.instance, task._migration, task._held_allocations) + def test_execute_with_cpu_topoloy(self): + self.request_spec = objects.RequestSpec( + numa_topology=objects.InstanceNUMATopology( + cells=[ + objects.InstanceNUMACell( + cpu_topology=objects.VirtCPUTopology() + ) + ] + ) + ) + self._test_execute() + class MigrationTaskAllocationUtils(test.NoDBTestCase): @mock.patch('nova.objects.ComputeNode.get_by_host_and_nodename')