Merge "Refactor policies to policy in InstanceGroup DB model"

This commit is contained in:
Zuul 2018-07-10 22:59:34 +00:00 committed by Gerrit Code Review
commit 571928cbaa
4 changed files with 46 additions and 27 deletions

View File

@ -12,6 +12,7 @@
from oslo_db.sqlalchemy import models
from oslo_log import log as logging
from sqlalchemy import Boolean
from sqlalchemy import Column
from sqlalchemy import DateTime
@ -29,6 +30,8 @@ from sqlalchemy import String
from sqlalchemy import Text
from sqlalchemy import Unicode
LOG = logging.getLogger(__name__)
def MediumText():
return Text().with_variant(MEDIUMTEXT(), 'mysql')
@ -442,6 +445,16 @@ class InstanceGroup(API_BASE):
_members = orm.relationship(InstanceGroupMember,
primaryjoin='InstanceGroup.id == InstanceGroupMember.group_id')
@property
def policy(self):
if len(self._policies) not in (0, 1):
msg = ("More than one policy (%(policies)s) is associated with "
"group %(group_name)s, only the first one in the list "
"would be returned.")
LOG.warning(msg, {"policies": [p.policy for p in self._policies],
"group_name": self.name})
return self._policies[0] if self._policies else None
@property
def policies(self):
return [p.policy for p in self._policies]

View File

