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:
Nikola Dipanov 2014-11-18 20:45:28 +01:00
parent b7eff237f1
commit a59e1a9c7e
3 changed files with 51 additions and 2 deletions

View File

@ -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.

View File

@ -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(

View File

@ -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']