summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRussell Bryant <rbryant@redhat.com>2012-07-20 10:45:04 -0400
committerRussell Bryant <rbryant@redhat.com>2012-07-25 19:48:30 -0400
commitd030e29f5b0ba215789739e443f25ca1c80bc3da (patch)
tree842ceced478a9215cafaa2c82980bbb7df37ead3
parenteebc64f949ccb2acb7462efc18f538f1827985af (diff)
downloadnova-d030e29f5b0ba215789739e443f25ca1c80bc3da.tar.gz
nova-d030e29f5b0ba215789739e443f25ca1c80bc3da.tar.xz
nova-d030e29f5b0ba215789739e443f25ca1c80bc3da.zip
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
-rw-r--r--nova/db/sqlalchemy/models.py20
-rw-r--r--nova/tests/compute/test_rpcapi.py15
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: