Add policy to InstanceGroup object
The change items in this patch as below: 1. Add policy and rules to InstanceGroup, deprecate the policies field. 2. Also, make _from_db_object and _create_in_db method to support new "policy" field. The internal usage of InstanceGroup.policies is converted to use the new model in the REST API and RequestSpec compat code. Related to blueprint complex-anti-affinity-policies Change-Id: Ib33719a4b9599d86848c618a6e142c71ece79ca5
This commit is contained in:
parent
afc7650e64
commit
8fa70e5dfc
|
@ -166,7 +166,8 @@ class ServerGroupController(wsgi.Controller):
|
||||||
sg.user_id = context.user_id
|
sg.user_id = context.user_id
|
||||||
try:
|
try:
|
||||||
sg.name = vals.get('name')
|
sg.name = vals.get('name')
|
||||||
sg.policies = vals.get('policies')
|
policies = vals.get('policies')
|
||||||
|
sg.policy = policies[0]
|
||||||
sg.create()
|
sg.create()
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
raise exc.HTTPBadRequest(explanation=e)
|
raise exc.HTTPBadRequest(explanation=e)
|
||||||
|
|
|
@ -455,10 +455,6 @@ class InstanceGroup(API_BASE):
|
||||||
"group_name": self.name})
|
"group_name": self.name})
|
||||||
return self._policies[0] if self._policies else None
|
return self._policies[0] if self._policies else None
|
||||||
|
|
||||||
@property
|
|
||||||
def policies(self):
|
|
||||||
return [p.policy for p in self._policies]
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def members(self):
|
def members(self):
|
||||||
return [m.instance_uuid for m in self._members]
|
return [m.instance_uuid for m in self._members]
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
import copy
|
import copy
|
||||||
|
|
||||||
from oslo_db import exception as db_exc
|
from oslo_db import exception as db_exc
|
||||||
|
from oslo_serialization import jsonutils
|
||||||
from oslo_utils import uuidutils
|
from oslo_utils import uuidutils
|
||||||
from oslo_utils import versionutils
|
from oslo_utils import versionutils
|
||||||
from sqlalchemy.orm import contains_eager
|
from sqlalchemy.orm import contains_eager
|
||||||
|
@ -110,7 +111,8 @@ class InstanceGroup(base.NovaPersistentObject, base.NovaObject,
|
||||||
# Version 1.8: Add count_members_by_user()
|
# Version 1.8: Add count_members_by_user()
|
||||||
# Version 1.9: Add get_by_instance_uuid()
|
# Version 1.9: Add get_by_instance_uuid()
|
||||||
# Version 1.10: Add hosts field
|
# Version 1.10: Add hosts field
|
||||||
VERSION = '1.10'
|
# Version 1.11: Add policy and deprecate policies, add _rules
|
||||||
|
VERSION = '1.11'
|
||||||
|
|
||||||
fields = {
|
fields = {
|
||||||
'id': fields.IntegerField(),
|
'id': fields.IntegerField(),
|
||||||
|
@ -124,10 +126,39 @@ class InstanceGroup(base.NovaPersistentObject, base.NovaObject,
|
||||||
'policies': fields.ListOfStringsField(nullable=True, read_only=True),
|
'policies': fields.ListOfStringsField(nullable=True, read_only=True),
|
||||||
'members': fields.ListOfStringsField(nullable=True),
|
'members': fields.ListOfStringsField(nullable=True),
|
||||||
'hosts': fields.ListOfStringsField(nullable=True),
|
'hosts': fields.ListOfStringsField(nullable=True),
|
||||||
|
'policy': fields.StringField(nullable=True),
|
||||||
|
# NOTE(danms): Use rules not _rules for general access
|
||||||
|
'_rules': fields.DictOfStringsField(),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
if 'rules' in kwargs:
|
||||||
|
kwargs['_rules'] = kwargs.pop('rules')
|
||||||
|
super(InstanceGroup, self).__init__(*args, **kwargs)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def rules(self):
|
||||||
|
if '_rules' not in self:
|
||||||
|
return {}
|
||||||
|
# NOTE(danms): Coerce our rules into a typed dict for convenience
|
||||||
|
rules = {}
|
||||||
|
if 'max_server_per_host' in self._rules:
|
||||||
|
rules['max_server_per_host'] = \
|
||||||
|
int(self._rules['max_server_per_host'])
|
||||||
|
return rules
|
||||||
|
|
||||||
def obj_make_compatible(self, primitive, target_version):
|
def obj_make_compatible(self, primitive, target_version):
|
||||||
target_version = versionutils.convert_version_to_tuple(target_version)
|
target_version = versionutils.convert_version_to_tuple(target_version)
|
||||||
|
if target_version < (1, 11):
|
||||||
|
# NOTE(yikun): Before 1.11, we had a policies property which is
|
||||||
|
# the list of policy name, even though it was a list, there was
|
||||||
|
# ever only one entry in the list.
|
||||||
|
policy = primitive.pop('policy', None)
|
||||||
|
if policy:
|
||||||
|
primitive['policies'] = [policy]
|
||||||
|
else:
|
||||||
|
primitive['policies'] = []
|
||||||
|
primitive.pop('rules', None)
|
||||||
if target_version < (1, 7):
|
if target_version < (1, 7):
|
||||||
# NOTE(danms): Before 1.7, we had an always-empty
|
# NOTE(danms): Before 1.7, we had an always-empty
|
||||||
# metadetails property
|
# metadetails property
|
||||||
|
@ -151,8 +182,28 @@ class InstanceGroup(base.NovaPersistentObject, base.NovaObject,
|
||||||
# TODO(mriedem): Remove this when NovaPersistentObject is removed.
|
# TODO(mriedem): Remove this when NovaPersistentObject is removed.
|
||||||
ignore = {'deleted': False,
|
ignore = {'deleted': False,
|
||||||
'deleted_at': None}
|
'deleted_at': None}
|
||||||
if field in ignore and not hasattr(db_inst, field):
|
if '_rules' == field:
|
||||||
|
db_policy = db_inst['policy']
|
||||||
|
instance_group._rules = (
|
||||||
|
jsonutils.loads(db_policy['rules'])
|
||||||
|
if db_policy and db_policy['rules']
|
||||||
|
else {})
|
||||||
|
elif field in ignore and not hasattr(db_inst, field):
|
||||||
instance_group[field] = ignore[field]
|
instance_group[field] = ignore[field]
|
||||||
|
elif 'policies' == field:
|
||||||
|
continue
|
||||||
|
# NOTE(yikun): The obj.policies is deprecated and marked as
|
||||||
|
# read_only in version 1.11, and there is no "policies" property
|
||||||
|
# in InstanceGroup model anymore, so we just skip to set
|
||||||
|
# "policies" and then load the "policies" when "policy" is set.
|
||||||
|
elif 'policy' == field:
|
||||||
|
db_policy = db_inst['policy']
|
||||||
|
if db_policy:
|
||||||
|
instance_group.policy = db_policy['policy']
|
||||||
|
instance_group.policies = [instance_group.policy]
|
||||||
|
else:
|
||||||
|
instance_group.policy = None
|
||||||
|
instance_group.policies = []
|
||||||
else:
|
else:
|
||||||
instance_group[field] = db_inst[field]
|
instance_group[field] = db_inst[field]
|
||||||
|
|
||||||
|
@ -214,7 +265,8 @@ class InstanceGroup(base.NovaPersistentObject, base.NovaObject,
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
@db_api.api_context_manager.writer
|
@db_api.api_context_manager.writer
|
||||||
def _create_in_db(context, values, policies=None, members=None):
|
def _create_in_db(context, values, policies=None, members=None,
|
||||||
|
policy=None, rules=None):
|
||||||
try:
|
try:
|
||||||
group = api_models.InstanceGroup()
|
group = api_models.InstanceGroup()
|
||||||
group.update(values)
|
group.update(values)
|
||||||
|
@ -223,13 +275,22 @@ class InstanceGroup(base.NovaPersistentObject, base.NovaObject,
|
||||||
raise exception.InstanceGroupIdExists(group_uuid=values['uuid'])
|
raise exception.InstanceGroupIdExists(group_uuid=values['uuid'])
|
||||||
|
|
||||||
if policies:
|
if policies:
|
||||||
policy = api_models.InstanceGroupPolicy(
|
db_policy = api_models.InstanceGroupPolicy(
|
||||||
group_id=group['id'], policy=policies[0], rules=None)
|
group_id=group['id'], policy=policies[0], rules=None)
|
||||||
group._policies = [policy]
|
group._policies = [db_policy]
|
||||||
group.save(context.session)
|
group.rules = None
|
||||||
|
elif policy:
|
||||||
|
db_rules = jsonutils.dumps(rules or {})
|
||||||
|
db_policy = api_models.InstanceGroupPolicy(
|
||||||
|
group_id=group['id'], policy=policy,
|
||||||
|
rules=db_rules)
|
||||||
|
group._policies = [db_policy]
|
||||||
else:
|
else:
|
||||||
group._policies = []
|
group._policies = []
|
||||||
|
|
||||||
|
if group._policies:
|
||||||
|
group.save(context.session)
|
||||||
|
|
||||||
if members:
|
if members:
|
||||||
group._members = _instance_group_members_add(context, group,
|
group._members = _instance_group_members_add(context, group,
|
||||||
members)
|
members)
|
||||||
|
@ -358,6 +419,8 @@ class InstanceGroup(base.NovaPersistentObject, base.NovaObject,
|
||||||
payload = dict(updates)
|
payload = dict(updates)
|
||||||
updates.pop('id', None)
|
updates.pop('id', None)
|
||||||
policies = updates.pop('policies', None)
|
policies = updates.pop('policies', None)
|
||||||
|
policy = updates.pop('policy', None)
|
||||||
|
rules = updates.pop('_rules', None)
|
||||||
members = updates.pop('members', None)
|
members = updates.pop('members', None)
|
||||||
|
|
||||||
if 'uuid' not in updates:
|
if 'uuid' not in updates:
|
||||||
|
@ -366,7 +429,9 @@ class InstanceGroup(base.NovaPersistentObject, base.NovaObject,
|
||||||
|
|
||||||
db_group = self._create_in_db(self._context, updates,
|
db_group = self._create_in_db(self._context, updates,
|
||||||
policies=policies,
|
policies=policies,
|
||||||
members=members)
|
members=members,
|
||||||
|
policy=policy,
|
||||||
|
rules=rules)
|
||||||
self._from_db_object(self._context, self, db_group)
|
self._from_db_object(self._context, self, db_group)
|
||||||
payload['server_group_id'] = self.uuid
|
payload['server_group_id'] = self.uuid
|
||||||
compute_utils.notify_about_server_group_update(self._context,
|
compute_utils.notify_about_server_group_update(self._context,
|
||||||
|
|
|
@ -210,7 +210,7 @@ class RequestSpec(base.NovaObject):
|
||||||
policies = list(filter_properties.get('group_policies'))
|
policies = list(filter_properties.get('group_policies'))
|
||||||
hosts = list(filter_properties.get('group_hosts'))
|
hosts = list(filter_properties.get('group_hosts'))
|
||||||
members = list(filter_properties.get('group_members'))
|
members = list(filter_properties.get('group_members'))
|
||||||
self.instance_group = objects.InstanceGroup(policies=policies,
|
self.instance_group = objects.InstanceGroup(policy=policies[0],
|
||||||
hosts=hosts,
|
hosts=hosts,
|
||||||
members=members)
|
members=members)
|
||||||
# hosts has to be not part of the updates for saving the object
|
# hosts has to be not part of the updates for saving the object
|
||||||
|
|
|
@ -32,7 +32,8 @@ class InstanceGroupObjectTestCase(test.TestCase):
|
||||||
user_id=self.context.user_id,
|
user_id=self.context.user_id,
|
||||||
project_id=self.context.project_id,
|
project_id=self.context.project_id,
|
||||||
name='foogroup',
|
name='foogroup',
|
||||||
policies=['foo1'],
|
policy='anti-affinity',
|
||||||
|
rules={'max_server_per_host': 1},
|
||||||
members=['memberfoo'])
|
members=['memberfoo'])
|
||||||
group.update(values)
|
group.update(values)
|
||||||
group.create()
|
group.create()
|
||||||
|
@ -45,9 +46,11 @@ class InstanceGroupObjectTestCase(test.TestCase):
|
||||||
self.assertIsInstance(db_group.policy, api_models.InstanceGroupPolicy)
|
self.assertIsInstance(db_group.policy, api_models.InstanceGroupPolicy)
|
||||||
self.assertEqual(create_group.policies[0], db_group.policy.policy)
|
self.assertEqual(create_group.policies[0], db_group.policy.policy)
|
||||||
self.assertEqual(create_group.id, db_group.policy.group_id)
|
self.assertEqual(create_group.id, db_group.policy.group_id)
|
||||||
self.assertIsNone(db_group.policy.rules)
|
ovo_fixture.compare_obj(
|
||||||
ovo_fixture.compare_obj(self, create_group, db_group,
|
self, create_group, db_group,
|
||||||
allow_missing=('deleted', 'deleted_at'))
|
comparators={'policy': lambda a, b: b == a.policy},
|
||||||
|
allow_missing=('deleted', 'deleted_at', 'policies', '_rules'))
|
||||||
|
self.assertEqual({'max_server_per_host': 1}, create_group.rules)
|
||||||
|
|
||||||
def test_destroy(self):
|
def test_destroy(self):
|
||||||
create_group = self._api_group()
|
create_group = self._api_group()
|
||||||
|
@ -64,8 +67,11 @@ class InstanceGroupObjectTestCase(test.TestCase):
|
||||||
create_group.save()
|
create_group.save()
|
||||||
db_group = create_group._get_from_db_by_uuid(self.context,
|
db_group = create_group._get_from_db_by_uuid(self.context,
|
||||||
create_group.uuid)
|
create_group.uuid)
|
||||||
ovo_fixture.compare_obj(self, create_group, db_group,
|
ovo_fixture.compare_obj(
|
||||||
allow_missing=('deleted', 'deleted_at'))
|
self, create_group, db_group,
|
||||||
|
comparators={'policy': lambda a, b: b == a.policy},
|
||||||
|
allow_missing=('deleted', 'deleted_at', 'policies', '_rules'))
|
||||||
|
self.assertEqual({'max_server_per_host': 1}, create_group.rules)
|
||||||
|
|
||||||
def test_add_members(self):
|
def test_add_members(self):
|
||||||
create_group = self._api_group()
|
create_group = self._api_group()
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
import copy
|
import copy
|
||||||
|
|
||||||
import mock
|
import mock
|
||||||
|
from oslo_serialization import jsonutils
|
||||||
from oslo_utils import timeutils
|
from oslo_utils import timeutils
|
||||||
from oslo_versionedobjects import exception as ovo_exc
|
from oslo_versionedobjects import exception as ovo_exc
|
||||||
|
|
||||||
|
@ -30,6 +31,10 @@ _TS_NOW = timeutils.utcnow(with_timezone=True)
|
||||||
# in process we lose microsecond resolution.
|
# in process we lose microsecond resolution.
|
||||||
_TS_NOW = _TS_NOW.replace(microsecond=0)
|
_TS_NOW = _TS_NOW.replace(microsecond=0)
|
||||||
_DB_UUID = uuids.fake
|
_DB_UUID = uuids.fake
|
||||||
|
_INST_GROUP_POLICY_DB = {
|
||||||
|
'policy': 'policy1',
|
||||||
|
'rules': jsonutils.dumps({'max_server_per_host': '2'}),
|
||||||
|
}
|
||||||
_INST_GROUP_DB = {
|
_INST_GROUP_DB = {
|
||||||
'id': 1,
|
'id': 1,
|
||||||
'uuid': _DB_UUID,
|
'uuid': _DB_UUID,
|
||||||
|
@ -37,11 +42,18 @@ _INST_GROUP_DB = {
|
||||||
'project_id': 'fake_project',
|
'project_id': 'fake_project',
|
||||||
'name': 'fake_name',
|
'name': 'fake_name',
|
||||||
# a group can only have 1 policy associated with it
|
# a group can only have 1 policy associated with it
|
||||||
'policies': ['policy1'],
|
'policy': _INST_GROUP_POLICY_DB,
|
||||||
|
'_policies': [_INST_GROUP_POLICY_DB],
|
||||||
'members': ['instance_id1', 'instance_id2'],
|
'members': ['instance_id1', 'instance_id2'],
|
||||||
'created_at': _TS_NOW,
|
'created_at': _TS_NOW,
|
||||||
'updated_at': _TS_NOW
|
'updated_at': _TS_NOW,
|
||||||
}
|
}
|
||||||
|
_INST_GROUP_OBJ_VALS = dict(
|
||||||
|
{k: v for k, v in
|
||||||
|
_INST_GROUP_DB.items()
|
||||||
|
if k not in ('policy', '_policies')},
|
||||||
|
policy=_INST_GROUP_POLICY_DB['policy'],
|
||||||
|
rules=jsonutils.loads(_INST_GROUP_POLICY_DB['rules']))
|
||||||
|
|
||||||
|
|
||||||
class _TestInstanceGroupObject(object):
|
class _TestInstanceGroupObject(object):
|
||||||
|
@ -53,11 +65,21 @@ class _TestInstanceGroupObject(object):
|
||||||
_DB_UUID)
|
_DB_UUID)
|
||||||
mock_api_get.assert_called_once_with(self.context, _DB_UUID)
|
mock_api_get.assert_called_once_with(self.context, _DB_UUID)
|
||||||
self.assertEqual(_INST_GROUP_DB['members'], obj.members)
|
self.assertEqual(_INST_GROUP_DB['members'], obj.members)
|
||||||
self.assertEqual(_INST_GROUP_DB['policies'], obj.policies)
|
self.assertEqual([_INST_GROUP_POLICY_DB['policy']], obj.policies)
|
||||||
self.assertEqual(_DB_UUID, obj.uuid)
|
self.assertEqual(_DB_UUID, obj.uuid)
|
||||||
self.assertEqual(_INST_GROUP_DB['project_id'], obj.project_id)
|
self.assertEqual(_INST_GROUP_DB['project_id'], obj.project_id)
|
||||||
self.assertEqual(_INST_GROUP_DB['user_id'], obj.user_id)
|
self.assertEqual(_INST_GROUP_DB['user_id'], obj.user_id)
|
||||||
self.assertEqual(_INST_GROUP_DB['name'], obj.name)
|
self.assertEqual(_INST_GROUP_DB['name'], obj.name)
|
||||||
|
self.assertEqual(_INST_GROUP_POLICY_DB['policy'], obj.policy)
|
||||||
|
self.assertEqual({'max_server_per_host': 2}, obj.rules)
|
||||||
|
|
||||||
|
def test_rules_helper(self):
|
||||||
|
obj = objects.InstanceGroup()
|
||||||
|
self.assertEqual({}, obj.rules)
|
||||||
|
self.assertNotIn('_rules', obj)
|
||||||
|
obj._rules = {}
|
||||||
|
self.assertEqual({}, obj.rules)
|
||||||
|
self.assertIn('_rules', obj)
|
||||||
|
|
||||||
@mock.patch('nova.objects.InstanceGroup._get_from_db_by_instance',
|
@mock.patch('nova.objects.InstanceGroup._get_from_db_by_instance',
|
||||||
return_value=_INST_GROUP_DB)
|
return_value=_INST_GROUP_DB)
|
||||||
|
@ -87,9 +109,10 @@ class _TestInstanceGroupObject(object):
|
||||||
changed_group['name'] = 'new_name'
|
changed_group['name'] = 'new_name'
|
||||||
db_group = copy.deepcopy(_INST_GROUP_DB)
|
db_group = copy.deepcopy(_INST_GROUP_DB)
|
||||||
mock_db_get.return_value = db_group
|
mock_db_get.return_value = db_group
|
||||||
obj = objects.InstanceGroup(self.context, **_INST_GROUP_DB)
|
obj = objects.InstanceGroup(self.context, **_INST_GROUP_OBJ_VALS)
|
||||||
self.assertEqual(obj.name, 'fake_name')
|
self.assertEqual(obj.name, 'fake_name')
|
||||||
obj.obj_reset_changes()
|
obj.obj_reset_changes()
|
||||||
|
self.assertEqual(set([]), obj.obj_what_changed())
|
||||||
obj.name = 'new_name'
|
obj.name = 'new_name'
|
||||||
obj.members = ['instance_id1'] # Remove member 2
|
obj.members = ['instance_id1'] # Remove member 2
|
||||||
obj.save()
|
obj.save()
|
||||||
|
@ -105,7 +128,7 @@ class _TestInstanceGroupObject(object):
|
||||||
@mock.patch('nova.objects.InstanceGroup._get_from_db_by_uuid')
|
@mock.patch('nova.objects.InstanceGroup._get_from_db_by_uuid')
|
||||||
def test_save_without_hosts(self, mock_db_get, mock_notify):
|
def test_save_without_hosts(self, mock_db_get, mock_notify):
|
||||||
mock_db_get.return_value = _INST_GROUP_DB
|
mock_db_get.return_value = _INST_GROUP_DB
|
||||||
obj = objects.InstanceGroup(self.context, **_INST_GROUP_DB)
|
obj = objects.InstanceGroup(self.context, **_INST_GROUP_OBJ_VALS)
|
||||||
obj.obj_reset_changes()
|
obj.obj_reset_changes()
|
||||||
obj.hosts = ['fake-host1']
|
obj.hosts = ['fake-host1']
|
||||||
self.assertRaises(exception.InstanceGroupSaveException,
|
self.assertRaises(exception.InstanceGroupSaveException,
|
||||||
|
@ -139,7 +162,7 @@ class _TestInstanceGroupObject(object):
|
||||||
obj.user_id = _INST_GROUP_DB['user_id']
|
obj.user_id = _INST_GROUP_DB['user_id']
|
||||||
obj.project_id = _INST_GROUP_DB['project_id']
|
obj.project_id = _INST_GROUP_DB['project_id']
|
||||||
obj.members = _INST_GROUP_DB['members']
|
obj.members = _INST_GROUP_DB['members']
|
||||||
obj.policies = _INST_GROUP_DB['policies']
|
obj.policies = [_INST_GROUP_DB['policy']['policy']]
|
||||||
obj.updated_at = _TS_NOW
|
obj.updated_at = _TS_NOW
|
||||||
obj.created_at = _TS_NOW
|
obj.created_at = _TS_NOW
|
||||||
obj.create()
|
obj.create()
|
||||||
|
@ -153,7 +176,9 @@ class _TestInstanceGroupObject(object):
|
||||||
'updated_at': _TS_NOW,
|
'updated_at': _TS_NOW,
|
||||||
},
|
},
|
||||||
members=_INST_GROUP_DB['members'],
|
members=_INST_GROUP_DB['members'],
|
||||||
policies=_INST_GROUP_DB['policies'])
|
policies=[_INST_GROUP_DB['policy']['policy']],
|
||||||
|
policy=None,
|
||||||
|
rules=None)
|
||||||
mock_notify.assert_called_once_with(
|
mock_notify.assert_called_once_with(
|
||||||
self.context, "create",
|
self.context, "create",
|
||||||
{'uuid': _DB_UUID,
|
{'uuid': _DB_UUID,
|
||||||
|
@ -163,7 +188,7 @@ class _TestInstanceGroupObject(object):
|
||||||
'created_at': _TS_NOW,
|
'created_at': _TS_NOW,
|
||||||
'updated_at': _TS_NOW,
|
'updated_at': _TS_NOW,
|
||||||
'members': _INST_GROUP_DB['members'],
|
'members': _INST_GROUP_DB['members'],
|
||||||
'policies': _INST_GROUP_DB['policies'],
|
'policies': [_INST_GROUP_DB['policy']['policy']],
|
||||||
'server_group_id': _DB_UUID})
|
'server_group_id': _DB_UUID})
|
||||||
|
|
||||||
def _group_matcher(group):
|
def _group_matcher(group):
|
||||||
|
@ -175,7 +200,7 @@ class _TestInstanceGroupObject(object):
|
||||||
group.created_at == _TS_NOW and
|
group.created_at == _TS_NOW and
|
||||||
group.updated_at == _TS_NOW and
|
group.updated_at == _TS_NOW and
|
||||||
group.members == _INST_GROUP_DB['members'] and
|
group.members == _INST_GROUP_DB['members'] and
|
||||||
group.policies == _INST_GROUP_DB['policies'] and
|
group.policies == [_INST_GROUP_DB['policy']['policy']] and
|
||||||
group.id == 1)
|
group.id == 1)
|
||||||
|
|
||||||
group_matcher = test_utils.CustomMockCallMatcher(_group_matcher)
|
group_matcher = test_utils.CustomMockCallMatcher(_group_matcher)
|
||||||
|
@ -271,12 +296,31 @@ class _TestInstanceGroupObject(object):
|
||||||
filters=expected_filters)
|
filters=expected_filters)
|
||||||
|
|
||||||
def test_obj_make_compatible(self):
|
def test_obj_make_compatible(self):
|
||||||
obj = objects.InstanceGroup(self.context, **_INST_GROUP_DB)
|
obj = objects.InstanceGroup(self.context, **_INST_GROUP_OBJ_VALS)
|
||||||
obj_primitive = obj.obj_to_primitive()
|
obj_primitive = obj.obj_to_primitive()
|
||||||
self.assertNotIn('metadetails', obj_primitive)
|
self.assertNotIn('metadetails', obj_primitive)
|
||||||
obj.obj_make_compatible(obj_primitive, '1.6')
|
obj.obj_make_compatible(obj_primitive, '1.6')
|
||||||
self.assertEqual({}, obj_primitive['metadetails'])
|
self.assertEqual({}, obj_primitive['metadetails'])
|
||||||
|
|
||||||
|
def test_obj_make_compatible_pre_1_11(self):
|
||||||
|
none_policy_group = copy.deepcopy(_INST_GROUP_DB)
|
||||||
|
none_policy_group['policy'] = None
|
||||||
|
dbs = [_INST_GROUP_DB, none_policy_group]
|
||||||
|
data = lambda x: x['nova_object.data']
|
||||||
|
for db in dbs:
|
||||||
|
ig = objects.InstanceGroup()
|
||||||
|
obj = ig._from_db_object(self.context, ig, db)
|
||||||
|
# Latest version obj has policy and policies
|
||||||
|
obj_primitive = obj.obj_to_primitive()
|
||||||
|
self.assertIn('policy', data(obj_primitive))
|
||||||
|
self.assertIn('policies', data(obj_primitive))
|
||||||
|
# Before 1.10, only has polices which is the list of policy name
|
||||||
|
obj_primitive = obj.obj_to_primitive('1.10')
|
||||||
|
self.assertNotIn('policy', data(obj_primitive))
|
||||||
|
self.assertIn('policies', data(obj_primitive))
|
||||||
|
self.assertEqual([db['policy']['policy']] if db['policy'] else [],
|
||||||
|
data(obj_primitive)['policies'])
|
||||||
|
|
||||||
@mock.patch.object(objects.InstanceList, 'get_by_filters')
|
@mock.patch.object(objects.InstanceList, 'get_by_filters')
|
||||||
def test_load_hosts(self, mock_get_by_filt):
|
def test_load_hosts(self, mock_get_by_filt):
|
||||||
mock_get_by_filt.return_value = [objects.Instance(host='host1'),
|
mock_get_by_filt.return_value = [objects.Instance(host='host1'),
|
||||||
|
|
|
@ -1103,7 +1103,7 @@ object_data = {
|
||||||
'InstanceExternalEvent': '1.2-23eb6ba79cde5cd06d3445f845ba4589',
|
'InstanceExternalEvent': '1.2-23eb6ba79cde5cd06d3445f845ba4589',
|
||||||
'InstanceFault': '1.2-7ef01f16f1084ad1304a513d6d410a38',
|
'InstanceFault': '1.2-7ef01f16f1084ad1304a513d6d410a38',
|
||||||
'InstanceFaultList': '1.2-6bb72de2872fe49ded5eb937a93f2451',
|
'InstanceFaultList': '1.2-6bb72de2872fe49ded5eb937a93f2451',
|
||||||
'InstanceGroup': '1.10-1a0c8c7447dc7ecb9da53849430c4a5f',
|
'InstanceGroup': '1.11-852ac511d30913ee88f3c3a869a8f30a',
|
||||||
'InstanceGroupList': '1.8-90f8f1a445552bb3bbc9fa1ae7da27d4',
|
'InstanceGroupList': '1.8-90f8f1a445552bb3bbc9fa1ae7da27d4',
|
||||||
'InstanceInfoCache': '1.5-cd8b96fefe0fc8d4d337243ba0bf0e1e',
|
'InstanceInfoCache': '1.5-cd8b96fefe0fc8d4d337243ba0bf0e1e',
|
||||||
'InstanceList': '2.4-d2c5723da8c1d08e07cb00160edfd292',
|
'InstanceList': '2.4-d2c5723da8c1d08e07cb00160edfd292',
|
||||||
|
|
|
@ -232,7 +232,7 @@ class _TestRequestSpecObject(object):
|
||||||
spec = objects.RequestSpec()
|
spec = objects.RequestSpec()
|
||||||
spec._populate_group_info(filt_props)
|
spec._populate_group_info(filt_props)
|
||||||
self.assertIsInstance(spec.instance_group, objects.InstanceGroup)
|
self.assertIsInstance(spec.instance_group, objects.InstanceGroup)
|
||||||
self.assertEqual(['affinity'], spec.instance_group.policies)
|
self.assertEqual('affinity', spec.instance_group.policy)
|
||||||
self.assertEqual(['fake1'], spec.instance_group.hosts)
|
self.assertEqual(['fake1'], spec.instance_group.hosts)
|
||||||
self.assertEqual(['fake-instance1'], spec.instance_group.members)
|
self.assertEqual(['fake-instance1'], spec.instance_group.members)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue