From 4de8f1ee665bae051644e6dd6f5d8f9c52e7f925 Mon Sep 17 00:00:00 2001 From: Adit Sarfaty Date: Tue, 19 Mar 2019 07:49:08 +0000 Subject: [PATCH] Revert "NSX|V3: Simplify LBaaS implementation" This reverts commit 31770cf52a2583fbf012b99e08fe7f068bdef166. Change-Id: Ibbd1ffdea6de5d64dec0ad4eac94185aa5c7de77 --- ...asv2-error-no-member-635ffc6308289aca.yaml | 7 - .../alembic_migrations/versions/EXPAND_HEAD | 2 +- .../99bfcb6003c6_lbaas_error_no_member.py | 38 ----- .../nsx_v3/implementation/listener_mgr.py | 55 +++---- .../nsx_v3/implementation/loadbalancer_mgr.py | 84 +---------- .../lbaas/nsx_v3/implementation/member_mgr.py | 110 +++++++++++++- .../unit/services/lbaas/test_nsxv3_driver.py | 139 ++++++++++++++++-- 7 files changed, 265 insertions(+), 170 deletions(-) delete mode 100644 releasenotes/notes/nsxv3-lbaasv2-error-no-member-635ffc6308289aca.yaml delete mode 100644 vmware_nsx/db/migration/alembic_migrations/versions/stein/expand/99bfcb6003c6_lbaas_error_no_member.py diff --git a/releasenotes/notes/nsxv3-lbaasv2-error-no-member-635ffc6308289aca.yaml b/releasenotes/notes/nsxv3-lbaasv2-error-no-member-635ffc6308289aca.yaml deleted file mode 100644 index dd96a26d97..0000000000 --- a/releasenotes/notes/nsxv3-lbaasv2-error-no-member-635ffc6308289aca.yaml +++ /dev/null @@ -1,7 +0,0 @@ ---- -prelude: > - NSXv3 plugin will mark unused loadbalancers in ERROR state. -features: - - | - Upon upgrade to Stein, unused LBaaS-v2 loadbalancers, which have no members - will be marked in ERROR state, and cannot be used. diff --git a/vmware_nsx/db/migration/alembic_migrations/versions/EXPAND_HEAD b/vmware_nsx/db/migration/alembic_migrations/versions/EXPAND_HEAD index 84d6dafa9c..92707c7b04 100644 --- a/vmware_nsx/db/migration/alembic_migrations/versions/EXPAND_HEAD +++ b/vmware_nsx/db/migration/alembic_migrations/versions/EXPAND_HEAD @@ -1 +1 @@ -99bfcb6003c6 +fc6308289aca diff --git a/vmware_nsx/db/migration/alembic_migrations/versions/stein/expand/99bfcb6003c6_lbaas_error_no_member.py b/vmware_nsx/db/migration/alembic_migrations/versions/stein/expand/99bfcb6003c6_lbaas_error_no_member.py deleted file mode 100644 index a584feaa37..0000000000 --- a/vmware_nsx/db/migration/alembic_migrations/versions/stein/expand/99bfcb6003c6_lbaas_error_no_member.py +++ /dev/null @@ -1,38 +0,0 @@ -# Copyright 2019 VMware, Inc. -# -# 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. - -"""lbaas_error_no_member - -Revision ID: 99bfcb6003c6 -Revises: fc6308289aca -Create Date: 2019-03-07 11:27:00.000000 -""" - -from alembic import op - -from neutron.db import migration - -# revision identifiers, used by Alembic. -revision = '99bfcb6003c6' -down_revision = 'fc6308289aca' - - -def upgrade(): - if (migration.schema_has_table('nsxv3_lbaas_loadbalancers') and - migration.schema_has_table('lbaas_loadbalancers')): - # Mark as ERROR loadbalancers without nsx mapping - op.execute("UPDATE lbaas_loadbalancers " - "SET provisioning_status='ERROR' " - "where id not in (select loadbalancer_id from " - "nsxv3_lbaas_loadbalancers)") diff --git a/vmware_nsx/services/lbaas/nsx_v3/implementation/listener_mgr.py b/vmware_nsx/services/lbaas/nsx_v3/implementation/listener_mgr.py index 45706f1582..eb89a800f9 100644 --- a/vmware_nsx/services/lbaas/nsx_v3/implementation/listener_mgr.py +++ b/vmware_nsx/services/lbaas/nsx_v3/implementation/listener_mgr.py @@ -149,20 +149,16 @@ class EdgeListenerManagerFromDict(base_mgr.Nsxv3LoadbalancerBaseManager): # server to the lb service binding = nsx_db.get_nsx_lbaas_loadbalancer_binding( context.session, lb_id) - if not binding: - completor(success=False) - msg = _('Failed to get loadbalancer %s binding') % lb_id - raise n_exc.BadRequest(resource='lbaas-listener', msg=msg) - - lb_service_id = binding['lb_service_id'] - try: - service_client.add_virtual_server(lb_service_id, - virtual_server['id']) - except nsxlib_exc.ManagerError: - completor(success=False) - msg = _('Failed to add virtual server to lb service ' - 'at NSX backend') - raise n_exc.BadRequest(resource='lbaas-listener', msg=msg) + if binding: + lb_service_id = binding['lb_service_id'] + try: + service_client.add_virtual_server(lb_service_id, + virtual_server['id']) + except nsxlib_exc.ManagerError: + completor(success=False) + msg = _('Failed to add virtual server to lb service ' + 'at NSX backend') + raise n_exc.BadRequest(resource='lbaas-listener', msg=msg) nsx_db.add_nsx_lbaas_listener_binding( context.session, lb_id, listener['id'], app_profile_id, @@ -223,24 +219,19 @@ class EdgeListenerManagerFromDict(base_mgr.Nsxv3LoadbalancerBaseManager): app_profile_id = binding['app_profile_id'] lb_binding = nsx_db.get_nsx_lbaas_loadbalancer_binding( context.session, lb_id) - if not lb_binding: - completor(success=False) - msg = (_('Failed to delete virtual server: %(listener)s: ' - 'loadbalancer %(lb)s mapping was not found') % - {'listener': listener['id'], 'lb': lb_id}) - raise n_exc.BadRequest(resource='lbaas-listener', msg=msg) - try: - lbs_id = lb_binding.get('lb_service_id') - lb_service = service_client.get(lbs_id) - vs_list = lb_service.get('virtual_server_ids') - if vs_list and vs_id in vs_list: - service_client.remove_virtual_server(lbs_id, vs_id) - except nsxlib_exc.ManagerError: - completor(success=False) - msg = (_('Failed to remove virtual server: %(listener)s ' - 'from lb service %(lbs)s') % - {'listener': listener['id'], 'lbs': lbs_id}) - raise n_exc.BadRequest(resource='lbaas-listener', msg=msg) + if lb_binding: + try: + lbs_id = lb_binding.get('lb_service_id') + lb_service = service_client.get(lbs_id) + vs_list = lb_service.get('virtual_server_ids') + if vs_list and vs_id in vs_list: + service_client.remove_virtual_server(lbs_id, vs_id) + except nsxlib_exc.ManagerError: + completor(success=False) + msg = (_('Failed to remove virtual server: %(listener)s ' + 'from lb service %(lbs)s') % + {'listener': listener['id'], 'lbs': lbs_id}) + raise n_exc.BadRequest(resource='lbaas-listener', msg=msg) try: if listener.get('default_pool_id'): vs_client.update(vs_id, pool_id='') diff --git a/vmware_nsx/services/lbaas/nsx_v3/implementation/loadbalancer_mgr.py b/vmware_nsx/services/lbaas/nsx_v3/implementation/loadbalancer_mgr.py index 49f600d78c..ed70c9a602 100644 --- a/vmware_nsx/services/lbaas/nsx_v3/implementation/loadbalancer_mgr.py +++ b/vmware_nsx/services/lbaas/nsx_v3/implementation/loadbalancer_mgr.py @@ -20,7 +20,6 @@ from oslo_log import log as logging from oslo_utils import excutils from vmware_nsx._i18n import _ -from vmware_nsx.common import exceptions as nsx_exc from vmware_nsx.db import db as nsx_db from vmware_nsx.services.lbaas import base_mgr from vmware_nsx.services.lbaas import lb_const @@ -35,8 +34,10 @@ class EdgeLoadBalancerManagerFromDict(base_mgr.Nsxv3LoadbalancerBaseManager): @log_helpers.log_method_call def create(self, context, lb, completor): - if not lb_utils.validate_lb_subnet(context, self.core_plugin, - lb['vip_subnet_id']): + if lb_utils.validate_lb_subnet(context, self.core_plugin, + lb['vip_subnet_id']): + completor(success=True) + else: completor(success=False) msg = (_('Cannot create lb on subnet %(sub)s for ' 'loadbalancer %(lb)s. The subnet needs to connect a ' @@ -44,80 +45,6 @@ class EdgeLoadBalancerManagerFromDict(base_mgr.Nsxv3LoadbalancerBaseManager): {'sub': lb['vip_subnet_id'], 'lb': lb['id']}) raise n_exc.BadRequest(resource='lbaas-subnet', msg=msg) - router_id = lb_utils.get_router_from_network( - context, self.core_plugin, lb['vip_subnet_id']) - nsx_router_id = nsx_db.get_nsx_router_id(context.session, - router_id) - service_client = self.core_plugin.nsxlib.load_balancer.service - lb_service = service_client.get_router_lb_service(nsx_router_id) - if not lb_service: - lb_size = lb_utils.get_lb_flavor_size( - self.flavor_plugin, context, lb.get('flavor_id')) - # Make sure the NSX service router exists - if not self.core_plugin.service_router_has_services( - context, router_id): - self.core_plugin.create_service_router(context, router_id) - lb_service = self._create_lb_service( - context, service_client, lb['tenant_id'], - router_id, nsx_router_id, lb['id'], lb_size) - if not lb_service: - completor(success=False) - msg = (_('Failed to create lb service for loadbalancer ' - '%s') % lb['id']) - raise nsx_exc.NsxPluginException(err_msg=msg) - - self._add_loadbalancer_binding( - context, lb['id'], lb_service['id'], - nsx_router_id, lb['vip_address']) - - completor(success=True) - - @log_helpers.log_method_call - def _create_lb_service(self, context, service_client, tenant_id, - router_id, nsx_router_id, lb_id, lb_size): - router = self.core_plugin.get_router(context, router_id) - if not router.get('external_gateway_info'): - msg = (_('Tenant router %(router)s does not connect to ' - 'external gateway') % {'router': router['id']}) - raise n_exc.BadRequest(resource='lbaas-lbservice-create', - msg=msg) - lb_name = utils.get_name_and_uuid(router['name'] or 'router', - router_id) - tags = lb_utils.get_tags(self.core_plugin, router_id, - lb_const.LR_ROUTER_TYPE, - tenant_id, context.project_name) - attachment = {'target_id': nsx_router_id, - 'target_type': 'LogicalRouter'} - try: - lb_service = service_client.create(display_name=lb_name, - tags=tags, - attachment=attachment, - size=lb_size) - except nsxlib_exc.ManagerError as e: - LOG.error("Failed to create LB service: %s", e) - return - - # Add rule to advertise external vips - lb_utils.update_router_lb_vip_advertisement( - context, self.core_plugin, router, nsx_router_id) - - return lb_service - - @log_helpers.log_method_call - def _add_loadbalancer_binding(self, context, lb_id, lbs_id, - nsx_router_id, vip_address): - # First check if there is already binding for the lb. - # If there is no binding for the lb, add the db binding. - binding = nsx_db.get_nsx_lbaas_loadbalancer_binding( - context.session, lb_id) - if not binding: - nsx_db.add_nsx_lbaas_loadbalancer_binding( - context.session, lb_id, lbs_id, - nsx_router_id, vip_address) - else: - LOG.debug("LB binding has already been added, and no need to add " - "here.") - @log_helpers.log_method_call def update(self, context, old_lb, new_lb, completor): vs_client = self.core_plugin.nsxlib.load_balancer.virtual_server @@ -262,8 +189,7 @@ class EdgeLoadBalancerManagerFromDict(base_mgr.Nsxv3LoadbalancerBaseManager): lb_binding = nsx_db.get_nsx_lbaas_loadbalancer_binding( context.session, id) if not lb_binding: - LOG.warning("Failed to get loadbalancer %s operating status. " - "Mapping was not found", id) + # No service yet return {} lb_service_id = lb_binding['lb_service_id'] diff --git a/vmware_nsx/services/lbaas/nsx_v3/implementation/member_mgr.py b/vmware_nsx/services/lbaas/nsx_v3/implementation/member_mgr.py index 25b06e58e3..2eb0179e8c 100644 --- a/vmware_nsx/services/lbaas/nsx_v3/implementation/member_mgr.py +++ b/vmware_nsx/services/lbaas/nsx_v3/implementation/member_mgr.py @@ -23,8 +23,10 @@ from vmware_nsx.common import exceptions as nsx_exc from vmware_nsx.common import locking from vmware_nsx.db import db as nsx_db from vmware_nsx.services.lbaas import base_mgr +from vmware_nsx.services.lbaas import lb_const from vmware_nsx.services.lbaas.nsx_v3.implementation import lb_utils from vmware_nsxlib.v3 import exceptions as nsxlib_exc +from vmware_nsxlib.v3 import utils LOG = logging.getLogger(__name__) @@ -43,6 +45,37 @@ class EdgeMemberManagerFromDict(base_mgr.Nsxv3LoadbalancerBaseManager): 'be a floating IP') % {'fip': fip}) raise n_exc.BadRequest(resource='lbaas-vip', msg=msg) + @log_helpers.log_method_call + def _create_lb_service(self, context, service_client, tenant_id, + router_id, nsx_router_id, lb_id, lb_size): + router = self.core_plugin.get_router(context, router_id) + if not router.get('external_gateway_info'): + msg = (_('Tenant router %(router)s does not connect to ' + 'external gateway') % {'router': router['id']}) + raise n_exc.BadRequest(resource='lbaas-lbservice-create', + msg=msg) + lb_name = utils.get_name_and_uuid(router['name'] or 'router', + router_id) + tags = lb_utils.get_tags(self.core_plugin, router_id, + lb_const.LR_ROUTER_TYPE, + tenant_id, context.project_name) + attachment = {'target_id': nsx_router_id, + 'target_type': 'LogicalRouter'} + try: + lb_service = service_client.create(display_name=lb_name, + tags=tags, + attachment=attachment, + size=lb_size) + except nsxlib_exc.ManagerError as e: + LOG.error("Failed to create LB service: %s", e) + return + + # Add rule to advertise external vips + lb_utils.update_router_lb_vip_advertisement( + context, self.core_plugin, router, nsx_router_id) + + return lb_service + @log_helpers.log_method_call def _get_updated_pool_members(self, context, lb_pool, member): network = lb_utils.get_network_from_subnet( @@ -58,6 +91,21 @@ class EdgeMemberManagerFromDict(base_mgr.Nsxv3LoadbalancerBaseManager): m['weight'] = member['weight'] return lb_pool['members'] + @log_helpers.log_method_call + def _add_loadbalancer_binding(self, context, lb_id, lbs_id, + nsx_router_id, vip_address): + # First check if there is already binding for the lb. + # If there is no binding for the lb, add the db binding. + binding = nsx_db.get_nsx_lbaas_loadbalancer_binding( + context.session, lb_id) + if not binding: + nsx_db.add_nsx_lbaas_loadbalancer_binding( + context.session, lb_id, lbs_id, + nsx_router_id, vip_address) + else: + LOG.debug("LB binding has already been added, and no need " + "to add here.") + @log_helpers.log_method_call def create(self, context, member, completor): with locking.LockManager.get_lock( @@ -80,6 +128,7 @@ class EdgeMemberManagerFromDict(base_mgr.Nsxv3LoadbalancerBaseManager): raise n_exc.BadRequest(resource='lbaas-subnet', msg=msg) pool_client = self.core_plugin.nsxlib.load_balancer.pool + service_client = self.core_plugin.nsxlib.load_balancer.service network = lb_utils.get_network_from_subnet( context, self.core_plugin, member['subnet_id']) @@ -99,14 +148,43 @@ class EdgeMemberManagerFromDict(base_mgr.Nsxv3LoadbalancerBaseManager): binding = nsx_db.get_nsx_lbaas_pool_binding(context.session, lb_id, pool_id) if binding: + vs_id = binding.get('lb_vs_id') lb_pool_id = binding.get('lb_pool_id') lb_binding = nsx_db.get_nsx_lbaas_loadbalancer_binding( context.session, lb_id) + lb_service = None if not lb_binding: - completor(success=False) - msg = (_('Failed to get LB binding for member %s') % - member['id']) - raise nsx_exc.NsxPluginException(err_msg=msg) + nsx_router_id = nsx_db.get_nsx_router_id(context.session, + router_id) + lb_service = service_client.get_router_lb_service( + nsx_router_id) + virtual_server_ids = ( + lb_service and + lb_service.get('virtual_server_ids', []) or []) + if not lb_service: + lb_size = lb_utils.get_lb_flavor_size( + self.flavor_plugin, context, + loadbalancer.get('flavor_id')) + if not self.core_plugin.service_router_has_services( + context, + router_id): + self.core_plugin.create_service_router(context, + router_id) + lb_service = self._create_lb_service( + context, service_client, member['tenant_id'], + router_id, nsx_router_id, loadbalancer['id'], lb_size) + if not lb_service: + completor(success=False) + msg = (_('Failed to create lb service to attach ' + 'virtual server %(vs)s for member ' + '%(member)s') % + {'vs': vs_id, 'member': member['id']}) + raise nsx_exc.NsxPluginException(err_msg=msg) + + lb_service_id = lb_service['id'] + self._add_loadbalancer_binding( + context, loadbalancer['id'], lb_service_id, + nsx_router_id, loadbalancer['vip_address']) with locking.LockManager.get_lock('pool-member-%s' % lb_pool_id): lb_pool = pool_client.get(lb_pool_id) @@ -119,6 +197,30 @@ class EdgeMemberManagerFromDict(base_mgr.Nsxv3LoadbalancerBaseManager): members = (old_m + new_m) if old_m else new_m pool_client.update_pool_with_members(lb_pool_id, members) + # Check whether the virtual server should be added to the load + # balancing server. It is safe to perform this operation after the + # member has been added to the pool. This allows us to skip this + # check if there is already a member in the pool + if vs_id and not old_m: + # load the LB service if not already loaded + if not lb_service: + nsx_router_id = nsx_db.get_nsx_router_id(context.session, + router_id) + lb_service = service_client.get_router_lb_service( + nsx_router_id) + lb_service_id = lb_service['id'] + virtual_server_ids = lb_service.get('virtual_server_ids', + []) + if vs_id not in virtual_server_ids: + try: + service_client.add_virtual_server(lb_service_id, vs_id) + except nsxlib_exc.ManagerError: + completor(success=False) + msg = (_('Failed to attach virtual server %(vs)s ' + 'to lb service %(service)s') % + {'vs': vs_id, 'service': lb_service_id}) + raise n_exc.BadRequest(resource='lbaas-member', + msg=msg) else: completor(success=False) msg = (_('Failed to get pool binding to add member %s') % diff --git a/vmware_nsx/tests/unit/services/lbaas/test_nsxv3_driver.py b/vmware_nsx/tests/unit/services/lbaas/test_nsxv3_driver.py index 9a75924f99..85b3cb7c7b 100644 --- a/vmware_nsx/tests/unit/services/lbaas/test_nsxv3_driver.py +++ b/vmware_nsx/tests/unit/services/lbaas/test_nsxv3_driver.py @@ -248,12 +248,7 @@ class TestEdgeLbaasV2Loadbalancer(BaseTestEdgeLbaasV2): def test_create(self): with mock.patch.object(lb_utils, 'validate_lb_subnet' - ) as mock_validate_lb_subnet,\ - mock.patch.object(lb_utils, 'get_router_from_network'),\ - mock.patch.object(nsx_db, 'get_nsx_lbaas_loadbalancer_binding'),\ - mock.patch.object(nsx_db, 'get_nsx_router_id'),\ - mock.patch.object(self.service_client, 'get_router_lb_service'),\ - mock.patch.object(nsx_db, 'add_nsx_lbaas_loadbalancer_binding'): + ) as mock_validate_lb_subnet: mock_validate_lb_subnet.return_value = True self.edge_driver.loadbalancer.create(self.context, self.lb) @@ -376,6 +371,7 @@ class TestEdgeLbaasV2Listener(BaseTestEdgeLbaasV2): mock_add_listener_binding.assert_called_with( self.context.session, LB_ID, LISTENER_ID, APP_PROFILE_ID, LB_VS_ID) + mock_successful_completion = ( self.lbv2_driver.listener.successful_completion) mock_successful_completion.assert_called_with(self.context, @@ -893,7 +889,7 @@ class TestEdgeLbaasV2Member(BaseTestEdgeLbaasV2): def _tested_entity(self): return 'member' - def test_create(self): + def _test_create(self, lb_binding, pool_binding): with mock.patch.object(lb_utils, 'validate_lb_member_subnet' ) as mock_validate_lb_subnet, \ mock.patch.object(self.lbv2_driver.plugin, 'get_pool_members' @@ -910,6 +906,11 @@ class TestEdgeLbaasV2Member(BaseTestEdgeLbaasV2): ) as mock_get_nsx_router_id, \ mock.patch.object(self.service_client, 'get_router_lb_service' ) as mock_get_lb_service, \ + mock.patch.object(nsx_db, 'add_nsx_lbaas_loadbalancer_binding' + ) as mock_add_loadbalancer_binding, \ + mock.patch.object(self.service_client, + 'add_virtual_server' + ) as mock_add_vs_to_service, \ mock.patch.object(self.pool_client, 'get' ) as mock_get_pool, \ mock.patch.object(self.pool_client, 'update_pool_with_members' @@ -918,13 +919,20 @@ class TestEdgeLbaasV2Member(BaseTestEdgeLbaasV2): mock_get_pool_members.return_value = [self.member] mock_get_network.return_value = LB_NETWORK mock_get_router.return_value = LB_ROUTER_ID - mock_get_pool_binding.return_value = POOL_BINDING - mock_get_lb_binding.return_value = LB_BINDING + mock_get_pool_binding.return_value = pool_binding + mock_get_lb_binding.return_value = lb_binding mock_get_nsx_router_id.return_value = LB_ROUTER_ID mock_get_lb_service.return_value = {'id': LB_SERVICE_ID} mock_get_pool.return_value = LB_POOL self.edge_driver.member.create(self.context, self.member) + if not lb_binding: + mock_add_loadbalancer_binding.assert_called_with( + self.context.session, LB_ID, LB_SERVICE_ID, LB_ROUTER_ID, + LB_VIP) + else: + mock_add_loadbalancer_binding.assert_not_called() + mock_add_vs_to_service.assert_called_with(LB_SERVICE_ID, LB_VS_ID) mock_update_pool_with_members.assert_called_with(LB_POOL_ID, [LB_MEMBER]) mock_successful_completion = ( @@ -933,6 +941,119 @@ class TestEdgeLbaasV2Member(BaseTestEdgeLbaasV2): self.member, delete=False) + def test_create(self): + self._test_create(None, POOL_BINDING) + + def test_create_existing_binding(self): + self._test_create(LB_BINDING, POOL_BINDING) + + def test_create_with_service(self): + ext_cidr = '1.1.1.0/24' + with mock.patch.object(lb_utils, 'validate_lb_member_subnet' + ) as mock_validate_lb_subnet, \ + mock.patch.object(self.lbv2_driver.plugin, 'get_pool_members' + ) as mock_get_pool_members, \ + mock.patch.object(lb_utils, 'get_network_from_subnet' + ) as mock_get_network, \ + mock.patch.object(lb_utils, 'get_router_from_network' + ) as mock_get_router, \ + mock.patch.object(nsx_db, 'get_nsx_lbaas_pool_binding' + ) as mock_get_pool_binding, \ + mock.patch.object(nsx_db, 'get_nsx_lbaas_loadbalancer_binding' + ) as mock_get_lb_binding, \ + mock.patch.object(nsx_db, 'get_nsx_router_id' + ) as mock_get_nsx_router_id, \ + mock.patch.object(self.service_client, 'get_router_lb_service' + ) as mock_get_lb_service, \ + mock.patch.object(self.service_client, 'create' + ) as mock_create_lb_service, \ + mock.patch.object(nsx_db, 'add_nsx_lbaas_loadbalancer_binding' + ) as mock_add_loadbalancer_bidning, \ + mock.patch.object(self.service_client, + 'add_virtual_server' + ) as mock_add_vs_to_service, \ + mock.patch.object(self.pool_client, 'get' + ) as mock_get_pool, \ + mock.patch.object(self.pool_client, 'update_pool_with_members' + ) as mock_update_pool_with_members,\ + mock.patch.object(self.core_plugin.nsxlib.logical_router, + 'update_advertisement_rules') as update_adv,\ + mock.patch.object(self.core_plugin, '_find_router_gw_subnets' + ) as mock_get_subnets,\ + mock.patch.object(self.core_plugin, 'get_router' + ) as mock_core_get_router: + mock_validate_lb_subnet.return_value = True + mock_get_pool_members.return_value = [self.member] + mock_get_network.return_value = LB_NETWORK + mock_get_router.return_value = LB_ROUTER_ID + mock_get_pool_binding.return_value = POOL_BINDING + mock_get_lb_binding.return_value = None + mock_get_nsx_router_id.return_value = LB_ROUTER_ID + mock_get_lb_service.return_value = {} + mock_create_lb_service.return_value = {'id': LB_SERVICE_ID} + mock_get_pool.return_value = LB_POOL + mock_core_get_router.return_value = { + 'id': LB_ROUTER_ID, + 'name': 'router1', + 'external_gateway_info': 'dummy'} + mock_get_subnets.return_value = [{'cidr': ext_cidr}] + + self.edge_driver.member.create(self.context, self.member) + + mock_add_loadbalancer_bidning.assert_called_with( + self.context.session, LB_ID, LB_SERVICE_ID, LB_ROUTER_ID, + LB_VIP) + mock_add_vs_to_service.assert_called_with(LB_SERVICE_ID, LB_VS_ID) + mock_update_pool_with_members.assert_called_with(LB_POOL_ID, + [LB_MEMBER]) + update_adv.assert_called_with( + LB_ROUTER_ID, + [{'networks': [ext_cidr], + 'display_name': lb_utils.ADV_RULE_NAME, + 'rule_filter': {'match_route_types': ['T1_LB_VIP'], + 'prefix_operator': 'GE'}, + 'action': 'ALLOW'}], + name_prefix=lb_utils.ADV_RULE_NAME) + mock_successful_completion = ( + self.lbv2_driver.member.successful_completion) + mock_successful_completion.assert_called_with(self.context, + self.member, + delete=False) + + def test_create_lbs_no_router_gateway(self): + with mock.patch.object(lb_utils, 'validate_lb_member_subnet' + ) as mock_validate_lb_subnet, \ + mock.patch.object(self.lbv2_driver.plugin, 'get_pool_members' + ) as mock_get_pool_members, \ + mock.patch.object(lb_utils, 'get_network_from_subnet' + ) as mock_get_network, \ + mock.patch.object(lb_utils, 'get_router_from_network' + ) as mock_get_router_from_network, \ + mock.patch.object(nsx_db, 'get_nsx_lbaas_pool_binding' + ) as mock_get_pool_binding, \ + mock.patch.object(nsx_db, 'get_nsx_lbaas_loadbalancer_binding' + ) as mock_get_lb_binding, \ + mock.patch.object(nsx_db, 'get_nsx_router_id' + ) as mock_get_nsx_router_id, \ + mock.patch.object(self.service_client, 'get_router_lb_service' + ) as mock_get_lb_service, \ + mock.patch.object(self.core_plugin, 'get_router' + ) as mock_get_router: + mock_validate_lb_subnet.return_value = True + mock_get_pool_members.return_value = [self.member] + mock_get_network.return_value = LB_NETWORK + mock_get_router_from_network.return_value = LB_ROUTER_ID + mock_get_pool_binding.return_value = POOL_BINDING + mock_get_lb_binding.return_value = None + mock_get_nsx_router_id.return_value = LB_ROUTER_ID + mock_get_lb_service.return_value = None + mock_get_router.return_value = {'id': 'router1-xxx'} + + self.assertRaises(n_exc.BadRequest, + self.edge_driver.member.create, + self.context, + self.member) + def test_create_member_different_router(self): with mock.patch.object(self.lbv2_driver.plugin, 'get_pool_members' ) as mock_get_pool_members, \