@ -68,17 +68,6 @@ def _instance_group_model_add(context, model_class, items, item_models, field,
return models
def _instance_group_policies_add(context, group, policies):
query = _instance_group_model_get_query(context,
api_models.InstanceGroupPolicy,
group.id)
query = query.filter(
api_models.InstanceGroupPolicy.policy.in_(set(policies)))
return _instance_group_model_add(context, api_models.InstanceGroupPolicy,
policies, query.all(), 'policy', group.id,
append_to_models=group._policies)
def _instance_group_members_add(context, group, members):
query = _instance_group_model_get_query(context,
api_models.InstanceGroupMember,
@ -132,7 +121,7 @@ class InstanceGroup(base.NovaPersistentObject, base.NovaObject,
'uuid': fields.UUIDField(),
'name': fields.StringField(nullable=True),
'policies': fields.ListOfStringsField(nullable=True),
'policies': fields.ListOfStringsField(nullable=True, read_only=True),
'members': fields.ListOfStringsField(nullable=True),
'hosts': fields.ListOfStringsField(nullable=True),
}
@ -214,13 +203,10 @@ class InstanceGroup(base.NovaPersistentObject, base.NovaObject,
def _save_in_db(context, group_uuid, values):
grp = InstanceGroup._get_from_db_by_uuid(context, group_uuid)
values_copy = copy.copy(values)
policies = values_copy.pop('policies', None)
members = values_copy.pop('members', None)
grp.update(values_copy)
if policies is not None:
_instance_group_policies_add(context, grp, policies)
if members is not None:
_instance_group_members_add(context, grp, members)
@ -237,8 +223,10 @@ class InstanceGroup(base.NovaPersistentObject, base.NovaObject,
raise exception.InstanceGroupIdExists(group_uuid=values['uuid'])
if policies:
group._policies = _instance_group_policies_add(context, group,
policies)
policy = api_models.InstanceGroupPolicy(
group_id=group['id'], policy=policies[0], rules=None)
group._policies = [policy]
group.save(context.session)
else:
group._policies = []
@ -335,6 +323,12 @@ class InstanceGroup(base.NovaPersistentObject, base.NovaObject,
if 'hosts' in updates:
raise exception.InstanceGroupSaveException(field='hosts')
# NOTE(yikun): You have to provide exactly one policy on group create,
# and also there are no group update APIs, so we do NOT support
# policies update.
if 'policies' in updates:
raise exception.InstanceGroupSaveException(field='policies')
if not updates:
return

View File

@ -14,6 +14,7 @@ import mock
from oslo_versionedobjects import fixture as ovo_fixture
from nova import context
from nova.db.sqlalchemy import api_models
from nova import exception
from nova import objects
from nova.objects import base
@ -31,7 +32,7 @@ class InstanceGroupObjectTestCase(test.TestCase):
user_id=self.context.user_id,
project_id=self.context.project_id,
name='foogroup',
policies=['foo1', 'foo2'],
policies=['foo1'],
members=['memberfoo'])
group.update(values)
group.create()
@ -41,6 +42,10 @@ class InstanceGroupObjectTestCase(test.TestCase):
create_group = self._api_group()
db_group = create_group._get_from_db_by_uuid(self.context,
create_group.uuid)
self.assertIsInstance(db_group.policy, api_models.InstanceGroupPolicy)
self.assertEqual(create_group.policies[0], db_group.policy.policy)
self.assertEqual(create_group.id, db_group.policy.group_id)
self.assertIsNone(db_group.policy.rules)
ovo_fixture.compare_obj(self, create_group, db_group,
allow_missing=('deleted', 'deleted_at'))
@ -54,7 +59,6 @@ class InstanceGroupObjectTestCase(test.TestCase):
@mock.patch('nova.compute.utils.notify_about_server_group_update')
def test_save(self, _mock_notify):
create_group = self._api_group()
create_group.policies = ['bar1', 'bar2']
create_group.members = ['memberbar1', 'memberbar2']
create_group.name = 'anewname'
create_group.save()

View File

@ -16,6 +16,7 @@ import copy
import mock
from oslo_utils import timeutils
from oslo_versionedobjects import exception as ovo_exc
from nova import exception
from nova import objects
@ -35,7 +36,8 @@ _INST_GROUP_DB = {
'user_id': 'fake_user',
'project_id': 'fake_project',
'name': 'fake_name',
'policies': ['policy1', 'policy2'],
# a group can only have 1 policy associated with it
'policies': ['policy1'],
'members': ['instance_id1', 'instance_id2'],
'created_at': _TS_NOW,
'updated_at': _TS_NOW
@ -79,10 +81,8 @@ class _TestInstanceGroupObject(object):
@mock.patch('nova.compute.utils.notify_about_server_group_update')
@mock.patch('nova.objects.InstanceGroup._get_from_db_by_uuid')
@mock.patch('nova.objects.instance_group._instance_group_policies_add')
@mock.patch('nova.objects.instance_group._instance_group_members_add')
def test_save(self, mock_members_add, mock_policies_add, mock_db_get,
mock_notify):
def test_save(self, mock_members_add, mock_db_get, mock_notify):
changed_group = copy.deepcopy(_INST_GROUP_DB)
changed_group['name'] = 'new_name'
db_group = copy.deepcopy(_INST_GROUP_DB)
@ -91,18 +91,14 @@ class _TestInstanceGroupObject(object):
self.assertEqual(obj.name, 'fake_name')
obj.obj_reset_changes()
obj.name = 'new_name'
obj.policies = ['policy1'] # Remove policy 2
obj.members = ['instance_id1'] # Remove member 2
obj.save()
self.assertEqual(set([]), obj.obj_what_changed())
mock_policies_add.assert_called_once_with(
self.context, mock_db_get.return_value, ['policy1'])
mock_members_add.assert_called_once_with(
self.context, mock_db_get.return_value, ['instance_id1'])
mock_notify.assert_called_once_with(self.context, "update",
{'name': 'new_name',
'members': ['instance_id1'],
'policies': ['policy1'],
'server_group_id': _DB_UUID})
@mock.patch('nova.compute.utils.notify_about_server_group_update')
@ -120,6 +116,18 @@ class _TestInstanceGroupObject(object):
# since hosts was the only update, there is no actual call
self.assertFalse(mock_notify.called)
def test_set_policies_failure(self):
group_obj = objects.InstanceGroup(context=self.context,
policies=['affinity'])
self.assertRaises(ovo_exc.ReadOnlyFieldError, setattr,
group_obj, 'policies', ['anti-affinity'])
def test_save_policies(self):
group_obj = objects.InstanceGroup(context=self.context)
group_obj.policies = ['fake-host1']
self.assertRaises(exception.InstanceGroupSaveException,
group_obj.save)
@mock.patch('nova.compute.utils.notify_about_server_group_action')
@mock.patch('nova.compute.utils.notify_about_server_group_update')
@mock.patch('nova.objects.InstanceGroup._create_in_db',