diff --git a/etc/neutron_lbaas.conf b/etc/neutron_lbaas.conf index f1a11640f..e28c870c8 100644 --- a/etc/neutron_lbaas.conf +++ b/etc/neutron_lbaas.conf @@ -56,6 +56,7 @@ service_provider=LOADBALANCER:Haproxy:neutron_lbaas.services.loadbalancer.driver # service_provider=LOADBALANCER:NetScaler:neutron_lbaas.services.loadbalancer.drivers.netscaler.netscaler_driver.NetScalerPluginDriver # service_provider=LOADBALANCER:Embrane:neutron_lbaas.services.loadbalancer.drivers.embrane.driver.EmbraneLbaas:default # service_provider = LOADBALANCER:A10Networks:neutron_lbaas.services.loadbalancer.drivers.a10networks.driver_v1.ThunderDriver:default +# service_provider = LOADBALANCER:VMWareEdge:neutron_lbaas.services.loadbalancer.drivers.vmware.edge_driver.EdgeLoadbalancerDriver:default # LBaaS v2 drivers # service_provider = LOADBALANCERV2:LoggingNoop:neutron_lbaas.drivers.logging_noop.driver.LoggingNoopLoadBalancerDriver:default diff --git a/neutron_lbaas/services/loadbalancer/drivers/vmware/__init__.py b/neutron_lbaas/services/loadbalancer/drivers/vmware/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/neutron_lbaas/services/loadbalancer/drivers/vmware/db.py b/neutron_lbaas/services/loadbalancer/drivers/vmware/db.py index 874aa64d8..dde106017 100644 --- a/neutron_lbaas/services/loadbalancer/drivers/vmware/db.py +++ b/neutron_lbaas/services/loadbalancer/drivers/vmware/db.py @@ -31,6 +31,11 @@ def get_nsxv_edge_pool_mapping(context, pool_id): filter_by(pool_id=pool_id).first()) +def get_nsxv_edge_pool_mapping_by_edge(context, edge_id): + return(context.session.query(models.NsxvEdgePoolMapping). + filter_by(edge_id=edge_id).all()) + + def delete_nsxv_edge_pool_mapping(context, pool_id): session = context.session mapping = (session.query(models.NsxvEdgePoolMapping).filter_by( diff --git a/neutron_lbaas/services/loadbalancer/drivers/vmware/edge_driver.py b/neutron_lbaas/services/loadbalancer/drivers/vmware/edge_driver.py new file mode 100644 index 000000000..d993de5a9 --- /dev/null +++ b/neutron_lbaas/services/loadbalancer/drivers/vmware/edge_driver.py @@ -0,0 +1,208 @@ +# Copyright 2015 VMware, Inc. +# 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. + + +from neutron.plugins.common import constants + +from neutron_lbaas.db.loadbalancer import loadbalancer_db as lb_db +from neutron_lbaas.extensions import loadbalancer as lb_ext +from neutron_lbaas.services.loadbalancer.drivers import abstract_driver +from neutron_lbaas.services.loadbalancer.drivers.vmware import db + + +class EdgeLoadbalancerDriver(abstract_driver.LoadBalancerAbstractDriver): + + def __init__(self, plugin): + self._plugin = plugin + + @property + def _nsxv_driver(self): + return self._plugin._core_plugin.nsx_v + + def create_pool_successful(self, context, pool, edge_id, edge_pool_id): + db.add_nsxv_edge_pool_mapping( + context, pool['id'], edge_id, edge_pool_id) + + self.pool_successful(context, pool) + + def delete_pool_successful(self, context, pool): + self._plugin._delete_db_pool(context, pool['id']) + db.delete_nsxv_edge_pool_mapping(context, pool['id']) + + def pool_successful(self, context, pool): + self._plugin.update_status( + context, lb_db.Pool, pool['id'], constants.ACTIVE) + + def pool_failed(self, context, pool): + self._plugin.update_status( + context, lb_db.Pool, pool['id'], constants.ERROR) + + def create_pool(self, context, pool): + super(EdgeLoadbalancerDriver, self).create_pool(context, pool) + self._nsxv_driver.create_pool(context, pool) + + def update_pool(self, context, old_pool, pool): + super(EdgeLoadbalancerDriver, self).update_pool( + context, old_pool, pool) + pool_mapping = db.get_nsxv_edge_pool_mapping(context, old_pool['id']) + self._nsxv_driver.update_pool( + context, old_pool, pool, pool_mapping) + + def delete_pool(self, context, pool): + vip_id = self._plugin.get_pool(context, pool['id']).get('vip_id', None) + if vip_id: + raise lb_ext.PoolInUse(pool_id=pool['id']) + else: + super(EdgeLoadbalancerDriver, self).delete_pool(context, pool) + pool_mapping = db.get_nsxv_edge_pool_mapping(context, pool['id']) + self._nsxv_driver.delete_pool(context, pool, pool_mapping) + + def create_vip_successful(self, context, vip, edge_id, app_profile_id, + edge_vip_id, edge_fw_rule_id): + db.add_nsxv_edge_vip_mapping(context, vip['pool_id'], edge_id, + app_profile_id, edge_vip_id, + edge_fw_rule_id) + self.vip_successful(context, vip) + + def delete_vip_successful(self, context, vip): + db.delete_nsxv_edge_vip_mapping(context, vip['pool_id']) + self._plugin._delete_db_vip(context, vip['id']) + + def vip_successful(self, context, vip): + self._plugin.update_status( + context, lb_db.Vip, vip['id'], constants.ACTIVE) + + def vip_failed(self, context, vip): + self._plugin.update_status( + context, lb_db.Vip, vip['id'], constants.ERROR) + + def create_vip(self, context, vip): + super(EdgeLoadbalancerDriver, self).create_vip(context, vip) + + pool_mapping = db.get_nsxv_edge_pool_mapping(context, vip['pool_id']) + self._nsxv_driver.create_vip(context, vip, pool_mapping) + + def update_vip(self, context, old_vip, vip): + super(EdgeLoadbalancerDriver, self).update_vip(context, old_vip, vip) + + pool_mapping = db.get_nsxv_edge_pool_mapping(context, vip['pool_id']) + vip_mapping = db.get_nsxv_edge_vip_mapping(context, vip['pool_id']) + self._nsxv_driver.update_vip(context, old_vip, vip, pool_mapping, + vip_mapping) + + def delete_vip(self, context, vip): + super(EdgeLoadbalancerDriver, self).delete_vip(context, vip) + vip_mapping = db.get_nsxv_edge_vip_mapping(context, vip['pool_id']) + self._nsxv_driver.delete_vip(context, vip, vip_mapping) + + def member_successful(self, context, member): + self._plugin.update_status( + context, lb_db.Member, member['id'], constants.ACTIVE) + + def member_failed(self, context, member): + self._plugin.update_status( + context, lb_db.Member, member['id'], constants.ERROR) + + def create_member(self, context, member): + super(EdgeLoadbalancerDriver, self).create_member(context, member) + pool_mapping = db.get_nsxv_edge_pool_mapping( + context, member['pool_id']) + self._nsxv_driver.create_member( + context, member, pool_mapping) + + def update_member(self, context, old_member, member): + super(EdgeLoadbalancerDriver, self).update_member( + context, old_member, member) + pool_mapping = db.get_nsxv_edge_pool_mapping( + context, member['pool_id']) + + self._nsxv_driver.update_member( + context, old_member, member, pool_mapping) + + def delete_member(self, context, member): + super(EdgeLoadbalancerDriver, self).delete_member(context, member) + pool_mapping = db.get_nsxv_edge_pool_mapping( + context, member['pool_id']) + + self._nsxv_driver.delete_member(context, member, pool_mapping) + + def create_pool_health_monitor_successful(self, context, health_monitor, + pool_id, edge_id, edge_mon_id): + db.add_nsxv_edge_monitor_mapping( + context, health_monitor['id'], edge_id, edge_mon_id) + self.pool_health_monitor_successful(context, health_monitor, pool_id) + + def delete_pool_health_monitor_successful(self, context, health_monitor, + pool_id, mon_mapping): + db.delete_nsxv_edge_monitor_mapping( + context, health_monitor['id'], mon_mapping['edge_id']) + self._plugin._delete_db_pool_health_monitor( + context, health_monitor['id'], pool_id) + + def pool_health_monitor_successful(self, context, health_monitor, pool_id): + self._plugin.update_pool_health_monitor( + context, health_monitor['id'], pool_id, constants.ACTIVE, '') + + def pool_health_monitor_failed(self, context, health_monitor, pool_id): + self._plugin.update_pool_health_monitor( + context, health_monitor['id'], pool_id, constants.ERROR, '') + + def create_pool_health_monitor(self, context, health_monitor, pool_id): + super(EdgeLoadbalancerDriver, self).create_pool_health_monitor( + context, health_monitor, pool_id) + + pool_mapping = db.get_nsxv_edge_pool_mapping(context, pool_id) + mon_mapping = db.get_nsxv_edge_monitor_mapping( + context, health_monitor['id'], pool_mapping['edge_id']) + + self._nsxv_driver.create_pool_health_monitor( + context, health_monitor, pool_id, pool_mapping, mon_mapping) + + def update_pool_health_monitor(self, context, old_health_monitor, + health_monitor, pool_id): + super(EdgeLoadbalancerDriver, self).update_pool_health_monitor( + context, old_health_monitor, health_monitor, pool_id) + + pool_mapping = db.get_nsxv_edge_pool_mapping(context, pool_id) + mon_mapping = db.get_nsxv_edge_monitor_mapping( + context, health_monitor['id'], pool_mapping['edge_id']) + + self._nsxv_driver.update_pool_health_monitor( + context, old_health_monitor, health_monitor, pool_id, mon_mapping) + + def delete_pool_health_monitor(self, context, health_monitor, pool_id): + super(EdgeLoadbalancerDriver, self).delete_pool_health_monitor( + context, health_monitor, pool_id) + + pool_mapping = db.get_nsxv_edge_pool_mapping(context, pool_id) + edge_id = pool_mapping['edge_id'] + mon_mapping = db.get_nsxv_edge_monitor_mapping( + context, health_monitor['id'], edge_id) + self._nsxv_driver.delete_pool_health_monitor( + context, health_monitor, pool_id, pool_mapping, mon_mapping) + + def stats(self, context, pool_id): + super(EdgeLoadbalancerDriver, self).stats(context, pool_id) + pool_mapping = db.get_nsxv_edge_pool_mapping(context, pool_id) + return self._nsxv_driver.stats(context, pool_id, pool_mapping) + + def is_edge_in_use(self, edge_id): + pool_mappings = db.get_nsxv_edge_pool_mapping_by_edge( + self.context, edge_id) + + if pool_mappings: + return True + + return False diff --git a/neutron_lbaas/tests/unit/services/loadbalancer/drivers/vmware/__init__.py b/neutron_lbaas/tests/unit/services/loadbalancer/drivers/vmware/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/neutron_lbaas/tests/unit/services/loadbalancer/drivers/vmware/test_edge_driver.py b/neutron_lbaas/tests/unit/services/loadbalancer/drivers/vmware/test_edge_driver.py new file mode 100644 index 000000000..0d6fbb138 --- /dev/null +++ b/neutron_lbaas/tests/unit/services/loadbalancer/drivers/vmware/test_edge_driver.py @@ -0,0 +1,502 @@ +# Copyright 2015 VMware, Inc. +# 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. + +import contextlib +import mock + +from neutron import context +from neutron.plugins.common import constants + +from neutron import manager +from neutron_lbaas.db.loadbalancer import loadbalancer_db as lb_db +from neutron_lbaas.services.loadbalancer.drivers.vmware import db +from neutron_lbaas.tests.unit.db.loadbalancer import test_db_loadbalancer + + +EDGE_PROVIDER = ('LOADBALANCER:vmwareedge:neutron_lbaas.services.' + 'loadbalancer.drivers.vmware.edge_driver.' + 'EdgeLoadbalancerDriver:default') + +HEALTHMON_ID = 'cb297614-66c9-4048-8838-7e87231569ae' +POOL_ID = 'b3dfb476-6fdf-4ddd-b6bd-e86ae78dc30b' +TENANT_ID = 'f9135d3a908842bd8d785816c2c90d36' +SUBNET_ID = 'c8924d77-ff57-406f-a13c-a8c5def01fc9' +VIP_ID = 'f6393b95-34b0-4299-9001-cbc21e32bf03' +VIP_PORT_ID = '49c547e3-6775-42ea-a607-91e8f1a07432' +MEMBER_ID = '90dacafd-9c11-4af7-9d89-234e2d1fedb1' + +EDGE_ID = 'edge-x' +EDGE_POOL_ID = '111' +EDGE_VSE_ID = '222' +APP_PROFILE_ID = '333' +EDGE_MON_ID = '444' +EDGE_FW_RULE_ID = '555' + + +class TestLoadBalancerPluginBase( + test_db_loadbalancer.LoadBalancerPluginDbTestCase): + def setUp(self): + super(TestLoadBalancerPluginBase, self).setUp( + lbaas_provider=EDGE_PROVIDER) + + loaded_plugins = manager.NeutronManager().get_service_plugins() + self.service_plugin = loaded_plugins[constants.LOADBALANCER] + self.edge_driver = self.service_plugin.drivers['vmwareedge'] + self.service_plugin._core_plugin.nsx_v = mock.Mock() + + +class TestEdgeLoadBalancerPlugin(TestLoadBalancerPluginBase): + def setUp(self): + super(TestEdgeLoadBalancerPlugin, self).setUp() + self.context = context.get_admin_context() + + def test_create_pool_successful(self): + pool = {'id': POOL_ID} + + with contextlib.nested( + mock.patch.object(db, 'add_nsxv_edge_pool_mapping'), + mock.patch.object(self.edge_driver, 'pool_successful') + ) as (mock_add_pool, mock_pool_successful): + self.edge_driver.create_pool_successful(self.context, + pool, + EDGE_ID, EDGE_POOL_ID) + mock_add_pool.assert_called_with(self.context, POOL_ID, EDGE_ID, + EDGE_POOL_ID) + mock_pool_successful.assert_called_with(self.context, pool) + + def test_delete_pool_successful(self): + pool = {'id': POOL_ID} + + with contextlib.nested( + mock.patch.object(self.service_plugin, '_delete_db_pool'), + mock.patch.object(db, 'delete_nsxv_edge_pool_mapping') + ) as (mock_del_db_pool, mock_del_mapping): + self.edge_driver.delete_pool_successful(self.context, pool) + mock_del_db_pool.assert_called_with(self.context, POOL_ID) + mock_del_mapping.assert_called_with(self.context, POOL_ID) + + def test_pool_successful(self): + pool = {'id': POOL_ID} + + with mock.patch.object(self.service_plugin, 'update_status') as ( + mock_update_status): + self.edge_driver.pool_successful(self.context, pool) + mock_update_status.assert_called_with(self.context, lb_db.Pool, + pool['id'], constants.ACTIVE) + + def test_pool_failed(self): + pool = {'id': POOL_ID} + + with mock.patch.object(self.service_plugin, 'update_status') as ( + mock_update_status): + self.edge_driver.pool_failed(self.context, pool) + mock_update_status.assert_called_with(self.context, lb_db.Pool, + pool['id'], constants.ERROR) + + def test_create_pool(self): + lbaas_pool = { + 'status': 'PENDING_CREATE', 'lb_method': 'ROUND_ROBIN', + 'protocol': 'HTTP', 'description': '', 'health_monitors': [], + 'members': [], 'status_description': None, 'id': POOL_ID, + 'vip_id': None, 'name': 'testpool', 'admin_state_up': True, + 'subnet_id': SUBNET_ID, 'tenant_id': TENANT_ID, + 'health_monitors_status': [], 'provider': 'vmwareedge'} + + with mock.patch.object(self.service_plugin._core_plugin.nsx_v, + 'create_pool') as mock_create_pool: + + self.edge_driver.create_pool(self.context, lbaas_pool) + mock_create_pool.assert_called_with(self.context, lbaas_pool) + + def test_update_pool(self): + from_pool = { + 'status': 'ACTIVE', 'lb_method': 'ROUND_ROBIN', + 'protocol': 'HTTP', 'description': '', 'health_monitors': [], + 'members': [], 'status_description': None, 'id': POOL_ID, + 'vip_id': None, 'name': 'testpool2', 'admin_state_up': True, + 'subnet_id': SUBNET_ID, 'tenant_id': TENANT_ID, + 'health_monitors_status': [], 'provider': 'vmwareedge'} + + to_pool = { + 'status': 'PENDING_UPDATE', 'lb_method': 'LEAST_CONNECTIONS', + 'protocol': 'HTTP', 'description': '', 'health_monitors': [], + 'members': [], 'status_description': None, 'id': POOL_ID, + 'vip_id': None, 'name': 'testpool2', 'admin_state_up': True, + 'subnet_id': SUBNET_ID, 'tenant_id': TENANT_ID, + 'health_monitors_status': [], 'provider': 'vmwareedge'} + + mapping = {'edge_id': EDGE_ID, 'edge_pool_id': EDGE_POOL_ID} + + with contextlib.nested( + mock.patch.object(db, 'get_nsxv_edge_pool_mapping'), + mock.patch.object(self.service_plugin._core_plugin.nsx_v, + 'update_pool') + ) as (mock_get_mapping, mock_update_pool): + + mock_get_mapping.return_value = mapping + self.edge_driver.update_pool(self.context, from_pool, to_pool) + mock_update_pool.assert_called_with(self.context, from_pool, + to_pool, mapping) + + def test_delete_pool(self): + lbaas_pool = { + 'status': 'PENDING_CREATE', 'lb_method': 'ROUND_ROBIN', + 'protocol': 'HTTP', 'description': '', 'health_monitors': [], + 'members': [], 'status_description': None, 'id': POOL_ID, + 'vip_id': None, 'name': 'testpool', 'admin_state_up': True, + 'subnet_id': SUBNET_ID, 'tenant_id': TENANT_ID, + 'health_monitors_status': [], 'provider': 'vmwareedge'} + mapping = {'edge_id': EDGE_ID, 'edge_pool_id': EDGE_POOL_ID} + + with contextlib.nested( + mock.patch.object(db, 'get_nsxv_edge_pool_mapping'), + mock.patch.object(self.service_plugin, 'get_pool', + return_value={}), + mock.patch.object(self.service_plugin._core_plugin.nsx_v, + 'delete_pool') + ) as (mock_get_mapping, mock_get_pool, mock_delete_pool): + + mock_get_mapping.return_value = mapping + self.edge_driver.delete_pool(self.context, lbaas_pool) + mock_delete_pool.assert_called_with(self.context, lbaas_pool, + mapping) + + def test_create_vip_successful(self): + vip = {'pool_id': POOL_ID} + with contextlib.nested( + mock.patch.object(db, 'add_nsxv_edge_vip_mapping'), + mock.patch.object(self.edge_driver, 'vip_successful') + ) as (mock_add_vip_mapping, mock_vip_successful): + + self.edge_driver.create_vip_successful( + self.context, vip, EDGE_ID, APP_PROFILE_ID, EDGE_VSE_ID, + EDGE_FW_RULE_ID) + + mock_add_vip_mapping.assert_called_with( + self.context, POOL_ID, EDGE_ID, APP_PROFILE_ID, + EDGE_VSE_ID, EDGE_FW_RULE_ID) + mock_vip_successful.assert_called_with(self.context, vip) + + def test_delete_vip_successful(self): + vip = {'pool_id': POOL_ID, 'id': VIP_ID} + with contextlib.nested( + mock.patch.object(db, 'delete_nsxv_edge_vip_mapping'), + mock.patch.object(self.service_plugin, '_delete_db_vip') + ) as (mock_del_vip_mapping, mock_del_vip): + + self.edge_driver.delete_vip_successful(self.context, vip) + mock_del_vip_mapping.assert_called_with(self.context, POOL_ID) + mock_del_vip.assert_called_with(self.context, VIP_ID) + + def test_vip_successful(self): + vip = {'pool_id': POOL_ID, 'id': VIP_ID} + with mock.patch.object(self.service_plugin, 'update_status') as ( + mock_update_status): + self.edge_driver.vip_successful(self.context, vip) + mock_update_status.assert_called_with( + self.context, lb_db.Vip, VIP_ID, constants.ACTIVE) + + def test_vip_failed(self): + vip = {'pool_id': POOL_ID, 'id': VIP_ID} + with mock.patch.object(self.service_plugin, 'update_status') as ( + mock_update_status): + self.edge_driver.vip_failed(self.context, vip) + mock_update_status.assert_called_with( + self.context, lb_db.Vip, VIP_ID, constants.ERROR) + + def test_create_vip(self): + lbaas_vip = { + 'status': 'PENDING_CREATE', 'protocol': 'HTTP', + 'description': '', 'address': '10.0.0.8', 'protocol_port': 555, + 'port_id': VIP_PORT_ID, 'id': VIP_ID, 'status_description': None, + 'name': 'testvip1', 'admin_state_up': True, + 'subnet_id': SUBNET_ID, 'tenant_id': TENANT_ID, + 'connection_limit': -1, 'pool_id': POOL_ID, + 'session_persistence': {'type': 'SOURCE_IP'}} + mapping = {'edge_id': EDGE_ID, 'edge_pool_id': EDGE_POOL_ID} + + with contextlib.nested( + mock.patch.object(db, 'get_nsxv_edge_pool_mapping'), + mock.patch.object(self.service_plugin._core_plugin.nsx_v, + 'create_vip') + ) as (mock_get_mapping, mock_create_vip): + mock_get_mapping.return_value = mapping + self.edge_driver.create_vip(self.context, lbaas_vip) + mock_create_vip.assert_called_with(self.context, lbaas_vip, + mapping) + + def test_update_vip(self): + vip_from = { + 'status': 'ACTIVE', 'protocol': 'HTTP', 'description': '', + 'address': '10.0.0.8', 'protocol_port': 555L, + 'port_id': VIP_PORT_ID, 'id': VIP_ID, 'status_description': None, + 'name': 'testvip1', 'admin_state_up': True, + 'subnet_id': SUBNET_ID, 'tenant_id': TENANT_ID, + 'connection_limit': -1L, 'pool_id': POOL_ID, + 'session_persistence': {'type': 'SOURCE_IP'}} + vip_to = { + 'status': 'PENDING_UPDATE', 'protocol': 'HTTP', + 'description': '', 'address': '10.0.0.8', 'protocol_port': 555L, + 'port_id': VIP_PORT_ID, 'id': VIP_ID, 'status_description': None, + 'name': 'testvip1', 'admin_state_up': True, + 'subnet_id': SUBNET_ID, 'tenant_id': TENANT_ID, + 'connection_limit': -1, 'pool_id': POOL_ID, + 'session_persistence': {'type': 'HTTP_COOKIE'}} + pool_mapping = {'edge_id': EDGE_ID, 'edge_pool_id': EDGE_POOL_ID} + vip_mapping = {'edge_id': EDGE_ID, 'edge_vse_id': EDGE_VSE_ID, + 'edge_app_profile_id': APP_PROFILE_ID} + + with contextlib.nested( + mock.patch.object(db, 'get_nsxv_edge_pool_mapping'), + mock.patch.object(db, 'get_nsxv_edge_vip_mapping'), + mock.patch.object(self.service_plugin._core_plugin.nsx_v, + 'update_vip') + ) as (mock_get_pool_mapping, mock_get_vip_mapping, mock_upd_vip): + + mock_get_pool_mapping.return_value = pool_mapping + mock_get_vip_mapping.return_value = vip_mapping + self.edge_driver.update_vip(self.context, vip_from, vip_to) + mock_upd_vip.assert_called_with(self.context, vip_from, vip_to, + pool_mapping, vip_mapping) + + def test_delete_vip(self): + lbaas_vip = { + 'status': 'PENDING_DELETE', 'protocol': 'HTTP', + 'description': '', 'address': '10.0.0.11', 'protocol_port': 555L, + 'port_id': VIP_PORT_ID, 'id': VIP_ID, 'status_description': None, + 'name': 'testvip', 'admin_state_up': True, 'subnet_id': SUBNET_ID, + 'tenant_id': TENANT_ID, 'connection_limit': -1L, + 'pool_id': POOL_ID, 'session_persistence': None} + mapping = {'edge_id': EDGE_ID, 'edge_vse_id': EDGE_VSE_ID, + 'edge_app_profile_id': APP_PROFILE_ID, + 'edge_fw_rule_id': EDGE_FW_RULE_ID} + + with contextlib.nested( + mock.patch.object(db, 'get_nsxv_edge_vip_mapping'), + mock.patch.object(self.service_plugin._core_plugin.nsx_v, + 'delete_vip') + ) as (mock_get_mapping, mock_del_vip): + + mock_get_mapping.return_value = mapping + self.edge_driver.delete_vip(self.context, lbaas_vip) + mock_del_vip.assert_called_with(self.context, lbaas_vip, mapping) + + def test_member_successful(self): + member = {'id': MEMBER_ID} + with mock.patch.object(self.service_plugin, 'update_status') as ( + mock_update_status): + self.edge_driver.member_successful(self.context, member) + mock_update_status.assert_called_with( + self.context, lb_db.Member, member['id'], constants.ACTIVE) + + def test_member_failed(self): + member = {'id': MEMBER_ID} + with mock.patch.object(self.service_plugin, 'update_status') as ( + mock_update_status): + self.edge_driver.member_failed(self.context, member) + mock_update_status.assert_called_with( + self.context, lb_db.Member, member['id'], constants.ERROR) + + def test_create_member(self): + lbaas_member = { + 'admin_state_up': True, 'status': 'PENDING_CREATE', + 'status_description': None, 'weight': 5, 'address': '10.0.0.4', + 'tenant_id': TENANT_ID, 'protocol_port': 555, 'id': MEMBER_ID, + 'pool_id': POOL_ID} + mapping = {'edge_id': EDGE_ID, 'edge_pool_id': EDGE_POOL_ID} + + with contextlib.nested( + mock.patch.object(db, 'get_nsxv_edge_pool_mapping'), + mock.patch.object(self.service_plugin._core_plugin.nsx_v, + 'create_member') + ) as (mock_get_mapping, mock_create_member): + + mock_get_mapping.return_value = mapping + self.edge_driver.create_member(self.context, lbaas_member) + mock_create_member.assert_called_with(self.context, lbaas_member, + mapping) + + def test_update_member(self): + member_from = { + 'admin_state_up': True, 'status': 'PENDING_UPDATE', + 'status_description': None, 'weight': 5, 'address': '10.0.0.4', + 'tenant_id': TENANT_ID, 'protocol_port': 555, 'id': MEMBER_ID, + 'pool_id': POOL_ID} + member_to = { + 'admin_state_up': True, 'status': 'ACTIVE', + 'status_description': None, 'weight': 10, 'address': '10.0.0.4', + 'tenant_id': TENANT_ID, 'protocol_port': 555, 'id': MEMBER_ID, + 'pool_id': POOL_ID} + mapping = {'edge_id': EDGE_ID, 'edge_pool_id': EDGE_POOL_ID} + + with contextlib.nested( + mock.patch.object(db, 'get_nsxv_edge_pool_mapping'), + mock.patch.object(self.service_plugin._core_plugin.nsx_v, + 'update_member') + ) as (mock_get_mapping, mock_update_member): + + mock_get_mapping.return_value = mapping + self.edge_driver.update_member(self.context, member_from, + member_to) + mock_update_member.assert_called_with(self.context, member_from, + member_to, mapping) + + def test_delete_member(self): + lbaas_member = { + 'admin_state_up': True, 'status': 'PENDING_DELETE', + 'status_description': None, 'weight': 5, 'address': '10.0.0.4', + 'tenant_id': TENANT_ID, 'protocol_port': 555, 'id': MEMBER_ID, + 'pool_id': POOL_ID} + mapping = {'edge_id': EDGE_ID, 'edge_pool_id': EDGE_POOL_ID} + + with contextlib.nested( + mock.patch.object(db, 'get_nsxv_edge_pool_mapping'), + mock.patch.object(self.service_plugin._core_plugin.nsx_v, + 'delete_member') + ) as (mock_get_mapping, mock_delete_member): + + mock_get_mapping.return_value = mapping + self.edge_driver.delete_member(self.context, lbaas_member) + mock_delete_member.assert_called_with(self.context, lbaas_member, + mapping) + + def test_create_pool_health_monitor_successful(self): + hmon = {'id': HEALTHMON_ID} + with contextlib.nested( + mock.patch.object(db, 'add_nsxv_edge_monitor_mapping'), + mock.patch.object(self.edge_driver, + 'pool_health_monitor_successful') + ) as (mock_add_pool_mon_mapping, mock_pool_hmon_successful): + self.edge_driver.create_pool_health_monitor_successful( + self.context, hmon, POOL_ID, EDGE_ID, EDGE_MON_ID) + mock_add_pool_mon_mapping.assert_called_with( + self.context, HEALTHMON_ID, EDGE_ID, EDGE_MON_ID) + mock_pool_hmon_successful.assert_called_with(self.context, + hmon, POOL_ID) + + def test_delete_pool_health_monitor_successful(self): + hmon = {'id': HEALTHMON_ID, 'pool_id': POOL_ID} + hmon_mapping = {'edge_id': EDGE_ID} + with contextlib.nested( + mock.patch.object(db, 'delete_nsxv_edge_monitor_mapping'), + mock.patch.object(self.service_plugin, + '_delete_db_pool_health_monitor') + ) as (mock_del_pool_hmon_mapping, mock_del_db_pool_hmon): + + self.edge_driver.delete_pool_health_monitor_successful( + self.context, hmon, POOL_ID, hmon_mapping) + mock_del_pool_hmon_mapping.assert_called_with( + self.context, HEALTHMON_ID, EDGE_ID) + mock_del_db_pool_hmon.assert_called_with( + self.context, HEALTHMON_ID, POOL_ID) + + def test_pool_health_monitor_successful(self): + hmon = {'id': HEALTHMON_ID} + with mock.patch.object(self.service_plugin, + 'update_pool_health_monitor') as ( + mock_update_hmon): + self.edge_driver.pool_health_monitor_successful(self.context, + hmon, POOL_ID) + mock_update_hmon.assert_called_with( + self.context, HEALTHMON_ID, POOL_ID, constants.ACTIVE, '') + + def test_pool_health_monitor_failed(self): + hmon = {'id': HEALTHMON_ID} + with mock.patch.object(self.service_plugin, + 'update_pool_health_monitor') as ( + mock_update_hmon): + self.edge_driver.pool_health_monitor_failed(self.context, hmon, + POOL_ID) + mock_update_hmon.assert_called_with( + self.context, HEALTHMON_ID, POOL_ID, constants.ERROR, '') + + def test_create_pool_health_monitor(self): + hmon = { + 'admin_state_up': True, 'tenant_id': TENANT_ID, 'delay': 5L, + 'max_retries': 5L, 'timeout': 5L, 'pools': [ + {'status': 'PENDING_CREATE', 'status_description': None, + 'pool_id': POOL_ID}], + 'type': 'PING', 'id': HEALTHMON_ID} + pool_mapping = {'edge_id': EDGE_ID, 'edge_pool_id': EDGE_POOL_ID} + + with contextlib.nested( + mock.patch.object(db, 'get_nsxv_edge_pool_mapping'), + mock.patch.object(db, 'get_nsxv_edge_monitor_mapping'), + mock.patch.object(self.service_plugin._core_plugin.nsx_v, + 'create_pool_health_monitor') + ) as (mock_get_pool_mapping, mock_get_mon_mapping, + mock_create_pool_hm): + + mock_get_pool_mapping.return_value = pool_mapping + mock_get_mon_mapping.return_value = None + self.edge_driver.create_pool_health_monitor(self.context, + hmon, POOL_ID) + mock_create_pool_hm.assert_called_with(self.context, hmon, POOL_ID, + pool_mapping, None) + + def test_update_pool_health_monitor(self): + from_hmon = { + 'admin_state_up': True, 'tenant_id': TENANT_ID, 'delay': 5L, + 'max_retries': 5L, 'timeout': 5L, 'pools': [ + {'status': 'PENDING_UPDATE', 'status_description': None, + 'pool_id': POOL_ID}], + 'type': 'PING', 'id': HEALTHMON_ID} + to_hmon = { + 'admin_state_up': True, 'tenant_id': TENANT_ID, 'delay': 5L, + 'max_retries': 10L, 'timeout': 5L, 'pools': [ + {'status': 'ACTIVE', 'status_description': None, + 'pool_id': POOL_ID}], + 'type': 'PING', 'id': HEALTHMON_ID} + pool_mapping = {'edge_id': EDGE_ID, 'edge_pool_id': EDGE_POOL_ID} + mon_mapping = {'edge_id': EDGE_ID, 'edge_monitor_id': EDGE_MON_ID} + + with contextlib.nested( + mock.patch.object(db, 'get_nsxv_edge_pool_mapping'), + mock.patch.object(db, 'get_nsxv_edge_monitor_mapping'), + mock.patch.object(self.service_plugin._core_plugin.nsx_v, + 'update_pool_health_monitor') + ) as (mock_get_pool_mapping, mock_get_mon_mapping, mock_upd_pool_hm): + + mock_get_pool_mapping.return_value = pool_mapping + mock_get_mon_mapping.return_value = mon_mapping + self.edge_driver.update_pool_health_monitor( + self.context, from_hmon, to_hmon, POOL_ID) + + mock_upd_pool_hm.assert_called_with( + self.context, from_hmon, to_hmon, POOL_ID, mon_mapping) + + def test_delete_pool_health_monitor(self): + hmon = { + 'admin_state_up': True, 'tenant_id': TENANT_ID, 'delay': 5L, + 'max_retries': 5L, 'timeout': 5L, 'pools': [ + {'status': 'PENDING_DELETE', 'status_description': None, + 'pool_id': POOL_ID}], + 'type': 'PING', 'id': HEALTHMON_ID} + pool_mapping = {'edge_id': EDGE_ID, 'edge_pool_id': EDGE_POOL_ID} + mon_mapping = {'edge_id': EDGE_ID, 'edge_monitor_id': EDGE_MON_ID} + + with contextlib.nested( + mock.patch.object(db, 'get_nsxv_edge_pool_mapping'), + mock.patch.object(db, 'get_nsxv_edge_monitor_mapping'), + mock.patch.object(self.service_plugin._core_plugin.nsx_v, + 'delete_pool_health_monitor') + ) as (mock_get_pool_mapping, mock_get_mon_mapping, mock_del_pool_hm): + + mock_get_pool_mapping.return_value = pool_mapping + mock_get_mon_mapping.return_value = mon_mapping + self.edge_driver.delete_pool_health_monitor(self.context, hmon, + POOL_ID) + mock_del_pool_hm.assert_called_with(self.context, hmon, POOL_ID, + pool_mapping, mon_mapping)