Group policy API-1 HEAT resources: EP, EPG, L2, L3

This is the first in a series of patches which implement
resources for neutron group policy APIs.

This patch implements four new resources:
    Endpoint
    EndpointGroup
    L2-Policy
    L3-Policy

Change-Id: Iac413aaa460bffa5c6f111e2e16beb9507a3d24a
Implements: blueprint group-based-policy-automation
This commit is contained in:
Hemanth Ravi 2014-10-19 19:08:42 -07:00
parent 15db2af2bb
commit a878e4080a
11 changed files with 1186 additions and 1 deletions

View File

View File

@ -0,0 +1,60 @@
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from gbpclient.v2_0 import client as gbpc
from neutronclient.common import exceptions
from heat.engine.clients import client_plugin
class GBPClientPlugin(client_plugin.ClientPlugin):
exceptions_module = exceptions
def _create(self):
con = self.context
endpoint_type = self._get_client_option('grouppolicy', 'endpoint_type')
endpoint = self.url_for(service_type='network',
endpoint_type=endpoint_type)
args = {
'auth_url': con.auth_url,
'service_type': 'network',
'token': self.auth_token,
'endpoint_url': endpoint,
'endpoint_type': endpoint_type,
'ca_cert': self._get_client_option('grouppolicy', 'ca_file'),
'insecure': self._get_client_option('grouppolicy', 'insecure')
}
return gbpc.Client(**args)
def is_not_found(self, ex):
if isinstance(ex, (exceptions.NotFound,
exceptions.NetworkNotFoundClient,
exceptions.PortNotFoundClient)):
return True
return (isinstance(ex, exceptions.NeutronClientException) and
ex.status_code == 404)
def is_conflict(self, ex):
if not isinstance(ex, exceptions.NeutronClientException):
return False
return ex.status_code == 409
def is_over_limit(self, ex):
if not isinstance(ex, exceptions.NeutronClientException):
return False
return ex.status_code == 413

View File

@ -0,0 +1,151 @@
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from heat.common import exception
from heat.engine import resource
from heat.engine import scheduler
from heat.openstack.common import log as logging
LOG = logging.getLogger(__name__)
class GBPResource(resource.Resource):
default_client_name = 'grouppolicy'
def grouppolicy(self):
return self.client('grouppolicy')
def validate(self):
'''
Validate any of the provided params
'''
res = super(GBPResource, self).validate()
if res:
return res
return self.validate_properties(self.properties)
@staticmethod
def validate_properties(properties):
'''
Validates to ensure nothing in value_specs overwrites
any key that exists in the schema.
Also ensures that shared and tenant_id is not specified
in value_specs.
'''
if 'value_specs' in properties.keys():
vs = properties.get('value_specs')
banned_keys = set(['shared', 'tenant_id']).union(
properties.keys())
for k in banned_keys.intersection(vs.keys()):
return '%s not allowed in value_specs' % k
@staticmethod
def _validate_depr_property_required(properties, prop_key, depr_prop_key):
prop_value = properties.get(prop_key)
depr_prop_value = properties.get(depr_prop_key)
if prop_value and depr_prop_value:
raise exception.ResourcePropertyConflict(prop_key,
depr_prop_key)
if not prop_value and not depr_prop_value:
msg = _('Either %(prop_key)s or %(depr_prop_key)s'
' should be specified.'
) % {'prop_key': prop_key,
'depr_prop_key': depr_prop_key}
raise exception.StackValidationFailed(message=msg)
@staticmethod
def prepare_properties(properties, name):
'''
Prepares the property values so that they can be passed directly to
the Neutron create call.
Removes None values and value_specs, merges value_specs with the main
values.
'''
props = dict((k, v) for k, v in properties.items()
if v is not None and k != 'value_specs')
if 'name' in properties.keys():
props.setdefault('name', name)
if 'value_specs' in properties.keys():
props.update(properties.get('value_specs'))
return props
def prepare_update_properties(self, definition):
'''
Prepares the property values so that they can be passed directly to
the Neutron update call.
Removes any properties which are not update_allowed, then processes
as for prepare_properties.
'''
p = definition.properties(self.properties_schema, self.context)
update_props = dict((k, v) for k, v in p.items()
if p.props.get(k).schema.update_allowed)
props = self.prepare_properties(
update_props,
self.physical_resource_name())
return props
@staticmethod
def is_built(attributes):
status = attributes['status']
if status == 'BUILD':
return False
if status in ('ACTIVE', 'DOWN'):
return True
elif status == 'ERROR':
raise resource.ResourceInError(
resource_status=status)
else:
raise resource.ResourceUnknownStatus(
resource_status=status,
result=_('Resource is not built'))
def _resolve_attribute(self, name):
try:
attributes = self._show_resource()
except Exception as ex:
self.client_plugin().ignore_not_found(ex)
return None
if name == 'show':
return attributes
return attributes[name]
def _confirm_delete(self):
while True:
try:
yield
self._show_resource()
except Exception as ex:
self.client_plugin().ignore_not_found(ex)
return
def FnGetRefId(self):
return unicode(self.resource_id)
def _delete_task(self):
delete_task = scheduler.TaskRunner(self._confirm_delete)
delete_task.start()
return delete_task
def check_delete_complete(self, delete_task):
# if the resource was already deleted, delete_task will be None
return delete_task is None or delete_task.step()

