Group policy API-2 HEAT resources: Classifiers, Rules

This is the second patch in the Group Policy resources implementation
series. This patch implements:
    Policy Classifiers
    Policy Actions
    Policy Rules

In the context of larger Group Policy model, the Policy Rule resource
is referenced by Contracts, which will be introduced in the subsequent
patch.

Change-Id: If6df98133bb517ebfba37e20a988d9837aeee7f8
Implements: blueprint group-based-policy-automation
This commit is contained in:
Hemanth Ravi 2014-10-20 11:35:42 -07:00
parent a878e4080a
commit cbbc6d5546
2 changed files with 639 additions and 34 deletions

View File

@ -17,6 +17,7 @@ from gbpautomation.heat.engine.resources.neutron import gbpresource
from neutronclient.common.exceptions import NeutronClientException
from heat.engine import attributes
from heat.engine import constraints
from heat.engine import properties
@ -348,10 +349,249 @@ class L3Policy(gbpresource.GBPResource):
self.resource_id, {'l3_policy': prop_diff})
class PolicyClassifier(gbpresource.GBPResource):
PROPERTIES = (
TENANT_ID, NAME, DESCRIPTION, PROTOCOL, PORT_RANGE,
DIRECTION
) = (
'tenant_id', 'name', 'description', 'protocol', 'port_range',
'direction'
)
properties_schema = {
TENANT_ID: properties.Schema(
properties.Schema.STRING,
_('Tenant id of the policy classifier.')
),
NAME: properties.Schema(
properties.Schema.STRING,
_('Name of the policy classifier.'),
update_allowed=True
),
DESCRIPTION: properties.Schema(
properties.Schema.STRING,
_('Description of the policy classifier.'),
update_allowed=True
),
PROTOCOL: properties.Schema(
properties.Schema.STRING,
_('Protocol of traffic described by the policy classifier.'),
constraints=[
constraints.AllowedValues(['tcp', 'udp', 'icmp', None])
],
update_allowed=True
),
PORT_RANGE: properties.Schema(
properties.Schema.STRING,
_('Port range of traffic described by the policy classifier.'),
update_allowed=True
),
DIRECTION: properties.Schema(
properties.Schema.STRING,
_('Direction of traffic described by the policy classifier.'),
constraints=[
constraints.AllowedValues(['in', 'out', 'bi', None])
],
update_allowed=True
)
}
def _show_resource(self):
client = self.grouppolicy()
pc_id = self.resource_id
return client.show_policy_classifier(pc_id)['policy_classifier']
def handle_create(self):
client = self.grouppolicy()
props = {}
for key in self.properties:
if self.properties.get(key) is not None:
props[key] = self.properties.get(key)
policy_classifier = client.create_policy_classifier(
{'policy_classifier': props})['policy_classifier']
self.resource_id_set(policy_classifier['id'])
def handle_delete(self):
client = self.grouppolicy()
pc_id = self.resource_id
try:
client.delete_policy_classifier(pc_id)
except NeutronClientException as ex:
self.client_plugin().ignore_not_found(ex)
else:
return self._delete_task()
def handle_update(self, json_snippet, tmpl_diff, prop_diff):
if prop_diff:
self.grouppolicy().update_policy_classifier(
self.resource_id, {'policy_classifier': prop_diff})
class PolicyAction(gbpresource.GBPResource):
PROPERTIES = (
TENANT_ID, NAME, DESCRIPTION, ACTION_TYPE, ACTION_VALUE
) = (
'tenant_id', 'name', 'description', 'action_type', 'action_value'
)
properties_schema = {
TENANT_ID: properties.Schema(
properties.Schema.STRING,
_('Tenant id of the action.')
),
NAME: properties.Schema(
properties.Schema.STRING,
_('Name of the action.'),
update_allowed=True
),
DESCRIPTION: properties.Schema(
properties.Schema.STRING,
_('Description of the action.'),
update_allowed=True
),
ACTION_TYPE: properties.Schema(
properties.Schema.STRING,
_('Type of action.'),
constraints=[
constraints.AllowedValues(['allow', 'redirect', None])
],
update_allowed=True
),
ACTION_VALUE: properties.Schema(
properties.Schema.STRING,
_('Value of the action.'),
update_allowed=True
)
}
def _show_resource(self):
client = self.grouppolicy()
action_id = self.resource_id
return client.show_policy_action(action_id)['policy_action']
def handle_create(self):
client = self.grouppolicy()
props = {}
for key in self.properties:
if self.properties.get(key) is not None:
props[key] = self.properties.get(key)
policy_action = client.create_policy_action(
{'policy_action': props})['policy_action']
self.resource_id_set(policy_action['id'])
def handle_delete(self):
client = self.grouppolicy()
action_id = self.resource_id
try:
client.delete_policy_action(action_id)
except NeutronClientException as ex:
self.client_plugin().ignore_not_found(ex)
else:
return self._delete_task()
def handle_update(self, json_snippet, tmpl_diff, prop_diff):
if prop_diff:
self.grouppolicy().update_policy_action(
self.resource_id, {'policy_action': prop_diff})
class PolicyRule(gbpresource.GBPResource):
PROPERTIES = (
TENANT_ID, NAME, DESCRIPTION, ENABLED, POLICY_CLASSIFIER_ID,
POLICY_ACTIONS
) = (
'tenant_id', 'name', 'description', 'enabled', 'policy_classifier_id',
'policy_actions'
)
properties_schema = {
TENANT_ID: properties.Schema(
properties.Schema.STRING,
_('Tenant id of the policy rule.')
),
NAME: properties.Schema(
properties.Schema.STRING,
_('Name of the policy rule.'),
update_allowed=True
),
DESCRIPTION: properties.Schema(
properties.Schema.STRING,
_('Description of the policy rule.'),
update_allowed=True
),
ENABLED: properties.Schema(
properties.Schema.BOOLEAN,
_('State of policy rule.'),
default=True, update_allowed=True
),
POLICY_CLASSIFIER_ID: properties.Schema(
properties.Schema.STRING,
_('Classifier id of the policy rule.'),
required=True, update_allowed=True
),
POLICY_ACTIONS: properties.Schema(
properties.Schema.LIST,
_('List of actions of the policy rule.'),
default=None, update_allowed=True
)
}
def _show_resource(self):
client = self.grouppolicy()
rule_id = self.resource_id
return client.show_policy_rule(rule_id)['policy_rule']
def handle_create(self):
client = self.grouppolicy()
props = {}
for key in self.properties:
if self.properties.get(key) is not None:
props[key] = self.properties.get(key)
policy_rule = client.create_policy_rule(
{'policy_rule': props})['policy_rule']
self.resource_id_set(policy_rule['id'])
def handle_delete(self):
client = self.grouppolicy()
rule_id = self.resource_id
try:
client.delete_policy_rule(rule_id)
except NeutronClientException as ex:
self.client_plugin().ignore_not_found(ex)
else:
return self._delete_task()
def handle_update(self, json_snippet, tmpl_diff, prop_diff):
if prop_diff:
self.grouppolicy().update_policy_rule(
self.resource_id, {'policy_rule': prop_diff})
def resource_mapping():
return {
'OS::Neutron::Endpoint': Endpoint,
'OS::Neutron::EndpointGroup': EndpointGroup,
'OS::Neutron::L2Policy': L2Policy,
'OS::Neutron::L3Policy': L3Policy,
'OS::Neutron::PolicyClassifier': PolicyClassifier,
'OS::Neutron::PolicyAction': PolicyAction,
'OS::Neutron::PolicyRule': PolicyRule
}

