From d0787393ce1ba073a317c3dccff8251068a707ac Mon Sep 17 00:00:00 2001 From: rabi Date: Tue, 12 Dec 2017 12:40:49 +0530 Subject: [PATCH] Add octavia client plugin and constraints Change-Id: I0fa34d19781c49ede8743defe72bbdc63f375896 Partial-Bug: #1737567 --- heat/engine/clients/os/octavia.py | 98 +++++++++++++++++++++++ heat/tests/clients/test_octavia_client.py | 24 ++++++ requirements.txt | 1 + setup.cfg | 4 + 4 files changed, 127 insertions(+) create mode 100644 heat/engine/clients/os/octavia.py create mode 100644 heat/tests/clients/test_octavia_client.py diff --git a/heat/engine/clients/os/octavia.py b/heat/engine/clients/os/octavia.py new file mode 100644 index 0000000000..b8ade71168 --- /dev/null +++ b/heat/engine/clients/os/octavia.py @@ -0,0 +1,98 @@ +# +# 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 octaviaclient.api import constants +from octaviaclient.api.v2 import octavia +from osc_lib import exceptions + +from heat.engine.clients import client_plugin +from heat.engine import constraints + +CLIENT_NAME = 'octavia' +DEFAULT_FIND_ATTR = 'name' + + +def _is_translated_exception(ex, code): + return (isinstance(ex, octavia.OctaviaClientException) + and ex.code == code) + + +class OctaviaClientPlugin(client_plugin.ClientPlugin): + + exceptions_module = octavia + + service_types = [LOADBALANCER] = ['load-balancer'] + + supported_versions = [V2] = ['2'] + + default_version = V2 + + def _create(self, version=None): + interface = self._get_client_option(CLIENT_NAME, 'endpoint_type') + endpoint = self.url_for(service_type=self.LOADBALANCER, + endpoint_type=interface) + return octavia.OctaviaAPI( + session=self.context.keystone_session, + service_type=self.LOADBALANCER, + endpoint=endpoint) + + def is_not_found(self, ex): + return isinstance( + ex, exceptions.NotFound) or _is_translated_exception(ex, 404) + + def is_over_limit(self, ex): + return isinstance( + ex, exceptions.OverLimit) or _is_translated_exception(ex, 413) + + def is_conflict(self, ex): + return isinstance( + ex, exceptions.Conflict) or _is_translated_exception(ex, 409) + + def get_pool(self, value): + pool = self.client().find(path=constants.BASE_POOL_URL, + value=value, attr=DEFAULT_FIND_ATTR) + return pool['id'] + + def get_listener(self, value): + lsnr = self.client().find(path=constants.BASE_LISTENER_URL, + value=value, attr=DEFAULT_FIND_ATTR) + return lsnr['id'] + + def get_loadbalancer(self, value): + lb = self.client().find(path=constants.BASE_LOADBALANCER_URL, + value=value, attr=DEFAULT_FIND_ATTR) + return lb['id'] + + +class OctaviaConstraint(constraints.BaseCustomConstraint): + + expected_exceptions = (exceptions.NotFound, + octavia.OctaviaClientException) + base_url = None + + def validate_with_client(self, client, value): + octavia_client = client.client(CLIENT_NAME) + octavia_client.find(path=self.base_url, value=value, + attr=DEFAULT_FIND_ATTR) + + +class LoadbalancerConstraint(OctaviaConstraint): + base_url = constants.BASE_LOADBALANCER_URL + + +class ListenerConstraint(OctaviaConstraint): + base_url = constants.BASE_LISTENER_URL + + +class PoolConstraint(OctaviaConstraint): + base_url = constants.BASE_POOL_URL diff --git a/heat/tests/clients/test_octavia_client.py b/heat/tests/clients/test_octavia_client.py new file mode 100644 index 0000000000..092f1aa88e --- /dev/null +++ b/heat/tests/clients/test_octavia_client.py @@ -0,0 +1,24 @@ +# +# 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.tests import common +from heat.tests import utils + + +class OctaviaClientPluginTest(common.HeatTestCase): + + def test_create(self): + context = utils.dummy_context() + plugin = context.clients.client_plugin('octavia') + client = plugin.client() + self.assertIsNotNone(client.endpoint) diff --git a/requirements.txt b/requirements.txt index 3e76270cf7..6344700085 100644 --- a/requirements.txt +++ b/requirements.txt @@ -44,6 +44,7 @@ python-mistralclient>=3.1.0 # Apache-2.0 python-monascaclient>=1.7.0 # Apache-2.0 python-neutronclient>=6.3.0 # Apache-2.0 python-novaclient>=9.1.0 # Apache-2.0 +python-octaviaclient>=1.0.0 # Apache-2.0 python-openstackclient>=3.12.0 # Apache-2.0 python-saharaclient>=1.4.0 # Apache-2.0 python-senlinclient>=1.1.0 # Apache-2.0 diff --git a/setup.cfg b/setup.cfg index e09e72c1d3..78514baeec 100644 --- a/setup.cfg +++ b/setup.cfg @@ -80,6 +80,7 @@ heat.clients = monasca = heat.engine.clients.os.monasca:MonascaClientPlugin nova = heat.engine.clients.os.nova:NovaClientPlugin neutron = heat.engine.clients.os.neutron:NeutronClientPlugin + octavia = heat.engine.clients.os.octavia:OctaviaClientPlugin openstack = heat.engine.clients.os.openstacksdk:OpenStackSDKPlugin sahara = heat.engine.clients.os.sahara:SaharaClientPlugin senlin = heat.engine.clients.os.senlin:SenlinClientPlugin @@ -148,6 +149,9 @@ heat.constraints = nova.keypair = heat.engine.clients.os.nova:KeypairConstraint nova.network = heat.engine.constraint.common_constraints:TestConstraintDelay nova.server = heat.engine.clients.os.nova:ServerConstraint + octavia.listener = heat.engine.clients.os.octavia:ListenerConstraint + octavia.loadbalancer = heat.engine.clients.os.octavia:LoadbalancerConstraint + octavia.pool = heat.engine.clients.os.octavia:PoolConstraint sahara.cluster = heat.engine.clients.os.sahara:ClusterConstraint sahara.cluster_template = heat.engine.clients.os.sahara:ClusterTemplateConstraint sahara.data_source = heat.engine.clients.os.sahara:DataSourceConstraint