objects: make instance numa topology versioned in db

Makes data stored in the database for numa topology
versioned by using object framework.

Change-Id: I0e8ca96296fb88aa7a26fae1e476275a23e0c6bb
This commit is contained in:
Sahid Orentino Ferdjaoui
2014-11-18 04:11:51 -05:00
parent 94aedacfd2
commit 4f6dbc2796
4 changed files with 69 additions and 44 deletions
+1 -2
View File
@@ -376,8 +376,7 @@ class Instance(base.NovaPersistentObject, base.NovaObject):
numa_topology = updates.pop('numa_topology', None)
if numa_topology:
expected_attrs.append('numa_topology')
updates['extra']['numa_topology'] = (
numa_topology.topology_from_obj().to_json())
updates['extra']['numa_topology'] = numa_topology._to_json()
pci_requests = updates.pop('pci_requests', None)
if pci_requests:
expected_attrs.append('pci_requests')
+20 -18
View File
@@ -12,6 +12,8 @@
# License for the specific language governing permissions and limitations
# under the License.
from oslo.serialization import jsonutils
from nova import db
from nova import exception
from nova.objects import base
@@ -47,13 +49,19 @@ class InstanceNUMATopology(base.NovaObject):
@classmethod
def obj_from_db_obj(cls, instance_uuid, db_obj):
topo = hardware.VirtNUMAInstanceTopology.from_json(db_obj)
obj_topology = cls.obj_from_topology(topo)
obj_topology.instance_uuid = instance_uuid
# NOTE (ndipanov) not really needed as we never save, but left for
# consistency
obj_topology.id = 0
obj_topology.obj_reset_changes()
if 'nova_object.name' in db_obj:
obj_topology = cls.obj_from_primitive(
jsonutils.loads(db_obj))
else:
# NOTE(sahid): This compatibility code needs to stay until we can
# guarantee that there are no cases of the old format stored in
# the database (or forever, if we can never guarantee that).
topo = hardware.VirtNUMAInstanceTopology.from_json(db_obj)
obj_topology = cls.obj_from_topology(topo)
obj_topology.instance_uuid = instance_uuid
# No benefit to store a list of changed fields
obj_topology.obj_reset_changes()
return obj_topology
@classmethod
@@ -81,22 +89,13 @@ class InstanceNUMATopology(base.NovaObject):
# TODO(ndipanov) Remove this method on the major version bump to 2.0
@base.remotable
def create(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()
self._save(context)
# 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()}
values = {'numa_topology': self._to_json()}
db.instance_extra_update_by_uuid(context, self.instance_uuid,
values)
self.obj_reset_changes()
@@ -121,3 +120,6 @@ class InstanceNUMATopology(base.NovaObject):
return None
return cls.obj_from_db_obj(instance_uuid, db_extra['numa_topology'])
def _to_json(self):
return jsonutils.dumps(self.obj_to_primitive())
+15 -15
View File
@@ -30,7 +30,6 @@ 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
@@ -419,17 +418,19 @@ class _TestInstanceObject(object):
@mock.patch('nova.objects.Instance._from_db_object')
def test_save_updates_numa_topology(self, mock_fdo, mock_update,
mock_extra_update):
fake_obj_numa_topology = objects.InstanceNUMATopology(cells=[
objects.InstanceNUMACell(id=0, cpuset=set([0]), memory=128),
objects.InstanceNUMACell(id=1, cpuset=set([1]), memory=128)])
fake_obj_numa_topology.instance_uuid = 'fake-uuid'
jsonified = fake_obj_numa_topology._to_json()
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.numa_topology = fake_obj_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()})
self.context, inst.uuid, {'numa_topology': jsonified})
mock_extra_update.reset_mock()
inst.numa_topology = None
inst.save()
@@ -707,19 +708,18 @@ class _TestInstanceObject(object):
def test_create_with_extras(self):
inst = instance.Instance(uuid=self.fake_instance['uuid'],
numa_topology=objects.InstanceNUMATopology.obj_from_topology(
test_instance_numa_topology.fake_numa_topology),
pci_requests=objects.InstancePCIRequests(
requests=[
objects.InstancePCIRequest(count=123,
spec=[])]))
numa_topology=test_instance_numa_topology.fake_obj_numa_topology,
pci_requests=objects.InstancePCIRequests(
requests=[
objects.InstancePCIRequest(count=123,
spec=[])]))
inst.create(self.context)
self.assertIsNotNone(inst.numa_topology)
self.assertIsNotNone(inst.pci_requests)
got_numa_topo = objects.InstanceNUMATopology.get_by_instance_uuid(
self.context, inst.uuid)
self.assertEqual(inst.numa_topology.id, got_numa_topo.id)
self.assertEqual(inst.numa_topology.instance_uuid,
got_numa_topo.instance_uuid)
got_pci_requests = objects.InstancePCIRequests.get_by_instance_uuid(
self.context, inst.uuid)
self.assertEqual(123, got_pci_requests.requests[0].count)
@@ -19,11 +19,16 @@ from nova import objects
from nova.tests.unit.objects import test_objects
from nova.virt import hardware
fake_instance_uuid = str(uuid.uuid4())
fake_numa_topology = hardware.VirtNUMAInstanceTopology(
cells=[hardware.VirtNUMATopologyCellInstance(
0, set([1, 2]), 512, 2048),
hardware.VirtNUMATopologyCellInstance(
1, set([3, 4]), 512, 2048)])
cells=[hardware.VirtNUMATopologyCellInstance(
0, set([1, 2]), 512, 2048),
hardware.VirtNUMATopologyCellInstance(
1, set([3, 4]), 512, 2048)])
fake_obj_numa_topology = objects.InstanceNUMATopology.obj_from_topology(
fake_numa_topology)
fake_obj_numa_topology.instance_uuid = fake_instance_uuid
fake_db_topology = {
'created_at': None,
@@ -31,10 +36,13 @@ fake_db_topology = {
'deleted_at': None,
'deleted': 0,
'id': 1,
'instance_uuid': str(uuid.uuid4()),
'numa_topology': fake_numa_topology.to_json()
'instance_uuid': fake_instance_uuid,
'numa_topology': fake_obj_numa_topology._to_json()
}
fake_old_db_topology = dict(fake_db_topology) # copy
fake_old_db_topology['numa_topology'] = fake_numa_topology.to_json()
class _TestInstanceNUMATopology(object):
@mock.patch('nova.db.instance_extra_update_by_uuid')
@@ -45,9 +53,15 @@ class _TestInstanceNUMATopology(object):
topo_obj.create(self.context)
self.assertEqual(1, len(mock_update.call_args_list))
@mock.patch('nova.db.instance_extra_get_by_instance_uuid')
def test_get_by_instance_uuid(self, mock_get):
mock_get.return_value = fake_db_topology
@mock.patch('nova.db.instance_extra_update_by_uuid')
def test_save(self, mock_update):
topo_obj = objects.InstanceNUMATopology.obj_from_topology(
fake_numa_topology)
topo_obj.instance_uuid = fake_db_topology['instance_uuid']
topo_obj._save(self.context)
self.assertEqual(1, len(mock_update.call_args_list))
def _test_get_by_instance_uuid(self):
numa_topology = objects.InstanceNUMATopology.get_by_instance_uuid(
self.context, fake_db_topology['instance_uuid'])
self.assertEqual(fake_db_topology['instance_uuid'],
@@ -59,6 +73,16 @@ class _TestInstanceNUMATopology(object):
self.assertEqual(topo_cell.memory, obj_cell.memory)
self.assertEqual(topo_cell.pagesize, obj_cell.pagesize)
@mock.patch('nova.db.instance_extra_get_by_instance_uuid')
def test_get_by_instance_uuid(self, mock_get):
mock_get.return_value = fake_db_topology
self._test_get_by_instance_uuid()
@mock.patch('nova.db.instance_extra_get_by_instance_uuid')
def test_get_by_instance_uuid_old(self, mock_get):
mock_get.return_value = fake_old_db_topology
self._test_get_by_instance_uuid()
@mock.patch('nova.db.instance_extra_get_by_instance_uuid')
def test_get_by_instance_uuid_missing(self, mock_get):
mock_get.return_value = None