View File

@ -11,6 +11,7 @@
# under the License.
import copy
import six
from gbpautomation.heat.engine.resources.neutron import grouppolicy
from gbpclient.v2_0 import client as gbpclient
@ -104,6 +105,65 @@ l3_policy_template = '''
}
'''
policy_classifier_template = '''
{
"AWSTemplateFormatVersion" : "2010-09-09",
"Description" : "Template to test neutron policy classifier",
"Parameters" : {},
"Resources" : {
"policy_classifier": {
"Type": "OS::Neutron::PolicyClassifier",
"Properties": {
"name": "test-policy-classifier",
"description": "test policy classifier resource",
"protocol": "tcp",
"port_range": "8000-9000",
"direction": "bi"
}
}
}
}
'''
policy_action_template = '''
{
"AWSTemplateFormatVersion" : "2010-09-09",
"Description" : "Template to test neutron policy action",
"Parameters" : {},
"Resources" : {
"policy_action": {
"Type": "OS::Neutron::PolicyAction",
"Properties": {
"name": "test-policy-action",
"description": "test policy action resource",
"action_type": "redirect",
"action_value": "7890"
}
}
}
}
'''
policy_rule_template = '''
{
"AWSTemplateFormatVersion" : "2010-09-09",
"Description" : "Template to test neutron l3 policy",
"Parameters" : {},
"Resources" : {
"policy_rule": {
"Type": "OS::Neutron::PolicyRule",
"Properties": {
"name": "test-policy-rule",
"description": "test policy rule resource",
"enabled": True,
"policy_classifier_id": "7890",
"policy_actions": ['3456', '1234']
}
}
}
}
'''
class EndpointTest(HeatTestCase):
@ -195,7 +255,7 @@ class EndpointTest(HeatTestCase):
scheduler.TaskRunner(rsrc.delete))
self.assertEqual(
'NeutronClientException: An unknown exception occurred.',
str(error))
six.text_type(error))
self.assertEqual((rsrc.DELETE, rsrc.FAILED), rsrc.state)
self.m.VerifyAll()
@ -344,17 +404,6 @@ class EndpointGroupTest(HeatTestCase):
self.assertEqual((rsrc.DELETE, rsrc.FAILED), rsrc.state)
self.m.VerifyAll()
def test_attribute_failed(self):
rsrc = self.create_endpoint_group()
self.m.ReplayAll()
scheduler.TaskRunner(rsrc.create)()
error = self.assertRaises(exception.InvalidTemplateAttribute,
rsrc.FnGetAtt, 'l3_policy_id')
self.assertEqual(
'The Referenced Attribute (endpoint_group l3_policy_id) is '
'incorrect.', str(error))
self.m.VerifyAll()
def test_update(self):
rsrc = self.create_endpoint_group()
gbpclient.Client.update_endpoint_group(
@ -463,17 +512,6 @@ class L2PolicyTest(HeatTestCase):
self.assertEqual((rsrc.DELETE, rsrc.FAILED), rsrc.state)
self.m.VerifyAll()
def test_attribute_failed(self):
rsrc = self.create_l2_policy()
self.m.ReplayAll()
scheduler.TaskRunner(rsrc.create)()
error = self.assertRaises(exception.InvalidTemplateAttribute,
rsrc.FnGetAtt, 'endpoint_id')
self.assertEqual(
'The Referenced Attribute (l2_policy endpoint_id) is '
'incorrect.', str(error))
self.m.VerifyAll()
def test_update(self):
rsrc = self.create_l2_policy()
gbpclient.Client.update_l2_policy(
@ -586,17 +624,6 @@ class L3PolicyTest(HeatTestCase):
self.assertEqual((rsrc.DELETE, rsrc.FAILED), rsrc.state)
self.m.VerifyAll()
def test_attribute_failed(self):
rsrc = self.create_l3_policy()
self.m.ReplayAll()
scheduler.TaskRunner(rsrc.create)()
error = self.assertRaises(exception.InvalidTemplateAttribute,
rsrc.FnGetAtt, 'subnet_id')
self.assertEqual(
'The Referenced Attribute (l3_policy subnet_id) is '
'incorrect.', str(error))
self.m.VerifyAll()
def test_update(self):
rsrc = self.create_l3_policy()
gbpclient.Client.update_l3_policy(
@ -609,3 +636,341 @@ class L3PolicyTest(HeatTestCase):
scheduler.TaskRunner(rsrc.update, update_template)()
self.m.VerifyAll()
class PolicyClassifierTest(HeatTestCase):
def setUp(self):
super(PolicyClassifierTest, self).setUp()
self.m.StubOutWithMock(gbpclient.Client,
'create_policy_classifier')
self.m.StubOutWithMock(gbpclient.Client,
'delete_policy_classifier')
self.m.StubOutWithMock(gbpclient.Client,
'show_policy_classifier')
self.m.StubOutWithMock(gbpclient.Client,
'update_policy_classifier')
self.stub_keystoneclient()
def create_policy_classifier(self):
gbpclient.Client.create_policy_classifier({
'policy_classifier': {
"name": "test-policy-classifier",
"description": "test policy classifier resource",
"protocol": "tcp",
"port_range": "8000-9000",
"direction": "bi"
}
}).AndReturn({'policy_classifier': {'id': '5678'}})
snippet = template_format.parse(policy_classifier_template)
stack = utils.parse_stack(snippet)
resource_defns = stack.t.resource_definitions(stack)
return grouppolicy.PolicyClassifier(
'policy_classifier', resource_defns['policy_classifier'], stack)
def test_create(self):
rsrc = self.create_policy_classifier()
self.m.ReplayAll()
scheduler.TaskRunner(rsrc.create)()
self.assertEqual((rsrc.CREATE, rsrc.COMPLETE), rsrc.state)
self.m.VerifyAll()
def test_create_failed(self):
gbpclient.Client.create_policy_classifier({
'policy_classifier': {
"name": "test-policy-classifier",
"description": "test policy classifier resource",
"protocol": "tcp",
"port_range": "8000-9000",
"direction": "bi"
}
}).AndRaise(grouppolicy.NeutronClientException())
self.m.ReplayAll()
snippet = template_format.parse(policy_classifier_template)
stack = utils.parse_stack(snippet)
resource_defns = stack.t.resource_definitions(stack)
rsrc = grouppolicy.PolicyClassifier(
'policy_classifier', resource_defns['policy_classifier'], stack)
error = self.assertRaises(exception.ResourceFailure,
scheduler.TaskRunner(rsrc.create))
self.assertEqual(
'NeutronClientException: An unknown exception occurred.',
str(error))
self.assertEqual((rsrc.CREATE, rsrc.FAILED), rsrc.state)
self.m.VerifyAll()
def test_delete(self):
gbpclient.Client.delete_policy_classifier('5678')
gbpclient.Client.show_policy_classifier('5678').AndRaise(
grouppolicy.NeutronClientException(status_code=404))
rsrc = self.create_policy_classifier()
self.m.ReplayAll()
scheduler.TaskRunner(rsrc.create)()
scheduler.TaskRunner(rsrc.delete)()
self.assertEqual((rsrc.DELETE, rsrc.COMPLETE), rsrc.state)
self.m.VerifyAll()
def test_delete_already_gone(self):
gbpclient.Client.delete_policy_classifier('5678').AndRaise(
grouppolicy.NeutronClientException(status_code=404))
rsrc = self.create_policy_classifier()
self.m.ReplayAll()
scheduler.TaskRunner(rsrc.create)()
scheduler.TaskRunner(rsrc.delete)()
self.assertEqual((rsrc.DELETE, rsrc.COMPLETE), rsrc.state)
self.m.VerifyAll()
def test_delete_failed(self):
gbpclient.Client.delete_policy_classifier('5678').AndRaise(
grouppolicy.NeutronClientException(status_code=400))
rsrc = self.create_policy_classifier()
self.m.ReplayAll()
scheduler.TaskRunner(rsrc.create)()
error = self.assertRaises(exception.ResourceFailure,
scheduler.TaskRunner(rsrc.delete))
self.assertEqual(
'NeutronClientException: An unknown exception occurred.',
str(error))
self.assertEqual((rsrc.DELETE, rsrc.FAILED), rsrc.state)
self.m.VerifyAll()
def test_update(self):
rsrc = self.create_policy_classifier()
gbpclient.Client.update_policy_classifier(
'5678', {'policy_classifier': {'protocol': 'udp'}})
self.m.ReplayAll()
scheduler.TaskRunner(rsrc.create)()
update_template = copy.deepcopy(rsrc.t)
update_template['Properties']['protocol'] = 'udp'
scheduler.TaskRunner(rsrc.update, update_template)()
self.m.VerifyAll()
class PolicyActionTest(HeatTestCase):
def setUp(self):
super(PolicyActionTest, self).setUp()
self.m.StubOutWithMock(gbpclient.Client, 'create_policy_action')
self.m.StubOutWithMock(gbpclient.Client, 'delete_policy_action')
self.m.StubOutWithMock(gbpclient.Client, 'show_policy_action')
self.m.StubOutWithMock(gbpclient.Client, 'update_policy_action')
self.stub_keystoneclient()
def create_policy_action(self):
gbpclient.Client.create_policy_action({
'policy_action': {
"name": "test-policy-action",
"description": "test policy action resource",
"action_type": "redirect",
"action_value": "7890"
}
}).AndReturn({'policy_action': {'id': '5678'}})
snippet = template_format.parse(policy_action_template)
stack = utils.parse_stack(snippet)
resource_defns = stack.t.resource_definitions(stack)
return grouppolicy.PolicyAction(
'policy_action', resource_defns['policy_action'], stack)
def test_create(self):
rsrc = self.create_policy_action()
self.m.ReplayAll()
scheduler.TaskRunner(rsrc.create)()
self.assertEqual((rsrc.CREATE, rsrc.COMPLETE), rsrc.state)
self.m.VerifyAll()
def test_create_failed(self):
gbpclient.Client.create_policy_action({
'policy_action': {
"name": "test-policy-action",
"description": "test policy action resource",
"action_type": "redirect",
"action_value": "7890"
}
}).AndRaise(grouppolicy.NeutronClientException())
self.m.ReplayAll()
snippet = template_format.parse(policy_action_template)
stack = utils.parse_stack(snippet)
resource_defns = stack.t.resource_definitions(stack)
rsrc = grouppolicy.PolicyAction(
'policy_action', resource_defns['policy_action'], stack)
error = self.assertRaises(exception.ResourceFailure,
scheduler.TaskRunner(rsrc.create))
self.assertEqual(
'NeutronClientException: An unknown exception occurred.',
str(error))
self.assertEqual((rsrc.CREATE, rsrc.FAILED), rsrc.state)
self.m.VerifyAll()
def test_delete(self):
gbpclient.Client.delete_policy_action('5678')
gbpclient.Client.show_policy_action('5678').AndRaise(
grouppolicy.NeutronClientException(status_code=404))
rsrc = self.create_policy_action()
self.m.ReplayAll()
scheduler.TaskRunner(rsrc.create)()
scheduler.TaskRunner(rsrc.delete)()
self.assertEqual((rsrc.DELETE, rsrc.COMPLETE), rsrc.state)
self.m.VerifyAll()
def test_delete_already_gone(self):
gbpclient.Client.delete_policy_action('5678').AndRaise(
grouppolicy.NeutronClientException(status_code=404))
rsrc = self.create_policy_action()
self.m.ReplayAll()
scheduler.TaskRunner(rsrc.create)()
scheduler.TaskRunner(rsrc.delete)()
self.assertEqual((rsrc.DELETE, rsrc.COMPLETE), rsrc.state)
self.m.VerifyAll()
def test_delete_failed(self):
gbpclient.Client.delete_policy_action('5678').AndRaise(
grouppolicy.NeutronClientException(status_code=400))
rsrc = self.create_policy_action()
self.m.ReplayAll()
scheduler.TaskRunner(rsrc.create)()
error = self.assertRaises(exception.ResourceFailure,
scheduler.TaskRunner(rsrc.delete))
self.assertEqual(
'NeutronClientException: An unknown exception occurred.',
str(error))
self.assertEqual((rsrc.DELETE, rsrc.FAILED), rsrc.state)
self.m.VerifyAll()
def test_update(self):
rsrc = self.create_policy_action()
gbpclient.Client.update_policy_action(
'5678', {'policy_action': {'action_type': 'allow'}})
self.m.ReplayAll()
scheduler.TaskRunner(rsrc.create)()
update_template = copy.deepcopy(rsrc.t)
update_template['Properties']['action_type'] = 'allow'
scheduler.TaskRunner(rsrc.update, update_template)()
self.m.VerifyAll()
class PolicyRuleTest(HeatTestCase):
def setUp(self):
super(PolicyRuleTest, self).setUp()
self.m.StubOutWithMock(gbpclient.Client, 'create_policy_rule')
self.m.StubOutWithMock(gbpclient.Client, 'delete_policy_rule')
self.m.StubOutWithMock(gbpclient.Client, 'show_policy_rule')
self.m.StubOutWithMock(gbpclient.Client, 'update_policy_rule')
self.stub_keystoneclient()
def create_policy_rule(self):
gbpclient.Client.create_policy_rule({
'policy_rule': {
"name": "test-policy-rule",
"description": "test policy rule resource",
"enabled": True,
"policy_classifier_id": "7890",
"policy_actions": ['3456', '1234']
}
}).AndReturn({'policy_rule': {'id': '5678'}})
snippet = template_format.parse(policy_rule_template)
stack = utils.parse_stack(snippet)
resource_defns = stack.t.resource_definitions(stack)
return grouppolicy.PolicyRule(
'policy_rule', resource_defns['policy_rule'], stack)
def test_create(self):
rsrc = self.create_policy_rule()
self.m.ReplayAll()
scheduler.TaskRunner(rsrc.create)()
self.assertEqual((rsrc.CREATE, rsrc.COMPLETE), rsrc.state)
self.m.VerifyAll()
def test_create_failed(self):
gbpclient.Client.create_policy_rule({
'policy_rule': {
"name": "test-policy-rule",
"description": "test policy rule resource",
"enabled": True,
"policy_classifier_id": "7890",
"policy_actions": ['3456', '1234']
}
}).AndRaise(grouppolicy.NeutronClientException())
self.m.ReplayAll()
snippet = template_format.parse(policy_rule_template)
stack = utils.parse_stack(snippet)
resource_defns = stack.t.resource_definitions(stack)
rsrc = grouppolicy.PolicyRule(
'policy_rule', resource_defns['policy_rule'], stack)
error = self.assertRaises(exception.ResourceFailure,
scheduler.TaskRunner(rsrc.create))
self.assertEqual(
'NeutronClientException: An unknown exception occurred.',
str(error))
self.assertEqual((rsrc.CREATE, rsrc.FAILED), rsrc.state)
self.m.VerifyAll()
def test_delete(self):
gbpclient.Client.delete_policy_rule('5678')
gbpclient.Client.show_policy_rule('5678').AndRaise(
grouppolicy.NeutronClientException(status_code=404))
rsrc = self.create_policy_rule()
self.m.ReplayAll()
scheduler.TaskRunner(rsrc.create)()
scheduler.TaskRunner(rsrc.delete)()
self.assertEqual((rsrc.DELETE, rsrc.COMPLETE), rsrc.state)
self.m.VerifyAll()
def test_delete_already_gone(self):
gbpclient.Client.delete_policy_rule('5678').AndRaise(
grouppolicy.NeutronClientException(status_code=404))
rsrc = self.create_policy_rule()
self.m.ReplayAll()
scheduler.TaskRunner(rsrc.create)()
scheduler.TaskRunner(rsrc.delete)()
self.assertEqual((rsrc.DELETE, rsrc.COMPLETE), rsrc.state)
self.m.VerifyAll()
def test_delete_failed(self):
gbpclient.Client.delete_policy_rule('5678').AndRaise(
grouppolicy.NeutronClientException(status_code=400))
rsrc = self.create_policy_rule()
self.m.ReplayAll()
scheduler.TaskRunner(rsrc.create)()
error = self.assertRaises(exception.ResourceFailure,
scheduler.TaskRunner(rsrc.delete))
self.assertEqual(
'NeutronClientException: An unknown exception occurred.',
str(error))
self.assertEqual((rsrc.DELETE, rsrc.FAILED), rsrc.state)
self.m.VerifyAll()
def test_update(self):
rsrc = self.create_policy_rule()
gbpclient.Client.update_policy_rule(
'5678', {'policy_rule': {'enabled': False}})
self.m.ReplayAll()
scheduler.TaskRunner(rsrc.create)()
update_template = copy.deepcopy(rsrc.t)
update_template['Properties']['enabled'] = False
scheduler.TaskRunner(rsrc.update, update_template)()
self.m.VerifyAll()