diff --git a/vmware_nsx/services/lbaas/nsx_v/lbaas_common.py b/vmware_nsx/services/lbaas/nsx_v/lbaas_common.py index 1bcfb09a46..bbe6967017 100644 --- a/vmware_nsx/services/lbaas/nsx_v/lbaas_common.py +++ b/vmware_nsx/services/lbaas/nsx_v/lbaas_common.py @@ -109,15 +109,16 @@ def delete_lb_interface(context, plugin, lb_id, subnet_id): dist=False) -def get_lbaas_edge_id(context, plugin, lb_id, vip_addr, subnet_id, tenant_id): +def get_lbaas_edge_id(context, plugin, lb_id, vip_addr, subnet_id, tenant_id, + appliance_size): subnet = plugin.get_subnet(context, subnet_id) network_id = subnet.get('network_id') availability_zone = plugin.get_network_az_by_net_id(context, network_id) resource_id = get_lb_resource_id(lb_id) - edge_id = plugin.edge_manager.allocate_lb_edge_appliance( - context, resource_id, availability_zone=availability_zone) + context, resource_id, availability_zone=availability_zone, + appliance_size=appliance_size) create_lb_interface(context, plugin, lb_id, subnet_id, tenant_id, vip_addr=vip_addr, subnet=subnet) diff --git a/vmware_nsx/services/lbaas/nsx_v/v2/loadbalancer_mgr.py b/vmware_nsx/services/lbaas/nsx_v/v2/loadbalancer_mgr.py index 3deeb54b2c..424c3226ba 100644 --- a/vmware_nsx/services/lbaas/nsx_v/v2/loadbalancer_mgr.py +++ b/vmware_nsx/services/lbaas/nsx_v/v2/loadbalancer_mgr.py @@ -13,6 +13,7 @@ # License for the specific language governing permissions and limitations # under the License. +from neutron.services.flavors import flavors_plugin from neutron_lib.callbacks import events from neutron_lib.callbacks import registry from neutron_lib.callbacks import resources @@ -24,6 +25,8 @@ from oslo_utils import excutils from vmware_nsx._i18n import _ from vmware_nsx.db import nsxv_db +from vmware_nsx.plugins.nsx_v.vshield.common import ( + constants as vcns_const) from vmware_nsx.plugins.nsx_v.vshield.common import exceptions as nsxv_exc from vmware_nsx.services.lbaas import base_mgr from vmware_nsx.services.lbaas.nsx_v import lbaas_common as lb_common @@ -39,11 +42,28 @@ class EdgeLoadBalancerManager(base_mgr.EdgeLoadbalancerBaseManager): self._handle_subnet_gw_change, resources.SUBNET, events.AFTER_UPDATE) + def _get_lb_flavor_size(self, context, flavor_id): + if not flavor_id: + return vcns_const.SERVICE_SIZE_MAPPING['lb'] + else: + flavor = flavors_plugin.FlavorsPlugin.get_flavor( + self.flavor_plugin, context, flavor_id) + flavor_size = flavor['name'] + if flavor_size.lower() in vcns_const.ALLOWED_EDGE_SIZES: + return flavor_size.lower() + else: + err_msg = (_("Invalid flavor size %(flavor)s, only %(sizes)s " + "are supported") % + {'flavor': flavor_size, + 'sizes': vcns_const.ALLOWED_EDGE_SIZES}) + raise n_exc.InvalidInput(error_message=err_msg) + @log_helpers.log_method_call def create(self, context, lb): + lb_size = self._get_lb_flavor_size(context, lb.flavor_id) edge_id = lb_common.get_lbaas_edge_id( context, self.core_plugin, lb.id, lb.vip_address, lb.vip_subnet_id, - lb.tenant_id) + lb.tenant_id, lb_size) if not edge_id: msg = _('Failed to allocate Edge on subnet %(sub)s for ' diff --git a/vmware_nsx/tests/unit/nsx_v/test_edge_loadbalancer_driver_v2.py b/vmware_nsx/tests/unit/nsx_v/test_edge_loadbalancer_driver_v2.py index e52cd2640e..81f23aa724 100644 --- a/vmware_nsx/tests/unit/nsx_v/test_edge_loadbalancer_driver_v2.py +++ b/vmware_nsx/tests/unit/nsx_v/test_edge_loadbalancer_driver_v2.py @@ -15,9 +15,11 @@ import mock +from neutron.services.flavors import flavors_plugin from neutron.tests import base from neutron_lbaas.services.loadbalancer import data_models as lb_models from neutron_lib import context +from neutron_lib import exceptions as n_exc from vmware_nsx.db import nsxv_db from vmware_nsx.plugins.nsx_v.vshield import vcns_driver @@ -102,8 +104,10 @@ class BaseTestEdgeLbaasV2(base.BaseTestCase): self.lbv2_driver = mock.Mock() self.core_plugin = mock.Mock() + self.flavor_plugin = flavors_plugin.FlavorsPlugin() base_mgr.LoadbalancerBaseManager._lbv2_driver = self.lbv2_driver base_mgr.LoadbalancerBaseManager._core_plugin = self.core_plugin + base_mgr.LoadbalancerBaseManager._flavor_plugin = self.flavor_plugin self._patch_lb_plugin(self.lbv2_driver, self._tested_entity) self.lb = lb_models.LoadBalancer(LB_ID, LB_TENANT_ID, 'lb-name', '', @@ -189,7 +193,6 @@ class TestEdgeLbaasV2Loadbalancer(BaseTestEdgeLbaasV2): mock_get_edge.return_value = LB_EDGE_ID mock_add_vip_fwr.return_value = LB_VIP_FWR_ID mock_get_lb_binding_by_edge.return_value = [] - self.edge_driver.loadbalancer.create(self.context, self.lb) mock_add_vip_fwr.assert_called_with(self.edge_driver.vcns, @@ -203,6 +206,8 @@ class TestEdgeLbaasV2Loadbalancer(BaseTestEdgeLbaasV2): LB_VIP) mock_set_fw_rule.assert_called_with( self.edge_driver.vcns, LB_EDGE_ID, 'accept') + mock_get_edge.assert_called_with(mock.ANY, mock.ANY, LB_ID, LB_VIP, + mock.ANY, LB_TENANT_ID, 'compact') mock_successful_completion = ( self.lbv2_driver.load_balancer.successful_completion) mock_successful_completion.assert_called_with(self.context, @@ -210,6 +215,72 @@ class TestEdgeLbaasV2Loadbalancer(BaseTestEdgeLbaasV2): mock_enable_edge_acceleration.assert_called_with( self.edge_driver.vcns, LB_EDGE_ID) + def test_create_with_flavor(self): + flavor_name = 'large' + with mock.patch.object(lb_common, 'get_lbaas_edge_id' + ) as mock_get_edge, \ + mock.patch.object(lb_common, 'add_vip_fw_rule' + ) as mock_add_vip_fwr, \ + mock.patch.object(lb_common, 'set_lb_firewall_default_rule' + ) as mock_set_fw_rule, \ + mock.patch.object(lb_common, 'enable_edge_acceleration' + ) as mock_enable_edge_acceleration, \ + mock.patch.object(nsxv_db, + 'get_nsxv_lbaas_loadbalancer_binding_by_edge' + ) as mock_get_lb_binding_by_edge, \ + mock.patch.object(nsxv_db, 'add_nsxv_lbaas_loadbalancer_binding' + ) as mock_db_binding,\ + mock.patch('neutron.services.flavors.flavors_plugin.FlavorsPlugin.' + 'get_flavor', return_value={'name': flavor_name}): + mock_get_edge.return_value = LB_EDGE_ID + mock_add_vip_fwr.return_value = LB_VIP_FWR_ID + mock_get_lb_binding_by_edge.return_value = [] + self.lb.flavor_id = 'dummy' + self.edge_driver.loadbalancer.create(self.context, self.lb) + + mock_add_vip_fwr.assert_called_with(self.edge_driver.vcns, + LB_EDGE_ID, + LB_ID, + LB_VIP) + mock_db_binding.assert_called_with(self.context.session, + LB_ID, + LB_EDGE_ID, + LB_VIP_FWR_ID, + LB_VIP) + mock_set_fw_rule.assert_called_with( + self.edge_driver.vcns, LB_EDGE_ID, 'accept') + mock_get_edge.assert_called_with( + mock.ANY, mock.ANY, LB_ID, LB_VIP, + mock.ANY, LB_TENANT_ID, flavor_name) + mock_successful_completion = ( + self.lbv2_driver.load_balancer.successful_completion) + mock_successful_completion.assert_called_with(self.context, + self.lb) + mock_enable_edge_acceleration.assert_called_with( + self.edge_driver.vcns, LB_EDGE_ID) + self.lb.flavor_id = None + + def test_create_with_illegal_flavor(self): + flavor_name = 'no_size' + with mock.patch.object(lb_common, 'get_lbaas_edge_id' + ) as mock_get_edge, \ + mock.patch.object(lb_common, 'add_vip_fw_rule' + ) as mock_add_vip_fwr, \ + mock.patch.object(nsxv_db, + 'get_nsxv_lbaas_loadbalancer_binding_by_edge' + ) as mock_get_lb_binding_by_edge, \ + mock.patch('neutron.services.flavors.flavors_plugin.FlavorsPlugin.' + 'get_flavor', return_value={'name': flavor_name}): + mock_get_edge.return_value = LB_EDGE_ID + mock_add_vip_fwr.return_value = LB_VIP_FWR_ID + mock_get_lb_binding_by_edge.return_value = [] + self.lb.flavor_id = 'dummy' + self.assertRaises( + n_exc.InvalidInput, + self.edge_driver.loadbalancer.create, + self.context, self.lb) + self.lb.flavor_id = None + def test_update(self): new_lb = lb_models.LoadBalancer(LB_ID, 'yyy-yyy', 'lb-name', 'heh-huh', 'some-subnet', 'port-id', LB_VIP)