View File

@ -0,0 +1,357 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from gbpautomation.heat.engine.resources.neutron import gbpresource
from neutronclient.common.exceptions import NeutronClientException
from heat.engine import attributes
from heat.engine import properties
class Endpoint(gbpresource.GBPResource):
PROPERTIES = (
TENANT_ID, NAME, DESCRIPTION, ENDPOINT_GROUP_ID
) = (
'tenant_id', 'name', 'description', 'endpoint_group_id'
)
ATTRIBUTES = (
NEUTRON_PORT_ID
) = (
'neutron_port_id'
)
properties_schema = {
TENANT_ID: properties.Schema(
properties.Schema.STRING,
_('Tenant id of the endpoint.')
),
NAME: properties.Schema(
properties.Schema.STRING,
_('Name of the endpoint.'),
update_allowed=True
),
DESCRIPTION: properties.Schema(
properties.Schema.STRING,
_('Description of the endpoint.'),
update_allowed=True
),
ENDPOINT_GROUP_ID: properties.Schema(
properties.Schema.STRING,
_('Endpoint group id of the endpoint.'),
required=True,
update_allowed=True
)
}
attributes_schema = {
NEUTRON_PORT_ID: attributes.Schema(
_("Neutron port id of this endpoint")
)
}
def _show_resource(self):
client = self.grouppolicy()
ep_id = self.resource_id
return client.show_endpoint(ep_id)['endpoint']
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)
ep = client.create_endpoint({'endpoint': props})['endpoint']
self.resource_id_set(ep['id'])
def _resolve_attribute(self, name):
client = self.grouppolicy()
ep_id = self.resource_id
if name == 'neutron_port_id':
return client.show_endpoint(ep_id)['endpoint']['neutron_port_id']
return super(Endpoint, self)._resolve_attribute(name)
def handle_delete(self):
client = self.grouppolicy()
ep_id = self.resource_id
try:
client.delete_endpoint(ep_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_endpoint(
self.resource_id, {'endpoint': prop_diff})
class EndpointGroup(gbpresource.GBPResource):
PROPERTIES = (
TENANT_ID, NAME, DESCRIPTION, L2_POLICY_ID,
PROVIDED_CONTRACTS, CONSUMED_CONTRACTS
) = (
'tenant_id', 'name', 'description', 'l2_policy_id',
'provided_contracts', 'consumed_contracts'
)
properties_schema = {
TENANT_ID: properties.Schema(
properties.Schema.STRING,
_('Tenant id of the endpoint group.')
),
NAME: properties.Schema(
properties.Schema.STRING,
_('Name of the endpoint group.'),
update_allowed=True
),
DESCRIPTION: properties.Schema(
properties.Schema.STRING,
_('Description of the endpoint group.'),
update_allowed=True
),
L2_POLICY_ID: properties.Schema(
properties.Schema.STRING,
_('L2 policy id of the endpoint group.'),
update_allowed=True
),
PROVIDED_CONTRACTS: properties.Schema(
properties.Schema.LIST,
_('Provided contracts for the endpoint group.'),
update_allowed=True
),
CONSUMED_CONTRACTS: properties.Schema(
properties.Schema.LIST,
_('Consumed contracts for the endpoint group.'),
update_allowed=True
)
}
def _show_resource(self):
client = self.grouppolicy()
epg_id = self.resource_id
return client.show_endpoint_group(epg_id)['endpoint_group']
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)
provided_contracts_list = {}
consumed_contracts_list = {}
props_provided_contracts = props.get('provided_contracts', [])
props_consumed_contracts = props.get('consumed_contracts', [])
for prop_prov_contract in props_provided_contracts:
contract_id = prop_prov_contract['contract_id']
contract_scope = prop_prov_contract['contract_scope']
provided_contracts_list.update({contract_id: contract_scope})
for prop_cons_contract in props_consumed_contracts:
contract_id = prop_cons_contract['contract_id']
contract_scope = prop_cons_contract['contract_scope']
consumed_contracts_list.update({contract_id: contract_scope})
if provided_contracts_list:
props['provided_contracts'] = provided_contracts_list
if consumed_contracts_list:
props['consumed_contracts'] = consumed_contracts_list
epg = client.create_endpoint_group(
{'endpoint_group': props})['endpoint_group']
self.resource_id_set(epg['id'])
def handle_delete(self):
client = self.grouppolicy()
epg_id = self.resource_id
try:
client.delete_endpoint_group(epg_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_endpoint_group(
self.resource_id, {'endpoint_group': prop_diff})
class L2Policy(gbpresource.GBPResource):
PROPERTIES = (
TENANT_ID, NAME, DESCRIPTION, L3_POLICY_ID
) = (
'tenant_id', 'name', 'description', 'l3_policy_id'
)
properties_schema = {
TENANT_ID: properties.Schema(
properties.Schema.STRING,
_('Tenant id of the L2 policy.')
),
NAME: properties.Schema(
properties.Schema.STRING,
_('Name of the L2 policy.'),
update_allowed=True
),
DESCRIPTION: properties.Schema(
properties.Schema.STRING,
_('Description of the L2 policy.'),
update_allowed=True
),
L3_POLICY_ID: properties.Schema(
properties.Schema.STRING,
_('L3 policy id associated with l2 policy.'),
required=True,
update_allowed=True
)
}
def _show_resource(self):
client = self.grouppolicy()
l2_policy_id = self.resource_id
return client.show_l2_policy(l2_policy_id)['l2_policy']
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)
l2_policy = client.create_l2_policy(
{'l2_policy': props})['l2_policy']
self.resource_id_set(l2_policy['id'])
def handle_delete(self):
client = self.grouppolicy()
l2_policy_id = self.resource_id
try:
client.delete_l2_policy(l2_policy_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_l2_policy(
self.resource_id, {'l2_policy': prop_diff})
class L3Policy(gbpresource.GBPResource):
PROPERTIES = (
TENANT_ID, NAME, DESCRIPTION, IP_VERSION, IP_POOL,
SUBNET_PREFIX_LENGTH
) = (
'tenant_id', 'name', 'description', 'ip_version', 'ip_pool',
'subnet_prefix_length'
)
properties_schema = {
TENANT_ID: properties.Schema(
properties.Schema.STRING,
_('Tenant id of the L3 policy.')
),
NAME: properties.Schema(
properties.Schema.STRING,
_('Name of the L3 policy.'),
update_allowed=True
),
DESCRIPTION: properties.Schema(
properties.Schema.STRING,
_('Description of the L3 policy.'),
update_allowed=True
),
IP_VERSION: properties.Schema(
properties.Schema.STRING,
_('IP version of the L3 policy.'),
update_allowed=False
),
IP_POOL: properties.Schema(
properties.Schema.STRING,
_('IP pool of the L3 policy.'),
update_allowed=False
),
SUBNET_PREFIX_LENGTH: properties.Schema(
properties.Schema.INTEGER,
_('Subnet prefix length of L3 policy.'),
update_allowed=True
)
}
def _show_resource(self):
client = self.grouppolicy()
l3_policy_id = self.resource_id
return client.show_l3_policy(l3_policy_id)['l3_policy']
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)
l3_policy = client.create_l3_policy(
{'l3_policy': props})['l3_policy']
self.resource_id_set(l3_policy['id'])
def handle_delete(self):
client = self.grouppolicy()
l3_policy_id = self.resource_id
try:
client.delete_l3_policy(l3_policy_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_l3_policy(
self.resource_id, {'l3_policy': prop_diff})
def resource_mapping():
return {
'OS::Neutron::Endpoint': Endpoint,
'OS::Neutron::EndpointGroup': EndpointGroup,
'OS::Neutron::L2Policy': L2Policy,
'OS::Neutron::L3Policy': L3Policy,
}

View File

@ -0,0 +1,611 @@
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import copy
from gbpautomation.heat.engine.resources.neutron import grouppolicy
from gbpclient.v2_0 import client as gbpclient
from heat.common import exception
from heat.common import template_format
from heat.tests.common import HeatTestCase
from heat.engine import scheduler
from heat.tests import utils
endpoint_template = '''
{
"AWSTemplateFormatVersion" : "2010-09-09",
"Description" : "Template to test neutron endpoint resource",
"Parameters" : {},
"Resources" : {
"endpoint": {
"Type": "OS::Neutron::Endpoint",
"Properties": {
"name": "test-endpoint",
"endpoint_group_id": "epg-id",
"description": "test endpoint resource"
}
}
}
}
'''
endpoint_group_template = '''
{
"AWSTemplateFormatVersion" : "2010-09-09",
"Description" : "Template to test neutron endpoint group resource",
"Parameters" : {},
"Resources" : {
"endpoint_group": {
"Type": "OS::Neutron::EndpointGroup",
"Properties": {
"name": "test-endpoint-group",
"description": "test endpoint group resource",
"l2_policy_id": "l2-policy-id",
"provided_contracts": [
{"contract_id": "contract1", "contract_scope": "scope1"},
{"contract_id": "contract2", "contract_scope": "scope2"}
],
"consumed_contracts": [
{"contract_id": "contract3", "contract_scope": "scope3"},
{"contract_id": "contract4", "contract_scope": "scope4"}
]
}
}
}
}
'''
l2_policy_template = '''
{
"AWSTemplateFormatVersion" : "2010-09-09",
"Description" : "Template to test neutron l2 policy",
"Parameters" : {},
"Resources" : {
"l2_policy": {
"Type": "OS::Neutron::L2Policy",
"Properties": {
"name": "test-l2-policy",
"description": "test L2 policy resource",
"l3_policy_id": "l3-policy-id"
}
}
}
}
'''
l3_policy_template = '''
{
"AWSTemplateFormatVersion" : "2010-09-09",
"Description" : "Template to test neutron l3 policy",
"Parameters" : {},
"Resources" : {
"l3_policy": {
"Type": "OS::Neutron::L3Policy",
"Properties": {
"name": "test-l3-policy",
"description": "test L3 policy resource",
"ip_version": "4",
"ip_pool": "10.20.20.0",
"subnet_prefix_length": 24
}
}
}
}
'''
class EndpointTest(HeatTestCase):
def setUp(self):
super(EndpointTest, self).setUp()
self.m.StubOutWithMock(gbpclient.Client, 'create_endpoint')
self.m.StubOutWithMock(gbpclient.Client, 'delete_endpoint')
self.m.StubOutWithMock(gbpclient.Client, 'show_endpoint')
self.m.StubOutWithMock(gbpclient.Client, 'update_endpoint')
self.stub_keystoneclient()
def create_endpoint(self):
gbpclient.Client.create_endpoint({
'endpoint': {
'name': 'test-endpoint',
'endpoint_group_id': 'epg-id',
"description": "test endpoint resource"
}
}).AndReturn({'endpoint': {'id': '5678'}})
snippet = template_format.parse(endpoint_template)
stack = utils.parse_stack(snippet)
resource_defns = stack.t.resource_definitions(stack)
return grouppolicy.Endpoint(
'endpoint', resource_defns['endpoint'], stack)
def test_create(self):
rsrc = self.create_endpoint()
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_endpoint({
'endpoint': {
'name': 'test-endpoint',
'endpoint_group_id': 'epg-id',
"description": "test endpoint resource"
}
}).AndRaise(grouppolicy.NeutronClientException())
self.m.ReplayAll()
snippet = template_format.parse(endpoint_template)
stack = utils.parse_stack(snippet)
resource_defns = stack.t.resource_definitions(stack)
rsrc = grouppolicy.Endpoint(
'endpoint', resource_defns['endpoint'], 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_endpoint('5678')
gbpclient.Client.show_endpoint('5678').AndRaise(
grouppolicy.NeutronClientException(status_code=404))
rsrc = self.create_endpoint()
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_endpoint('5678').AndRaise(
grouppolicy.NeutronClientException(status_code=404))
rsrc = self.create_endpoint()
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_endpoint('5678').AndRaise(
grouppolicy.NeutronClientException(status_code=400))
rsrc = self.create_endpoint()
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_attribute(self):
rsrc = self.create_endpoint()
gbpclient.Client.show_endpoint('5678').MultipleTimes(
).AndReturn(
{'endpoint': {'neutron_port_id': '1234'}})
self.m.ReplayAll()
scheduler.TaskRunner(rsrc.create)()
self.assertEqual('1234', rsrc.FnGetAtt('neutron_port_id'))
self.m.VerifyAll()
def test_attribute_failed(self):
rsrc = self.create_endpoint()
self.m.ReplayAll()
scheduler.TaskRunner(rsrc.create)()
error = self.assertRaises(exception.InvalidTemplateAttribute,
rsrc.FnGetAtt, 'l2_policy_id')
self.assertEqual(
'The Referenced Attribute (endpoint l2_policy_id) is '
'incorrect.', str(error))
self.m.VerifyAll()
def test_update(self):
rsrc = self.create_endpoint()
gbpclient.Client.update_endpoint(
'5678', {'endpoint': {'endpoint_group_id': 'epg_id_update'}})
self.m.ReplayAll()
scheduler.TaskRunner(rsrc.create)()
update_template = copy.deepcopy(rsrc.t)
update_template['Properties']['endpoint_group_id'] = 'epg_id_update'
scheduler.TaskRunner(rsrc.update, update_template)()
self.m.VerifyAll()
class EndpointGroupTest(HeatTestCase):
def setUp(self):
super(EndpointGroupTest, self).setUp()
self.m.StubOutWithMock(gbpclient.Client, 'create_endpoint_group')
self.m.StubOutWithMock(gbpclient.Client, 'delete_endpoint_group')
self.m.StubOutWithMock(gbpclient.Client, 'show_endpoint_group')
self.m.StubOutWithMock(gbpclient.Client, 'update_endpoint_group')
self.stub_keystoneclient()
def create_endpoint_group(self):
gbpclient.Client.create_endpoint_group({
"endpoint_group": {
"name": "test-endpoint-group",
"description": "test endpoint group resource",
"l2_policy_id": "l2-policy-id",
"provided_contracts": {
"contract1": "scope1",
"contract2": "scope2"
},
"consumed_contracts": {
"contract3": "scope3",
"contract4": "scope4"
}
}
}).AndReturn({'endpoint_group': {'id': '5678'}})
snippet = template_format.parse(endpoint_group_template)
stack = utils.parse_stack(snippet)
resource_defns = stack.t.resource_definitions(stack)
return grouppolicy.EndpointGroup(
'endpoint_group', resource_defns['endpoint_group'], stack)
def test_create(self):
rsrc = self.create_endpoint_group()
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_endpoint_group({
"endpoint_group": {
"name": "test-endpoint-group",
"description": "test endpoint group resource",
"l2_policy_id": "l2-policy-id",
"provided_contracts": {
"contract1": "scope1",
"contract2": "scope2"
},
"consumed_contracts": {
"contract3": "scope3",
"contract4": "scope4"
}
}
}).AndRaise(grouppolicy.NeutronClientException())
self.m.ReplayAll()
snippet = template_format.parse(endpoint_group_template)
stack = utils.parse_stack(snippet)
resource_defns = stack.t.resource_definitions(stack)
rsrc = grouppolicy.EndpointGroup(
'endpoint_group', resource_defns['endpoint_group'], 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_endpoint_group('5678')
gbpclient.Client.show_endpoint_group('5678').AndRaise(
grouppolicy.NeutronClientException(status_code=404))
rsrc = self.create_endpoint_group()
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_endpoint_group('5678').AndRaise(
grouppolicy.NeutronClientException(status_code=404))
rsrc = self.create_endpoint_group()
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_endpoint_group('5678').AndRaise(
grouppolicy.NeutronClientException(status_code=400))
rsrc = self.create_endpoint_group()
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_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(
'5678', {'endpoint_group': {'l2_policy_id': 'l2_id_update'}})
self.m.ReplayAll()
scheduler.TaskRunner(rsrc.create)()
update_template = copy.deepcopy(rsrc.t)
update_template['Properties']['l2_policy_id'] = 'l2_id_update'
scheduler.TaskRunner(rsrc.update, update_template)()
self.m.VerifyAll()
class L2PolicyTest(HeatTestCase):
def setUp(self):
super(L2PolicyTest, self).setUp()
self.m.StubOutWithMock(gbpclient.Client, 'create_l2_policy')
self.m.StubOutWithMock(gbpclient.Client, 'delete_l2_policy')
self.m.StubOutWithMock(gbpclient.Client, 'show_l2_policy')
self.m.StubOutWithMock(gbpclient.Client, 'update_l2_policy')
self.stub_keystoneclient()
def create_l2_policy(self):
gbpclient.Client.create_l2_policy({
'l2_policy': {
"name": "test-l2-policy",
"description": "test L2 policy resource",
"l3_policy_id": "l3-policy-id"
}
}).AndReturn({'l2_policy': {'id': '5678'}})
snippet = template_format.parse(l2_policy_template)
stack = utils.parse_stack(snippet)
resource_defns = stack.t.resource_definitions(stack)
return grouppolicy.L2Policy(
'l2_policy', resource_defns['l2_policy'], stack)
def test_create(self):
rsrc = self.create_l2_policy()
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_l2_policy({
'l2_policy': {
"name": "test-l2-policy",
"description": "test L2 policy resource",
"l3_policy_id": "l3-policy-id"
}
}).AndRaise(grouppolicy.NeutronClientException())
self.m.ReplayAll()
snippet = template_format.parse(l2_policy_template)
stack = utils.parse_stack(snippet)
resource_defns = stack.t.resource_definitions(stack)
rsrc = grouppolicy.L2Policy(
'l2_policy', resource_defns['l2_policy'], 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_l2_policy('5678')
gbpclient.Client.show_l2_policy('5678').AndRaise(
grouppolicy.NeutronClientException(status_code=404))
rsrc = self.create_l2_policy()
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_l2_policy('5678').AndRaise(
grouppolicy.NeutronClientException(status_code=404))
rsrc = self.create_l2_policy()
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_l2_policy('5678').AndRaise(
grouppolicy.NeutronClientException(status_code=400))
rsrc = self.create_l2_policy()
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_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(
'5678', {'l2_policy': {'l3_policy_id': 'l3_id_update'}})
self.m.ReplayAll()
scheduler.TaskRunner(rsrc.create)()
update_template = copy.deepcopy(rsrc.t)
update_template['Properties']['l3_policy_id'] = 'l3_id_update'
scheduler.TaskRunner(rsrc.update, update_template)()
self.m.VerifyAll()
class L3PolicyTest(HeatTestCase):
def setUp(self):
super(L3PolicyTest, self).setUp()
self.m.StubOutWithMock(gbpclient.Client, 'create_l3_policy')
self.m.StubOutWithMock(gbpclient.Client, 'delete_l3_policy')
self.m.StubOutWithMock(gbpclient.Client, 'show_l3_policy')
self.m.StubOutWithMock(gbpclient.Client, 'update_l3_policy')
self.stub_keystoneclient()
def create_l3_policy(self):
gbpclient.Client.create_l3_policy({
'l3_policy': {
"name": "test-l3-policy",
"description": "test L3 policy resource",
"ip_version": "4",
"ip_pool": "10.20.20.0",
"subnet_prefix_length": 24
}
}).AndReturn({'l3_policy': {'id': '5678'}})
snippet = template_format.parse(l3_policy_template)
stack = utils.parse_stack(snippet)
resource_defns = stack.t.resource_definitions(stack)
return grouppolicy.L3Policy(
'l3_policy', resource_defns['l3_policy'], stack)
def test_create(self):
rsrc = self.create_l3_policy()
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_l3_policy({
'l3_policy': {
"name": "test-l3-policy",
"description": "test L3 policy resource",
"ip_version": "4",
"ip_pool": "10.20.20.0",
"subnet_prefix_length": 24
}
}).AndRaise(grouppolicy.NeutronClientException())
self.m.ReplayAll()
snippet = template_format.parse(l3_policy_template)
stack = utils.parse_stack(snippet)
resource_defns = stack.t.resource_definitions(stack)
rsrc = grouppolicy.L3Policy(
'l3_policy', resource_defns['l3_policy'], 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_l3_policy('5678')
gbpclient.Client.show_l3_policy('5678').AndRaise(
grouppolicy.NeutronClientException(status_code=404))
rsrc = self.create_l3_policy()
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_l3_policy('5678').AndRaise(
grouppolicy.NeutronClientException(status_code=404))
rsrc = self.create_l3_policy()
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_l3_policy('5678').AndRaise(
grouppolicy.NeutronClientException(status_code=400))
rsrc = self.create_l3_policy()
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_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(
'5678', {'l3_policy': {'subnet_prefix_length': 28}})
self.m.ReplayAll()
scheduler.TaskRunner(rsrc.create)()
update_template = copy.deepcopy(rsrc.t)
update_template['Properties']['subnet_prefix_length'] = 28
scheduler.TaskRunner(rsrc.update, update_template)()
self.m.VerifyAll()

View File

@ -44,4 +44,8 @@ input_file = gbpautomation/locale/group-based-policy-automation.pot
[extract_messages]
keywords = _ gettext ngettext l_ lazy_gettext
mapping_file = babel.cfg
output_file = gbpautomation/locale/group-based-policy-automation.pot
output_file = gbpautomation/locale/group-based-policy-automation.pot
[entry_points]
heat.clients =
grouppolicy = gbpautomation.heat.engine.clients.os.grouppolicy:GBPClientPlugin

View File

@ -3,12 +3,14 @@
# process, which may cause wedges in the gate later.
-e git://github.com/openstack/heat.git@stable/juno#egg=heat
-e git://github.com/stackforge/python-group-based-policy-client.git@master#egg=gbpclient
# Hacking already pins down pep8, pyflakes and flake8
hacking>=0.8.0,<0.9
coverage>=3.6
discover
lockfile>=0.8
mock>=1.0
python-subunit>=0.0.18
mox>=0.5.3
MySQL-python
oslosphinx>=2.2.0 # Apache-2.0