LBaaS v2 custom constraints

Add custom constraints for LBaaS v2 resources, and update the resources
to include these constraints where needed.

blueprint: lbaasv2-suport

Change-Id: Id87fab6af9fc6009c721dbc1456908d73d234438
This commit is contained in:
Bryan Jones 2015-10-07 20:15:18 +00:00
parent 7f33380327
commit 748b8c96f3
7 changed files with 144 additions and 60 deletions

View File

@ -21,7 +21,6 @@ from oslo_utils import uuidutils
from heat.common import cache
from heat.common import exception
from heat.engine.clients import client_plugin
from heat.engine import constraints
MEMOIZE = core.get_memoization_decorator(conf=cfg.CONF,
@ -144,50 +143,3 @@ class NeutronClientPlugin(client_plugin.ClientPlugin):
else:
raise exception.PhysicalResourceNameAmbiguity(name=sg)
return seclist
class NetworkConstraint(constraints.BaseCustomConstraint):
expected_exceptions = (exceptions.NeutronClientException,
exception.NovaNetworkNotFound,
exception.PhysicalResourceNameAmbiguity)
def validate_with_client(self, client, value):
try:
neutron_client = client.client('neutron')
except Exception:
# is not using neutron
client.client_plugin('nova').get_nova_network_id(value)
else:
neutronV20.find_resourceid_by_name_or_id(
neutron_client, 'network', value)
class PortConstraint(constraints.BaseCustomConstraint):
expected_exceptions = (exceptions.NeutronClientException,)
def validate_with_client(self, client, value):
neutron_client = client.client('neutron')
neutronV20.find_resourceid_by_name_or_id(
neutron_client, 'port', value)
class RouterConstraint(constraints.BaseCustomConstraint):
expected_exceptions = (exceptions.NeutronClientException,)
def validate_with_client(self, client, value):
neutron_client = client.client('neutron')
neutronV20.find_resourceid_by_name_or_id(
neutron_client, 'router', value)
class SubnetConstraint(constraints.BaseCustomConstraint):
expected_exceptions = (exceptions.NeutronClientException,)
def validate_with_client(self, client, value):
neutron_client = client.client('neutron')
neutronV20.find_resourceid_by_name_or_id(
neutron_client, 'subnet', value)

View File

@ -0,0 +1,51 @@
#
# All Rights Reserved.
# 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.
#
# Copyright 2015 IBM Corp.
from neutronclient.common import exceptions
from neutronclient.neutron import v2_0 as neutronV20
from heat.engine import constraints
class LoadbalancerConstraint(constraints.BaseCustomConstraint):
expected_exceptions = (exceptions.NeutronClientException,)
def validate_with_client(self, client, value):
neutron_client = client.client('neutron')
neutronV20.find_resourceid_by_name_or_id(
neutron_client, 'loadbalancer', value)
class ListenerConstraint(constraints.BaseCustomConstraint):
expected_exceptions = (exceptions.NeutronClientException,)
def validate_with_client(self, client, value):
neutron_client = client.client('neutron')
neutronV20.find_resourceid_by_name_or_id(
neutron_client, 'listener', value)
class PoolConstraint(constraints.BaseCustomConstraint):
expected_exceptions = (exceptions.NeutronClientException,)
def validate_with_client(self, client, value):
neutron_client = client.client('neutron')
# v2 pool is called lbaas_pool to differentiate from v1 pool
neutronV20.find_resourceid_by_name_or_id(
neutron_client, 'lbaas_pool', value)

View File

@ -0,0 +1,67 @@
#
# 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.
#
# Copyright 2015 IBM Corp.
from neutronclient.common import exceptions
from neutronclient.neutron import v2_0 as neutronV20
from heat.common import exception
from heat.engine import constraints
class NetworkConstraint(constraints.BaseCustomConstraint):
expected_exceptions = (exceptions.NeutronClientException,
exception.NovaNetworkNotFound,
exception.PhysicalResourceNameAmbiguity)
def validate_with_client(self, client, value):
try:
neutron_client = client.client('neutron')
except Exception:
# is not using neutron
client.client_plugin('nova').get_nova_network_id(value)
else:
neutronV20.find_resourceid_by_name_or_id(
neutron_client, 'network', value)
class PortConstraint(constraints.BaseCustomConstraint):
expected_exceptions = (exceptions.NeutronClientException,)
def validate_with_client(self, client, value):
neutron_client = client.client('neutron')
neutronV20.find_resourceid_by_name_or_id(
neutron_client, 'port', value)
class RouterConstraint(constraints.BaseCustomConstraint):
expected_exceptions = (exceptions.NeutronClientException,)
def validate_with_client(self, client, value):
neutron_client = client.client('neutron')
neutronV20.find_resourceid_by_name_or_id(
neutron_client, 'router', value)
class SubnetConstraint(constraints.BaseCustomConstraint):
expected_exceptions = (exceptions.NeutronClientException,)
def validate_with_client(self, client, value):
neutron_client = client.client('neutron')
neutronV20.find_resourceid_by_name_or_id(
neutron_client, 'subnet', value)

View File

@ -16,6 +16,8 @@ from neutronclient.common import exceptions as qe
from heat.common import exception
from heat.engine.clients.os import neutron
from heat.engine.clients.os.neutron import lbaas_constraints as lc
from heat.engine.clients.os.neutron import neutron_constraints as nc
from heat.tests import common
from heat.tests import utils
@ -154,17 +156,26 @@ class NeutronClientPluginTests(NeutronClientPluginTestCase):
class NeutronConstraintsValidate(common.HeatTestCase):
scenarios = [
('validate_network',
dict(constraint_class=neutron.NetworkConstraint,
dict(constraint_class=nc.NetworkConstraint,
resource_type='network')),
('validate_port',
dict(constraint_class=neutron.PortConstraint,
dict(constraint_class=nc.PortConstraint,
resource_type='port')),
('validate_router',
dict(constraint_class=neutron.RouterConstraint,
dict(constraint_class=nc.RouterConstraint,
resource_type='router')),
('validate_subnet',
dict(constraint_class=neutron.SubnetConstraint,
resource_type='subnet'))
dict(constraint_class=nc.SubnetConstraint,
resource_type='subnet')),
('validate_loadbalancer',
dict(constraint_class=lc.LoadbalancerConstraint,
resource_type='loadbalancer')),
('validate_listener',
dict(constraint_class=lc.ListenerConstraint,
resource_type='listener')),
('validate_pool',
dict(constraint_class=lc.PoolConstraint,
resource_type='lbaas_pool'))
]
def test_validate(self):

View File

@ -29,7 +29,7 @@ from heat.common import policy
from heat.engine.clients.os import cinder
from heat.engine.clients.os import glance
from heat.engine.clients.os import keystone
from heat.engine.clients.os import neutron
from heat.engine.clients.os.neutron import neutron_constraints as neutron
from heat.engine.clients.os import nova
from heat.engine.clients.os import sahara
from heat.engine.clients.os import trove

View File

@ -1341,8 +1341,8 @@ class ResourceTest(common.HeatTestCase):
def _test_skip_validation_if_custom_constraint(self, tmpl):
stack = parser.Stack(utils.dummy_context(), 'test', tmpl)
stack.store()
path = ('heat.engine.clients.os.neutron.NetworkConstraint.'
'validate_with_client')
path = ('heat.engine.clients.os.neutron.neutron_constraints.'
'NetworkConstraint.validate_with_client')
with mock.patch(path) as mock_validate:
mock_validate.side_effect = neutron_exp.NeutronClientException
rsrc2 = stack['bar']

View File

@ -70,10 +70,13 @@ heat.clients =
heat.constraints =
nova.flavor = heat.engine.clients.os.nova:FlavorConstraint
nova.network = heat.engine.clients.os.nova:NetworkConstraint
neutron.network = heat.engine.clients.os.neutron:NetworkConstraint
neutron.port = heat.engine.clients.os.neutron:PortConstraint
neutron.router = heat.engine.clients.os.neutron:RouterConstraint
neutron.subnet = heat.engine.clients.os.neutron:SubnetConstraint
neutron.network = heat.engine.clients.os.neutron.neutron_constraints:NetworkConstraint
neutron.port = heat.engine.clients.os.neutron.neutron_constraints:PortConstraint
neutron.router = heat.engine.clients.os.neutron.neutron_constraints:RouterConstraint
neutron.subnet = heat.engine.clients.os.neutron.neutron_constraints:SubnetConstraint
neutron.lbaas.loadbalancer = heat.engine.clients.os.neutron.lbaas_constraints:LoadbalancerConstraint
neutron.lbaas.listener = heat.engine.clients.os.neutron.lbaas_constraints:ListenerConstraint
neutron.lbaas.pool = heat.engine.clients.os.neutron.lbaas_constraints:PoolConstraint
glance.image = heat.engine.clients.os.glance:ImageConstraint
iso_8601 = heat.engine.constraint.common_constraints:ISO8601Constraint
nova.server = heat.engine.clients.os.nova:ServerConstraint