Remove 'level' and 'cooldown' from policies

This patch further cleanse the engine layer about policy level and
cooldown.

We will need to add a cooldown specifically for scaling policy. See bug
filed: https://bugs.launchpad.net/senlin/+bug/1533644

Change-Id: Ic52a3dba25b1070cb3899d7dd5d2b810ef1fcca6
This commit is contained in:
tengqm 2016-01-13 07:10:10 -05:00
parent 64b34dc47d
commit 5160d2f230
6 changed files with 34 additions and 224 deletions

View File

@ -319,19 +319,13 @@ class EngineService(service.Service):
return [p.to_dict() for p in policies]
@request_context
def policy_create(self, context, name, spec, level=None, cooldown=None):
def policy_create(self, context, name, spec):
if cfg.CONF.name_unique:
if db_api.policy_get_by_name(context, name):
msg = _("The policy (%(name)s) already exists."
) % {"name": name}
raise exception.SenlinBadRequest(msg=msg)
if level is None:
level = policy_base.SHOULD
else:
level = utils.parse_int_param('level', level, upper_limit=100)
cooldown = utils.parse_int_param('cooldown', cooldown)
type_name, version = schema.get_spec_version(spec)
try:
plugin = environment.global_env().get_policy(type_name)
@ -347,8 +341,6 @@ class EngineService(service.Service):
'user': context.user,
'project': context.project,
'domain': context.domain,
'level': level,
'cooldown': cooldown,
}
policy = plugin(name, spec, **kwargs)
@ -371,30 +363,21 @@ class EngineService(service.Service):
return policy.to_dict()
@request_context
def policy_update(self, context, identity, name=None, level=None,
cooldown=None):
LOG.info(_LI("Updating policy '%s'."), identity)
def policy_update(self, context, identity, name):
db_policy = self.policy_find(context, identity)
policy = policy_base.Policy.load(context, db_policy=db_policy)
changed = False
if name is not None and name != policy.name:
if not name:
msg = _('Policy name not specified.')
raise exception.SenlinBadRequest(msg=msg)
if name != policy.name:
LOG.info(_LI("Updating policy '%s'."), identity)
policy.name = name
changed = True
if level is not None and level != policy.level:
level = utils.parse_int_param('level', level, upper_limit=100)
policy.level = level
changed = True
if cooldown is not None and cooldown != policy.cooldown:
cooldown = utils.parse_int_param('cooldown', cooldown)
policy.cooldown = cooldown
changed = True
if changed:
policy.store(context)
LOG.info(_LI("Policy '%s' is updated."), identity)
LOG.info(_LI("Policy '%s' is updated."), identity)
return policy.to_dict()
@request_context

View File

