Merge "Refactor policies to policy in InstanceGroup DB model"
This commit is contained in:
commit
571928cbaa
|
@ -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]
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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',
|
||||
|
|
Loading…
Reference in New Issue