Make Instance.save() update numa_topology
This is needed so that we can actually update the given topology with the updated data after a successful claim. Deleting it will also be needed when we actually make the resize work properly for instances with NUMA topology, so we add it here as well. We do not expose the new InstanceNUMATopology methods as @remotable to avoid having to bump the object version thus making this an easier backport target. This is OK since they are only called from Instance.save() which is @remotable, and can be trivially made remotable should this be needed later (causing a version bump that need not be backported). Change-Id: I64ff2d00ca20bd065bb17ebaa9c40b64b8cbb817 Partial-bug: #1386236
This commit is contained in:
parent
b7eff237f1
commit
a59e1a9c7e
|
@ -424,8 +424,12 @@ class Instance(base.NovaPersistentObject, base.NovaObject):
|
|||
pass
|
||||
|
||||
def _save_numa_topology(self, context):
|
||||
# NOTE(ndipanov): No need for this yet.
|
||||
pass
|
||||
if self.numa_topology:
|
||||
self.numa_topology.instance_uuid = self.uuid
|
||||
self.numa_topology._save(context)
|
||||
else:
|
||||
objects.InstanceNUMATopology.delete_by_instance_uuid(
|
||||
context, self.uuid)
|
||||
|
||||
def _save_pci_requests(self, context):
|
||||
# NOTE(danms): No need for this yet.
|
||||
|
|
|
@ -85,6 +85,7 @@ class InstanceNUMATopology(base.NovaObject):
|
|||
cells.append(cell)
|
||||
return hardware.VirtNUMAInstanceTopology(cells=cells)
|
||||
|
||||
# TODO(ndipanov) Remove this method on the major version bump to 2.0
|
||||
@base.remotable
|
||||
def create(self, context):
|
||||
topology = self.topology_from_obj()
|
||||
|
@ -95,6 +96,27 @@ class InstanceNUMATopology(base.NovaObject):
|
|||
values)
|
||||
self.obj_reset_changes()
|
||||
|
||||
# NOTE(ndipanov): We can't rename create and want to avoid version bump
|
||||
# as this needs to be backported to stable so this is not a @remotable
|
||||
# That's OK since we only call it from inside Instance.save() which is.
|
||||
def _save(self, context):
|
||||
topology = self.topology_from_obj()
|
||||
if not topology:
|
||||
return
|
||||
values = {'numa_topology': topology.to_json()}
|
||||
db.instance_extra_update_by_uuid(context, self.instance_uuid,
|
||||
values)
|
||||
self.obj_reset_changes()
|
||||
|
||||
# NOTE(ndipanov): We want to avoid version bump
|
||||
# as this needs to be backported to stable so this is not a @remotable
|
||||
# That's OK since we only call it from inside Instance.save() which is.
|
||||
@classmethod
|
||||
def delete_by_instance_uuid(cls, context, instance_uuid):
|
||||
values = {'numa_topology': None}
|
||||
db.instance_extra_update_by_uuid(context, instance_uuid,
|
||||
values)
|
||||
|
||||
@base.remotable_classmethod
|
||||
def get_by_instance_uuid(cls, context, instance_uuid):
|
||||
db_extra = db.instance_extra_get_by_instance_uuid(
|
||||
|
|
|
@ -30,6 +30,7 @@ from nova import notifications
|
|||
from nova import objects
|
||||
from nova.objects import instance
|
||||
from nova.objects import instance_info_cache
|
||||
from nova.objects import instance_numa_topology
|
||||
from nova.objects import pci_device
|
||||
from nova.objects import security_group
|
||||
from nova import test
|
||||
|
@ -413,6 +414,28 @@ class _TestInstanceObject(object):
|
|||
self.assertNotIn('pci_devices',
|
||||
mock_fdo.call_args_list[0][1]['expected_attrs'])
|
||||
|
||||
@mock.patch('nova.db.instance_extra_update_by_uuid')
|
||||
@mock.patch('nova.db.instance_update_and_get_original')
|
||||
@mock.patch('nova.objects.Instance._from_db_object')
|
||||
def test_save_updates_numa_topology(self, mock_fdo, mock_update,
|
||||
mock_extra_update):
|
||||
mock_update.return_value = None, None
|
||||
inst = instance.Instance(
|
||||
context=self.context, id=123, uuid='fake-uuid')
|
||||
inst.numa_topology = (
|
||||
instance_numa_topology.InstanceNUMATopology.obj_from_topology(
|
||||
test_instance_numa_topology.fake_numa_topology))
|
||||
inst.save()
|
||||
mock_extra_update.assert_called_once_with(
|
||||
self.context, inst.uuid,
|
||||
{'numa_topology':
|
||||
test_instance_numa_topology.fake_numa_topology.to_json()})
|
||||
mock_extra_update.reset_mock()
|
||||
inst.numa_topology = None
|
||||
inst.save()
|
||||
mock_extra_update.assert_called_once_with(
|
||||
self.context, inst.uuid, {'numa_topology': None})
|
||||
|
||||
def test_get_deleted(self):
|
||||
fake_inst = dict(self.fake_instance, id=123, deleted=123)
|
||||
fake_uuid = fake_inst['uuid']
|
||||
|
|
Loading…
Reference in New Issue