@ -21,64 +21,13 @@ from senlin.common import utils
from senlin.db import api as db_api
from senlin.engine import environment
# Default enforcement levels and level names.
#
# - MUST: A policy of this enforcement level must be strictly checked. A
# violation of such a policy will lead a cluster to ``CRITICAL``
# status, which means that the cluster is in a problematic status
# that cannot be recovered using Senlin APIs. A manual intervention
# is needed. Such a cluster should not be treated as funtional any
# more.
#
# - SHOULD: A violation of a policy at this enforcement level will render a
# cluster into an ``ERROR`` status. A manual intervention is needed
# to recover the cluster. The cluster may and may not be providing
# services in the ``ERROR`` status.
#
# - WOULD: A policy of this enforcement level is usually about some
# operations that would be done when the policy is enforced. A
# violation of the policy will leave the cluster in a ``WARNING``
# status, which means that the cluster is still operational, but
# there are unsuccessful operations attempted.
#
# - MIGHT: A policy of this enforcement level is usually associated with
# certain operations that may or may not be done. A violation of
# this policy will not cause any negative impact to the cluster.
#
POLICY_LEVELS = (
MUST, SHOULD, WOULD, MIGHT,
) = (
50, 40, 30, 20
)
_levelNames = {
MUST: 'MUST',
SHOULD: 'SHOULD',
WOULD: 'WOULD',
MIGHT: 'MIGHT',
'MUST': MUST,
'SHOULD': SHOULD,
'WOULD': WOULD,
'MIGHT': MIGHT,
}
CHECK_RESULTS = (
CHECK_OK, CHECK_ERROR
CHECK_OK, CHECK_ERROR,
) = (
'OK', 'ERROR'
'OK', 'ERROR',
)
def getLevelName(level):
'''Get a level name or number.
Return a level name if given a numeric value; or return a value if given
a string. If level is not predefined, "Level %s" will be returned.
'''
return _levelNames.get(level, ("Level %s" % level))
class Policy(object):
'''Base class for policies.'''
PROFILE_TYPE = 'ANY'
@ -146,8 +95,6 @@ class Policy(object):
self.user = kwargs.get('user')
self.project = kwargs.get('project')
self.domain = kwargs.get('domain')
self.level = kwargs.get('level', SHOULD)
self.cooldown = kwargs.get('cooldown', 0)
self.data = kwargs.get('data', {})
self.created_at = kwargs.get('created_at', None)
@ -168,8 +115,6 @@ class Policy(object):
'user': record.user,
'project': record.project,
'domain': record.domain,
'level': record.level,
'cooldown': record.cooldown,
'created_at': record.created_at,
'updated_at': record.updated_at,
'data': record.data,
@ -224,8 +169,6 @@ class Policy(object):
'project': self.project,
'domain': self.domain,
'spec': self.spec,
'level': self.level,
'cooldown': self.cooldown,
'data': self.data,
}
@ -320,8 +263,6 @@ class Policy(object):
'project': self.project,
'domain': self.domain,
'spec': self.spec,
'level': self.level,
'cooldown': self.cooldown,
'created_at': utils.format_time(self.created_at),
'updated_at': utils.format_time(self.updated_at),
'data': self.data,

View File

@ -54,8 +54,7 @@ class ClusterPolicyTest(base.SenlinTestCase):
'version': '1.0',
'properties': {'KEY2': 5},
}
self.policy = self.eng.policy_create(self.ctx, 'policy_1', policy_spec,
cooldown=6, level=5)
self.policy = self.eng.policy_create(self.ctx, 'policy_1', policy_spec)
self.cluster = self.eng.cluster_create(self.ctx, 'c-1', 0,
self.profile['id'])
@ -107,8 +106,8 @@ class ClusterPolicyTest(base.SenlinTestCase):
inputs = {
'policy_id': policy_id,
'priority': cfg.CONF.default_policy_priority,
'level': self.policy['level'],
'cooldown': self.policy['cooldown'],
'level': None,
'cooldown': None,
'enabled': True
}
self._verify_action(action, 'CLUSTER_ATTACH_POLICY',
@ -295,22 +294,19 @@ class ClusterPolicyTest(base.SenlinTestCase):
cluster=self.cluster['id'])),
six.text_type(ex.exc_info[1]))
def _prepare_policy(self, name, type_name=None, cooldown=None, level=None):
def _prepare_policy(self, name, type_name=None):
if type_name is not None:
env = environment.global_env()
env.register_policy(type_name, fakes.TestPolicy)
else:
type_name = 'TestPolicy'
spec = {
'type': type_name,
'version': '1.0',
'properties': {'KEY2': 5}
}
policy = self.eng.policy_create(self.ctx, name, spec,
cooldown=cooldown or 60,
level=level or 50)
return policy
return self.eng.policy_create(self.ctx, name, spec)
def test_cluster_policy_list(self):
cluster_id = self.cluster['id']

View File

@ -54,8 +54,7 @@ class ClusterTest(base.SenlinTestCase):
'version': '1.0',
'properties': {'KEY2': 3}
}
self.policy = self.eng.policy_create(self.ctx, 'policy_1', spec,
cooldown=60, level=50)
self.policy = self.eng.policy_create(self.ctx, 'policy_1', spec)
def _verify_action(self, obj, action, name, target, cause, inputs=None):
if inputs is None:

View File

