From d030e29f5b0ba215789739e443f25ca1c80bc3da Mon Sep 17 00:00:00 2001 From: Russell Bryant Date: Fri, 20 Jul 2012 10:45:04 -0400 Subject: Include name in a primitive Instance. This ensures that the name of an instance will be present in the result of jsonutils.to_primitive(Instance). The name isn't a column. It's a property that gets generated dynamically by the Instance class. Part of blueprint no-db-messaging. Change-Id: I45914ed55f2c037ee2efd7775bd57fbde36a2116 --- nova/db/sqlalchemy/models.py | 20 ++++++++++++++++---- nova/tests/compute/test_rpcapi.py | 15 +++++++++------ 2 files changed, 25 insertions(+), 10 deletions(-) diff --git a/nova/db/sqlalchemy/models.py b/nova/db/sqlalchemy/models.py index 3ad6e71dd..5f7e85511 100644 --- a/nova/db/sqlalchemy/models.py +++ b/nova/db/sqlalchemy/models.py @@ -76,11 +76,17 @@ class NovaBase(object): return getattr(self, key, default) def __iter__(self): - self._i = iter(object_mapper(self).columns) + columns = dict(object_mapper(self).columns).keys() + # NOTE(russellb): Allow models to specify other keys that can be looked + # up, beyond the actual db columns. An example would be the 'name' + # property for an Instance. + if hasattr(self, '_extra_keys'): + columns.extend(self._extra_keys()) + self._i = iter(columns) return self def next(self): - n = self._i.next().name + n = self._i.next() return n, getattr(self, n) def update(self, values): @@ -183,12 +189,15 @@ class Instance(BASE, NovaBase): except TypeError: # Support templates like "uuid-%(uuid)s", etc. info = {} - for key, value in self.iteritems(): + # NOTE(russellb): Don't use self.iteritems() here, as it will + # result in infinite recursion on the name property. + for column in iter(object_mapper(self).columns): + key = column.name # prevent recursion if someone specifies %(name)s # %(name)s will not be valid. if key == 'name': continue - info[key] = value + info[key] = self[key] try: base_name = FLAGS.instance_name_template % info except KeyError: @@ -197,6 +206,9 @@ class Instance(BASE, NovaBase): base_name += "-rescue" return base_name + def _extra_keys(self): + return ['name'] + user_id = Column(String(255)) project_id = Column(String(255)) diff --git a/nova/tests/compute/test_rpcapi.py b/nova/tests/compute/test_rpcapi.py index d1d633023..96b103393 100644 --- a/nova/tests/compute/test_rpcapi.py +++ b/nova/tests/compute/test_rpcapi.py @@ -20,7 +20,9 @@ Unit Tests for nova.compute.rpcapi from nova.compute import rpcapi as compute_rpcapi from nova import context +from nova import db from nova import flags +from nova.openstack.common import jsonutils from nova.openstack.common import rpc from nova import test @@ -31,17 +33,18 @@ FLAGS = flags.FLAGS class ComputeRpcAPITestCase(test.TestCase): def setUp(self): - self.fake_instance = { - 'uuid': 'fake_uuid', - 'host': 'fake_host', - 'name': 'fake_name', - 'id': 'fake_id', - } + self.context = context.get_admin_context() + inst = db.instance_create(self.context, {'host': 'fake_host', + 'instance_type_id': 1}) + self.fake_instance = jsonutils.to_primitive(inst) super(ComputeRpcAPITestCase, self).setUp() def tearDown(self): super(ComputeRpcAPITestCase, self).tearDown() + def test_serialized_instance_has_name(self): + self.assertTrue('name' in self.fake_instance) + def _test_compute_api(self, method, rpc_method, **kwargs): ctxt = context.RequestContext('fake_user', 'fake_project') if 'rpcapi_class' in kwargs: -- cgit