From bef2907e057fc781866f3df73bb708eedbeecfea Mon Sep 17 00:00:00 2001 From: Senthilnathan Murugappan Date: Mon, 28 Mar 2016 00:52:26 -0700 Subject: [PATCH] use loadbalancerv2 extensions from neutron_lbaas rather than v1 extensions Few other fixes: 1) Check if member exists in the pool before read/list/delete 2) Loadbalancer pool to Listener relationship is made 1:1 3) Healthmonitor to Pool relationship is made 1:1 Change-Id: Ic624b343d450c218b88b892dde5c067469b8e678 Closes-Bug:#1536373 Partial-Bug:1536374 --- .../loadbalancer/resource_manager.py | 2 + .../opencontrail/loadbalancer/v2/listener.py | 11 ++--- .../loadbalancer/v2/loadbalancer.py | 8 ++-- .../loadbalancer/v2/loadbalancer_db.py | 4 +- .../v2/loadbalancer_healthmonitor.py | 14 ++++-- .../loadbalancer/v2/loadbalancer_member.py | 43 ++++++++++++------- .../loadbalancer/v2/loadbalancer_pool.py | 14 ++++-- 7 files changed, 62 insertions(+), 34 deletions(-) diff --git a/neutron_plugin_contrail/plugins/opencontrail/loadbalancer/resource_manager.py b/neutron_plugin_contrail/plugins/opencontrail/loadbalancer/resource_manager.py index 219852e..41f3c94 100644 --- a/neutron_plugin_contrail/plugins/opencontrail/loadbalancer/resource_manager.py +++ b/neutron_plugin_contrail/plugins/opencontrail/loadbalancer/resource_manager.py @@ -19,6 +19,8 @@ class LoadbalancerMethodInvalid(n_exc.BadRequest): message = "Method %(lb_method)s not supported for pool %(pool_id)s" +class EntityInUse(n_exc.InUse): + message = "%(name)s %(id)s is in use" @six.add_metaclass(ABCMeta) class ResourceManager(object): diff --git a/neutron_plugin_contrail/plugins/opencontrail/loadbalancer/v2/listener.py b/neutron_plugin_contrail/plugins/opencontrail/loadbalancer/v2/listener.py index da90c04..9e32055 100644 --- a/neutron_plugin_contrail/plugins/opencontrail/loadbalancer/v2/listener.py +++ b/neutron_plugin_contrail/plugins/opencontrail/loadbalancer/v2/listener.py @@ -20,7 +20,7 @@ from vnc_api.vnc_api import SecurityGroup from vnc_api.vnc_api import LoadbalancerListener, LoadbalancerListenerType -from .. resource_manager import ResourceManager +from .. resource_manager import ResourceManager, EntityInUse from .. import utils import uuid @@ -79,10 +79,10 @@ def resource_delete(self, id): return self._api.loadbalancer_listener_delete(id=id) def get_exception_notfound(self, id=None): - return listener.EntityNotFound(id=id) + return loadbalancerv2.EntityNotFound(name=self.neutron_name, id=id) def get_exception_inuse(self, id=None): - pass + return EntityInUse(name=self.neutron_name, id=id) @property def neutron_name(self): @@ -101,7 +101,8 @@ def create(self, context, listener): try: lb = self._api.loadbalancer_read(id=l['loadbalancer_id']) except NoIdError: - raise loadbalancerv2.EntityNotFound(id=v['loadbalancer_id']) + raise loadbalancerv2.EntityNotFound(name='Loadbalancer', + id=v['loadbalancer_id']) project_id = lb.parent_uuid if str(uuid.UUID(tenant_id)) != project_id: raise n_exc.NotAuthorized() @@ -129,7 +130,7 @@ def delete_listener(self, context, id): try: ll = self._api.loadbalancer_listener_read(id=id) except NoIdError: - listener.EntityNotFound(id=id) + loadbalancerv2.EntityNotFound(name=self.neutron_name, id=id) super(ListenerManager, self).delete(context, id) diff --git a/neutron_plugin_contrail/plugins/opencontrail/loadbalancer/v2/loadbalancer.py b/neutron_plugin_contrail/plugins/opencontrail/loadbalancer/v2/loadbalancer.py index 4bfb5ba..685af54 100644 --- a/neutron_plugin_contrail/plugins/opencontrail/loadbalancer/v2/loadbalancer.py +++ b/neutron_plugin_contrail/plugins/opencontrail/loadbalancer/v2/loadbalancer.py @@ -22,7 +22,7 @@ from vnc_api.vnc_api import SecurityGroup from vnc_api.vnc_api import Loadbalancer, LoadbalancerType -from .. resource_manager import ResourceManager +from .. resource_manager import ResourceManager, EntityInUse from .. import utils import uuid @@ -111,10 +111,10 @@ def resource_delete(self, id): return self._api.loadbalancer_delete(id=id) def get_exception_notfound(self, id=None): - return loadbalancer.VipNotFound(vip_id=id) + return loadbalancerv2.EntityNotFound(name=self.neutron_name, id=id) def get_exception_inuse(self, id=None): - pass + return EntityInUse(name=self.neutron_name, id=id) @property def neutron_name(self): @@ -211,7 +211,7 @@ def delete(self, context, id): try: lb = self._api.loadbalancer_read(id=id) except NoIdError: - loadbalancer.EntityNotFound(id=id) + loadbalancerv2.EntityNotFound(name=self.neutron_name, id=id) super(LoadbalancerManager, self).delete(context, id) self._delete_virtual_interface( diff --git a/neutron_plugin_contrail/plugins/opencontrail/loadbalancer/v2/loadbalancer_db.py b/neutron_plugin_contrail/plugins/opencontrail/loadbalancer/v2/loadbalancer_db.py index feaf84c..93e6c1a 100644 --- a/neutron_plugin_contrail/plugins/opencontrail/loadbalancer/v2/loadbalancer_db.py +++ b/neutron_plugin_contrail/plugins/opencontrail/loadbalancer/v2/loadbalancer_db.py @@ -146,10 +146,10 @@ def delete_pool(self, context, id): return self._pool_manager.delete(context, id) def get_pool_members(self, context, pool_id, filters=None, fields=None): - return self._member_manager.get_collection(context, filters, fields) + return self._member_manager.get_collection(context, pool_id, filters, fields) def get_pool_member(self, context, id, pool_id, fields=None): - return self._member_manager.get_resource(context, id, fields) + return self._member_manager.get_resource(context, id, pool_id, fields) def create_pool_member(self, context, pool_id, member): try: diff --git a/neutron_plugin_contrail/plugins/opencontrail/loadbalancer/v2/loadbalancer_healthmonitor.py b/neutron_plugin_contrail/plugins/opencontrail/loadbalancer/v2/loadbalancer_healthmonitor.py index e481086..f23b23f 100644 --- a/neutron_plugin_contrail/plugins/opencontrail/loadbalancer/v2/loadbalancer_healthmonitor.py +++ b/neutron_plugin_contrail/plugins/opencontrail/loadbalancer/v2/loadbalancer_healthmonitor.py @@ -14,7 +14,7 @@ from vnc_api.vnc_api import LoadbalancerHealthmonitor from vnc_api.vnc_api import LoadbalancerHealthmonitorType -from .. resource_manager import ResourceManager +from .. resource_manager import ResourceManager, EntityInUse class LoadbalancerHealthmonitorManager(ResourceManager): @@ -82,10 +82,10 @@ def resource_delete(self, id): return self._api.loadbalancer_healthmonitor_delete(id=id) def get_exception_notfound(self, id=None): - return loadbalancer.HealthMonitorNotFound(monitor_id=id) + return loadbalancerv2.EntityNotFound(name=self.neutron_name, id=id) def get_exception_inuse(self, id=None): - return loadbalancer.HealthMonitorInUse(monitor_id=id) + return EntityInUse(name=self.neutron_name, id=id) @property def neutron_name(self): @@ -111,6 +111,14 @@ def create(self, context, healthmonitor): id_perms=id_perms) monitor_db.uuid = uuid + try: + pool = self._api.loadbalancer_pool_read(id=m['pool_id']) + except NoIdError: + raise loadbalancerv2.EntityNotFound(name='Pool', id=m['pool_id']) + exist_hm_refs = pool.get_loadbalancer_healthmonitor_refs() + if exist_hm_refs is not None: + raise loadbalancerv2.OneHealthMonitorPerPool(pool_id=m['pool_id'], + hm_id=exist_hm_refs[0]['uuid']) self._api.loadbalancer_healthmonitor_create(monitor_db) self._api.ref_update('loadbalancer-pool', m['pool_id'], 'loadbalancer-health-monitor', uuid, None, 'ADD') diff --git a/neutron_plugin_contrail/plugins/opencontrail/loadbalancer/v2/loadbalancer_member.py b/neutron_plugin_contrail/plugins/opencontrail/loadbalancer/v2/loadbalancer_member.py index 8906175..cf8eaaa 100644 --- a/neutron_plugin_contrail/plugins/opencontrail/loadbalancer/v2/loadbalancer_member.py +++ b/neutron_plugin_contrail/plugins/opencontrail/loadbalancer/v2/loadbalancer_member.py @@ -85,26 +85,27 @@ def resource_list(self, tenant_id=None): response = {'loadbalancer-members': member_list} return response - def get_collection(self, context, filters=None, fields=None): + def get_resource(self, context, id, pool_id, fields=None): + res = super(LoadbalancerMemberManager, self).get_resource(context, id) + if res and res['pool_id'] != pool_id: + raise loadbalancerv2.MemberNotFoundForPool(member_id=res['id'], + pool_id=res['pool_id']) + return self._fields(res, fields) + + def get_collection(self, context, pool_id, filters=None, fields=None): """ Optimize the query for members in a pool. """ - if 'pool_id' not in filters: - return super(LoadbalancerMemberManager, self).get_collection( - context, filters, fields) - member_list = [] - for pool in filters['pool_id']: - pool_members = self._api.loadbalancer_members_list( - parent_id=pool) - if 'loadbalancer-members' in pool_members: - member_list.extend(pool_members['loadbalancer-members']) + pool_members = self._api.loadbalancer_members_list( + parent_id=pool_id) + if 'loadbalancer-members' in pool_members: + member_list.extend(pool_members['loadbalancer-members']) response = [] for m in member_list: res = self._get_resource_dict(m['uuid'], filters, fields) if res is not None and self._is_authorized(context, res): response.append(res) - return response def resource_update(self, obj): @@ -114,7 +115,7 @@ def resource_delete(self, id): return self._api.loadbalancer_member_delete(id=id) def get_exception_notfound(self, id=None): - return loadbalancer.MemberNotFound(member_id=id) + return loadbalancerv2.EntityNotFound(name=self.neutron_name, id=id) def get_exception_inuse(self, id=None): pass @@ -135,7 +136,7 @@ def create(self, context, pool_id, member): try: pool = self._api.loadbalancer_pool_read(id=pool_id) except NoIdError: - raise loadbalancer.PoolNotFound(pool_id=pool_id) + raise loadbalancerv2.EntityNotFound(name='Pool', id=pool_id) tenant_id = self._get_tenant_id_for_create(context, m) if str(uuid.UUID(tenant_id)) != pool.parent_uuid: @@ -164,15 +165,25 @@ def delete(self, context, id, pool_id): try: member = self._api.loadbalancer_member_read(id=id) except NoIdError: - loadbalancer.EntityNotFound(id=id) + raise loadbalancerv2.EntityNotFound(name=self.neutron_name, id=id) + try: + pool = self._api.loadbalancer_pool_read(id=pool_id) + except NoIdError: + raise loadbalancerv2.EntityNotFound(name='Pool', + id=pool_id) + if id not in [member['uuid'] for member in + pool.get_loadbalancer_members() or []]: + raise loadbalancerv2.MemberNotFoundForPool(member_id=id, + pool_id=pool_id) super(LoadbalancerMemberManager, self).delete(context, id) def update_object(self, member_db, id, pool_id, m): try: pool = self._api.loadbalancer_pool_read(id=pool_id) except NoIdError: - raise loadbalancer.PoolNotFound(pool_id=pool_id) + raise loadbalancerv2.EntityNotFound(name='Pool', + id=pool_id) db_props = member_db.get_loadbalancer_member_properties() members = pool.get_loadbalancer_members() @@ -182,7 +193,7 @@ def update_object(self, member_db, id, pool_id, m): props = member_obj.get_loadbalancer_member_properties() if ((props.get_address() == db_props.get_address()) and (props.get_protocol_port() == db_props.get_protocol_port())): - raise loadbalancer.MemberExists( + raise loadbalancerv2.MemberExists( address=props.get_address(), port=props.get_protocol_port(), pool=pool_id) diff --git a/neutron_plugin_contrail/plugins/opencontrail/loadbalancer/v2/loadbalancer_pool.py b/neutron_plugin_contrail/plugins/opencontrail/loadbalancer/v2/loadbalancer_pool.py index a92443c..a99a9bb 100644 --- a/neutron_plugin_contrail/plugins/opencontrail/loadbalancer/v2/loadbalancer_pool.py +++ b/neutron_plugin_contrail/plugins/opencontrail/loadbalancer/v2/loadbalancer_pool.py @@ -15,7 +15,7 @@ from oslo_utils import uuidutils from vnc_api.vnc_api import * -from .. resource_manager import ResourceManager +from .. resource_manager import ResourceManager, EntityInUse from .. resource_manager import LoadbalancerMethodInvalid import uuid @@ -103,10 +103,10 @@ def resource_delete(self, id): return self._api.loadbalancer_pool_delete(id=id) def get_exception_notfound(self, id=None): - return loadbalancer.PoolNotFound(pool_id=id) + return loadbalancerv2.EntityNotFound(name=self.neutron_name, id=id) def get_exception_inuse(self, id=None): - return loadbalancer.PoolInUse(pool_id=id) + return EntityInUse(name=self.neutron_name, id=id) @property def neutron_name(self): @@ -136,7 +136,8 @@ def create(self, context, pool): try: ll = self._api.loadbalancer_listener_read(id=p['listener_id']) except NoIdError: - raise loadbalancer.EntityNotFound(id=p['listener_id']) + raise loadbalancerv2.EntityNotFound(name='Listener', + id=p['listener_id']) project_id = ll.parent_uuid if str(uuid.UUID(tenant_id)) != project_id: raise n_exc.NotAuthorized() @@ -159,6 +160,11 @@ def create(self, context, pool): if ll: + pool_exists = ll.get_loadbalancer_pool_back_refs() + if pool_exists is not None: + raise loadbalancerv2.OnePoolPerListener( + listener_id=p['listener_id'], + pool_id=pool_exists[0]['uuid']) pool.set_loadbalancer_listener(ll) self._api.loadbalancer_pool_create(pool)