summaryrefslogtreecommitdiffstats
path: root/nova
diff options
context:
space:
mode:
authorDan Smith <danms@us.ibm.com>2013-06-17 19:03:03 -0700
committerDan Smith <danms@us.ibm.com>2013-06-24 15:47:53 -0700
commiteec6ddcfaf2af215a0e041ab1b7bbcce8ebb5aad (patch)
treef7f2344fce4f126f912a2436e7c7c629c20af7ba /nova
parent1792c03d81a5a72fbf881e26be235fb77236b1c2 (diff)
downloadnova-eec6ddcfaf2af215a0e041ab1b7bbcce8ebb5aad.tar.gz
nova-eec6ddcfaf2af215a0e041ab1b7bbcce8ebb5aad.tar.xz
nova-eec6ddcfaf2af215a0e041ab1b7bbcce8ebb5aad.zip
Add Instance.security_groups
This makes Instance load the security_groups list when it is present in the database object. It also refactors the way info_cache is saved, so that it can more easily apply to security_groups as well. Related to blueprint unified-object-model Fixes bug 1192003 Change-Id: Ifb028e17ffef7c14557e6389a650d66ce8e9b25c
Diffstat (limited to 'nova')
-rw-r--r--nova/objects/instance.py31
-rw-r--r--nova/tests/api/openstack/fakes.py5
-rw-r--r--nova/tests/compute/test_compute.py9
-rw-r--r--nova/tests/objects/test_instance.py37
4 files changed, 75 insertions, 7 deletions
diff --git a/nova/objects/instance.py b/nova/objects/instance.py
index 55e98e46e..cc61b1ed9 100644
--- a/nova/objects/instance.py
+++ b/nova/objects/instance.py
@@ -16,6 +16,7 @@ from nova import db
from nova import notifications
from nova.objects import base
from nova.objects import instance_info_cache
+from nova.objects import security_group
from nova.objects import utils as obj_utils
from nova import utils
@@ -28,13 +29,14 @@ CONF = cfg.CONF
# These are fields that can be specified as expected_attrs
INSTANCE_OPTIONAL_FIELDS = ['metadata', 'system_metadata']
# These are fields that are always joined by the db right now
-INSTANCE_IMPLIED_FIELDS = ['info_cache']
+INSTANCE_IMPLIED_FIELDS = ['info_cache', 'security_groups']
class Instance(base.NovaObject):
# Version 1.0: Initial version
# Version 1.1: Added info_cache
- VERSION = '1.1'
+ # Version 1.2: Added security_groups
+ VERSION = '1.2'
fields = {
'id': int,
@@ -106,8 +108,10 @@ class Instance(base.NovaObject):
'system_metadata': dict,
'info_cache': obj_utils.nested_object_or_none(
- instance_info_cache.InstanceInfoCache)
+ instance_info_cache.InstanceInfoCache),
+ 'security_groups': obj_utils.nested_object_or_none(
+ security_group.SecurityGroupList),
}
obj_extra_fields = ['name']
@@ -149,6 +153,8 @@ class Instance(base.NovaObject):
_attr_launched_at_to_primitive = obj_utils.dt_serializer('launched_at')
_attr_terminated_at_to_primitive = obj_utils.dt_serializer('terminated_at')
_attr_info_cache_to_primitive = obj_utils.obj_serializer('info_cache')
+ _attr_security_groups_to_primitive = obj_utils.obj_serializer(
+ 'security_groups')
_attr_scheduled_at_from_primitive = obj_utils.dt_deserializer
_attr_launched_at_from_primitive = obj_utils.dt_deserializer
@@ -157,6 +163,9 @@ class Instance(base.NovaObject):
def _attr_info_cache_from_primitive(self, val):
return base.NovaObject.obj_from_primitive(val)
+ def _attr_security_groups_from_primitive(self, val):
+ return base.NovaObject.obj_from_primitive(val)
+
@staticmethod
def _from_db_object(context, instance, db_inst, expected_attrs=None):
"""Method to help with migration to objects.
@@ -186,6 +195,11 @@ class Instance(base.NovaObject):
instance['info_cache'] = instance_info_cache.InstanceInfoCache()
instance_info_cache.InstanceInfoCache._from_db_object(
context, instance['info_cache'], db_inst['info_cache'])
+ if db_inst['security_groups']:
+ instance['security_groups'] = security_group.SecurityGroupList()
+ security_group._make_secgroup_list(context,
+ instance['security_groups'],
+ db_inst['security_groups'])
instance._context = context
instance.obj_reset_changes()
@@ -211,6 +225,13 @@ class Instance(base.NovaObject):
return Instance._from_db_object(context, cls(), db_inst,
expected_attrs)
+ def _save_info_cache(self, context):
+ self.info_cache.save(context)
+
+ def _save_security_groups(self, context):
+ for secgroup in self.security_groups:
+ secgroup.save(context)
+
@base.remotable
def save(self, context, expected_task_state=None):
"""Save updates to this instance
@@ -228,7 +249,7 @@ class Instance(base.NovaObject):
for field in self.fields:
if (hasattr(self, base.get_attrname(field)) and
isinstance(self[field], base.NovaObject)):
- self[field].save(context)
+ getattr(self, '_save_%s' % field)(context)
elif field in changes:
updates[field] = self[field]
if expected_task_state is not None:
@@ -270,6 +291,8 @@ class Instance(base.NovaObject):
extra.append('metadata')
elif attrname == 'info_cache':
extra.append('info_cache')
+ elif attrname == 'security_groups':
+ extra.append('security_groups')
if not extra:
raise Exception('Cannot load "%s" from instance' % attrname)
diff --git a/nova/tests/api/openstack/fakes.py b/nova/tests/api/openstack/fakes.py
index f05561ff2..a4edf9e89 100644
--- a/nova/tests/api/openstack/fakes.py
+++ b/nova/tests/api/openstack/fakes.py
@@ -488,7 +488,10 @@ def stub_instance(id, user_id=None, project_id=None, host=None,
key_data = ''
if security_groups is None:
- security_groups = [{"id": 1, "name": "test"}]
+ security_groups = [{"id": 1, "name": "test", "description": "Foo:",
+ "project_id": "project", "user_id": "user",
+ "created_at": None, "updated_at": None,
+ "deleted_at": None, "deleted": False}]
# ReservationID isn't sent back, hack it in there.
server_name = name or "server%s" % id
diff --git a/nova/tests/compute/test_compute.py b/nova/tests/compute/test_compute.py
index 7953f8b63..cb9498b1a 100644
--- a/nova/tests/compute/test_compute.py
+++ b/nova/tests/compute/test_compute.py
@@ -262,6 +262,7 @@ class BaseTestCase(test.TestCase):
inst['created_at'] = timeutils.utcnow()
inst['updated_at'] = timeutils.utcnow()
inst['launched_at'] = timeutils.utcnow()
+ inst['security_groups'] = []
inst.update(params)
_create_service_entries(self.context.elevated(),
{'fake_zone': [inst['host']]})
@@ -275,7 +276,10 @@ class BaseTestCase(test.TestCase):
def _fake_db_create(_ctxt, inst):
for k, v in inst.items():
- setattr(instance, k, v)
+ if k == 'security_groups':
+ setattr(instance, k, v or None)
+ else:
+ setattr(instance, k, v)
return instance
self.stubs.Set(db, 'instance_create', _fake_db_create)
@@ -4851,7 +4855,8 @@ class ComputeTestCase(BaseTestCase):
inst = dict(fakes.stub_instance(1),
deleted_at=None, created_at=None, updated_at=None,
deleted=0, info_cache={'instance_uuid': 'fake-uuid',
- 'network_info': None})
+ 'network_info': None},
+ security_groups=None)
startup_instances = [inst, inst, inst]
def _do_mock_calls(defer_iptables_apply):
diff --git a/nova/tests/objects/test_instance.py b/nova/tests/objects/test_instance.py
index 09ce70355..f5128e73f 100644
--- a/nova/tests/objects/test_instance.py
+++ b/nova/tests/objects/test_instance.py
@@ -20,6 +20,7 @@ from nova import context
from nova import db
from nova.objects import base
from nova.objects import instance
+from nova.objects import security_group
from nova.openstack.common import timeutils
from nova.tests.api.openstack import fakes
from nova.tests.objects import test_objects
@@ -41,6 +42,7 @@ class _TestInstanceObject(object):
tzinfo=iso8601.iso8601.Utc(), microsecond=0))
fake_instance['deleted'] = False
fake_instance['info_cache']['instance_uuid'] = fake_instance['uuid']
+ fake_instance['security_groups'] = None
return fake_instance
def test_datetime_deserialization(self):
@@ -213,6 +215,40 @@ class _TestInstanceObject(object):
inst.info_cache.network_info = 'bar'
inst.save()
+ def test_with_security_groups(self):
+ ctxt = context.get_admin_context()
+ fake_inst = dict(self.fake_instance)
+ fake_uuid = fake_inst['uuid']
+ fake_inst['security_groups'] = [
+ {'id': 1, 'name': 'secgroup1', 'description': 'fake-desc',
+ 'user_id': 'fake-user', 'project_id': 'fake_project',
+ 'created_at': None, 'updated_at': None, 'deleted_at': None,
+ 'deleted': False},
+ {'id': 2, 'name': 'secgroup2', 'description': 'fake-desc',
+ 'user_id': 'fake-user', 'project_id': 'fake_project',
+ 'created_at': None, 'updated_at': None, 'deleted_at': None,
+ 'deleted': False},
+ ]
+ self.mox.StubOutWithMock(db, 'instance_get_by_uuid')
+ self.mox.StubOutWithMock(db, 'instance_update_and_get_original')
+ self.mox.StubOutWithMock(db, 'security_group_update')
+ db.instance_get_by_uuid(ctxt, fake_uuid, []).AndReturn(fake_inst)
+ db.security_group_update(ctxt, 1, {'description': 'changed'}
+ ).AndReturn(fake_inst['security_groups'][0])
+ self.mox.ReplayAll()
+ inst = instance.Instance.get_by_uuid(ctxt, fake_uuid)
+ self.assertEqual(len(inst.security_groups), 2)
+ for index, group in enumerate(fake_inst['security_groups']):
+ for key in group:
+ self.assertEqual(group[key],
+ inst.security_groups[index][key])
+ self.assertTrue(isinstance(inst.security_groups[index],
+ security_group.SecurityGroup))
+ self.assertEqual(inst.security_groups.obj_what_changed(), set())
+ inst.security_groups[0].description = 'changed'
+ inst.save()
+ self.assertEqual(inst.security_groups.obj_what_changed(), set())
+
def test_iteritems_with_extra_attrs(self):
self.stubs.Set(instance.Instance, 'name', 'foo')
inst = instance.Instance()
@@ -248,6 +284,7 @@ class _TestInstanceListObject(object):
tzinfo=iso8601.iso8601.Utc(), microsecond=0))
fake_instance['info_cache'] = {'network_info': 'foo',
'instance_uuid': fake_instance['uuid']}
+ fake_instance['security_groups'] = []
fake_instance['deleted'] = 0
if updates:
fake_instance.update(updates)