@ -18,25 +18,11 @@ from senlin.common import exception
from senlin.common.i18n import _
from senlin.engine import environment
from senlin.engine import service
from senlin.policies import base as policy_base
from senlin.tests.unit.common import base
from senlin.tests.unit.common import utils
from senlin.tests.unit import fakes
class PolicyLevelNameTest(base.SenlinTestCase):
def test_level_name(self):
names = []
for level in policy_base.POLICY_LEVELS:
name = policy_base.getLevelName(level)
names.append(name)
for name in names:
level = policy_base.getLevelName(name)
self.assertIn(level, policy_base.POLICY_LEVELS)
class PolicyTest(base.SenlinTestCase):
def setUp(self):
@ -62,8 +48,6 @@ class PolicyTest(base.SenlinTestCase):
self.assertEqual('p-1', result['name'])
self.assertEqual('TestPolicy-1.0', result['type'])
self.assertEqual(self.spec, result['spec'])
self.assertEqual(policy_base.SHOULD, result['level'])
self.assertIsNone(result['cooldown'])
self.assertIsNone(result['updated_at'])
self.assertIsNotNone(result['created_at'])
self.assertIsNotNone(result['id'])
@ -81,13 +65,6 @@ class PolicyTest(base.SenlinTestCase):
"already exists."),
six.text_type(ex.exc_info[1]))
def test_policy_create_with_cooldown_and_level(self):
result = self.eng.policy_create(self.ctx, 'p-1', self.spec,
cooldown=60, level=20)
self.assertEqual(self.spec, result['spec'])
self.assertEqual(60, result['cooldown'])
self.assertEqual(20, result['level'])
def test_policy_create_type_not_found(self):
self.spec['type'] = 'Bogus'
ex = self.assertRaises(rpc.ExpectedException,
@ -163,10 +140,9 @@ class PolicyTest(base.SenlinTestCase):
result = self.eng.policy_list(self.ctx, limit=2, marker=p1['id'])
self.assertEqual(2, len(result))
def test_policy_list_with_sort_keys(self):
p1 = self.eng.policy_create(self.ctx, 'p-B', self.spec, cooldown=60)
p2 = self.eng.policy_create(self.ctx, 'p-A', self.spec, cooldown=60)
p3 = self.eng.policy_create(self.ctx, 'p-C', self.spec, cooldown=120)
def test_policy_list_with_sorting(self):
p1 = self.eng.policy_create(self.ctx, 'p-B', self.spec)
p2 = self.eng.policy_create(self.ctx, 'p-A', self.spec)
# default by created_at
result = self.eng.policy_list(self.ctx)
@ -178,21 +154,11 @@ class PolicyTest(base.SenlinTestCase):
self.assertEqual(p2['id'], result[0]['id'])
self.assertEqual(p1['id'], result[1]['id'])
# use permission for sorting
result = self.eng.policy_list(self.ctx, sort='cooldown')
self.assertEqual(p3['id'], result[2]['id'])
# use name and permission for sorting
result = self.eng.policy_list(self.ctx, sort='cooldown,name')
self.assertEqual(p2['id'], result[0]['id'])
self.assertEqual(p1['id'], result[1]['id'])
self.assertEqual(p3['id'], result[2]['id'])
# unknown keys will be ignored
result = self.eng.policy_list(self.ctx, sort='duang')
self.assertIsNotNone(result)
def test_policy_list_with_sort_dir(self):
def test_policy_list_with_sorting_dir(self):
p1 = self.eng.policy_create(self.ctx, 'p-B', self.spec)
p2 = self.eng.policy_create(self.ctx, 'p-A', self.spec)
p3 = self.eng.policy_create(self.ctx, 'p-C', self.spec)
@ -213,9 +179,9 @@ class PolicyTest(base.SenlinTestCase):
self.assertEqual(p1['id'], result[1]['id'])
def test_policy_list_with_filters(self):
self.eng.policy_create(self.ctx, 'p-B', self.spec, cooldown=60)
self.eng.policy_create(self.ctx, 'p-A', self.spec, cooldown=60)
self.eng.policy_create(self.ctx, 'p-C', self.spec, cooldown=0)
self.eng.policy_create(self.ctx, 'p-B', self.spec)
self.eng.policy_create(self.ctx, 'p-A', self.spec)
self.eng.policy_create(self.ctx, 'p-C', self.spec)
result = self.eng.policy_list(self.ctx, filters={'name': 'p-B'})
self.assertEqual(1, len(result))
@ -224,10 +190,6 @@ class PolicyTest(base.SenlinTestCase):
result = self.eng.policy_list(self.ctx, filters={'name': 'p-D'})
self.assertEqual(0, len(result))
filters = {'cooldown': 60}
result = self.eng.policy_list(self.ctx, filters=filters)
self.assertEqual(2, len(result))
def test_policy_list_bad_param(self):
ex = self.assertRaises(rpc.ExpectedException,
self.eng.policy_list, self.ctx, limit='no')
@ -257,9 +219,8 @@ class PolicyTest(base.SenlinTestCase):
self.assertRaises(exception.PolicyNotFound,
self.eng.policy_find, self.ctx, 'Bogus')
def test_policy_update_fields(self):
p1 = self.eng.policy_create(self.ctx, 'p-1', self.spec, cooldown=60,
level=20)
def test_policy_update(self):
p1 = self.eng.policy_create(self.ctx, 'p-1', self.spec)
pid = p1['id']
self.assertEqual(self.spec, p1['spec'])
@ -272,36 +233,6 @@ class PolicyTest(base.SenlinTestCase):
p = self.eng.policy_get(self.ctx, pid)
self.assertEqual('p-2', p['name'])
# 2. update cooldown
p2 = self.eng.policy_update(self.ctx, pid, cooldown=120)
self.assertEqual(pid, p2['id'])
self.assertEqual(120, p2['cooldown'])
# check persisted into db
p = self.eng.policy_get(self.ctx, pid)
self.assertEqual(120, p['cooldown'])
# invalid cooldown value
ex = self.assertRaises(rpc.ExpectedException,
self.eng.policy_update, self.ctx, pid,
cooldown=-1)
self.assertEqual(exception.InvalidParameter, ex.exc_info[0])
# 3. update level
p2 = self.eng.policy_update(self.ctx, pid, level=50)
self.assertEqual(pid, p2['id'])
self.assertEqual(50, p2['level'])
# check persisted into db
p = self.eng.policy_get(self.ctx, pid)
self.assertEqual(50, p['level'])
# invalid enforcement level
ex = self.assertRaises(rpc.ExpectedException,
self.eng.policy_update, self.ctx, pid,
level=150)
self.assertEqual(exception.InvalidParameter, ex.exc_info[0])
def test_policy_update_not_found(self):
ex = self.assertRaises(rpc.ExpectedException,
self.eng.policy_update,
@ -309,38 +240,13 @@ class PolicyTest(base.SenlinTestCase):
self.assertEqual(exception.PolicyNotFound, ex.exc_info[0])
def test_policy_update_using_find(self):
p1 = self.eng.policy_create(self.ctx, 'p-1', self.spec)
pid = p1['id']
p2 = self.eng.policy_update(self.ctx, pid, name='p-2')
self.assertEqual(pid, p2['id'])
self.assertEqual('p-2', p2['name'])
# use short id
p3 = self.eng.policy_update(self.ctx, pid[:6], name='p-3')
self.assertEqual(pid, p3['id'])
self.assertEqual('p-3', p3['name'])
p4 = self.eng.policy_update(self.ctx, 'p-3', name='p-4')
self.assertEqual(pid, p4['id'])
self.assertEqual('p-4', p4['name'])
def test_policy_update_err_validate(self):
p1 = self.eng.policy_create(self.ctx, 'p-1', self.spec)
pid = p1['id']
def test_policy_update_name_not_specified(self):
self.eng.policy_create(self.ctx, 'p-1', self.spec)
ex = self.assertRaises(rpc.ExpectedException,
self.eng.policy_update,
self.ctx, pid, cooldown='yes')
self.ctx, 'p-1', None)
self.assertEqual(exception.InvalidParameter, ex.exc_info[0])
ex = self.assertRaises(rpc.ExpectedException,
self.eng.policy_update,
self.ctx, pid, level='high')
self.assertEqual(exception.InvalidParameter, ex.exc_info[0])
self.assertEqual(exception.SenlinBadRequest, ex.exc_info[0])
def test_policy_delete(self):
p1 = self.eng.policy_create(self.ctx, 'p-1', self.spec)

View File

@ -81,8 +81,6 @@ class TestPolicyBase(base.SenlinTestCase):
'user': self.ctx.user,
'project': self.ctx.project,
'domain': self.ctx.domain,
'level': policy_base.SHOULD,
'cooldown': 0,
'data': {}
}
@ -99,8 +97,6 @@ class TestPolicyBase(base.SenlinTestCase):
self.assertEqual(self.ctx.user, policy.user)
self.assertEqual(self.ctx.project, policy.project)
self.assertEqual(self.ctx.domain, policy.domain)
self.assertEqual(policy_base.SHOULD, policy.level)
self.assertEqual(0, policy.cooldown)
self.assertEqual({}, policy.data)
self.assertIsNone(policy.created_at)
self.assertIsNone(policy.updated_at)
@ -134,8 +130,6 @@ class TestPolicyBase(base.SenlinTestCase):
self.assertEqual(policy.user, result.user)
self.assertEqual(policy.project, result.project)
self.assertEqual(policy.domain, result.domain)
self.assertEqual(policy.level, result.level)
self.assertEqual(policy.cooldown, result.cooldown)
self.assertEqual(policy.spec, result.spec)
self.assertEqual(policy.data, result.data)
self.assertEqual({'key1': 'value1', 'key2': 2}, result.properties)
@ -202,12 +196,11 @@ class TestPolicyBase(base.SenlinTestCase):
project_safe=True)
mock_get.reset_mock()
res = list(policy_base.Policy.load_all(self.ctx, limit=1,
marker='MARKER', sort='K1:asc',
filters={'level': 30}))
res = list(policy_base.Policy.load_all(
self.ctx, limit=1, marker='MARKER', sort='K1:asc'))
self.assertEqual([], res)
mock_get.assert_called_once_with(self.ctx, limit=1, marker='MARKER',
sort='K1:asc', filters={'level': 30},
sort='K1:asc', filters=None,
project_safe=True)
def test_delete(self):
@ -241,8 +234,6 @@ class TestPolicyBase(base.SenlinTestCase):
self.assertEqual(policy.user, result.user)
self.assertEqual(policy.project, result.project)
self.assertEqual(policy.domain, result.domain)
self.assertEqual(policy.level, result.level)
self.assertEqual(policy.cooldown, result.cooldown)
self.assertEqual(policy.spec, result.spec)
self.assertEqual(policy.data, result.data)
@ -258,8 +249,6 @@ class TestPolicyBase(base.SenlinTestCase):
# do an update
policy.name = 'test-policy-1'
policy.level = 10
policy.cooldown = 60
policy.data = {'kk': 'vv'}
new_id = policy.store(self.ctx)
@ -268,8 +257,6 @@ class TestPolicyBase(base.SenlinTestCase):
result = db_api.policy_get(self.ctx, policy_id)
self.assertIsNotNone(result)
self.assertEqual('test-policy-1', result.name)
self.assertEqual(10, result.level)
self.assertEqual(60, result.cooldown)
self.assertEqual({'kk': 'vv'}, policy.data)
self.assertIsNotNone(policy.created_at)
self.assertIsNotNone(policy.updated_at)
@ -286,8 +273,6 @@ class TestPolicyBase(base.SenlinTestCase):
'project': policy.project,
'domain': policy.domain,
'spec': policy.spec,
'level': policy.level,
'cooldown': policy.cooldown,
'data': policy.data,
'created_at': common_utils.format_time(policy.created_at),
'updated_at': None,