# Copyright 2018 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 unittest import mock import decorator import testtools from oslo_utils import uuidutils from octavia_lib.api.drivers import data_models code_ok = True # Skip duplications between Octavia & Neutron configurations and missing # configuration groups with mock.patch('oslo_config.cfg.ConfigOpts.import_group'),\ mock.patch('oslo_config.cfg.ConfigOpts.__getattr__'): try: from vmware_nsx.services.lbaas.octavia import octavia_driver as driver except ImportError: # Octavia code not found # this can happen as Octavia is not in the requirements yet code_ok = False DRIVER = 'vmware_nsx.services.lbaas.octavia.octavia_driver.NSXOctaviaDriver' class TestNsxProviderDriver(testtools.TestCase): """Test the NSX Octavia driver Make sure all the relevant data is translated and sent to the listener """ def setUp(self): super(TestNsxProviderDriver, self).setUp() global code_ok if not code_ok: return # init the NSX driver without the RPC & certificate with mock.patch(DRIVER + '._init_rpc_messaging'): self.driver = driver.NSXOctaviaDriver() self.driver.client = mock.Mock() self.loadbalancer_id = uuidutils.generate_uuid() self.vip_address = '192.0.2.10' self.vip_network_id = uuidutils.generate_uuid() self.vip_port_id = uuidutils.generate_uuid() self.vip_subnet_id = uuidutils.generate_uuid() self.listener_id = uuidutils.generate_uuid() self.pool_id = uuidutils.generate_uuid() self.member_id = uuidutils.generate_uuid() self.member_subnet_id = uuidutils.generate_uuid() self.healthmonitor_id = uuidutils.generate_uuid() self.l7policy_id = uuidutils.generate_uuid() self.l7rule_id = uuidutils.generate_uuid() self.project_id = uuidutils.generate_uuid() self.default_tls_container_ref = uuidutils.generate_uuid() self.default_tls_container_data = { 'ref': self.default_tls_container_ref, 'certificate': 'cert_text', 'private_key': 'pk_text', 'passphrase': 'pp_text'} self.sni_container_ref_1 = uuidutils.generate_uuid() self.sni_container_ref_2 = uuidutils.generate_uuid() self.ref_member = data_models.Member( address='198.51.100.4', admin_state_up=True, member_id=self.member_id, monitor_address='203.0.113.2', monitor_port=66, name='jacket', pool_id=self.pool_id, protocol_port=99, subnet_id=self.member_subnet_id, weight=55) self.ref_healthmonitor = data_models.HealthMonitor( admin_state_up=False, delay=2, expected_codes="500", healthmonitor_id=self.healthmonitor_id, http_method='TRACE', max_retries=1, max_retries_down=0, name='doc', pool_id=self.pool_id, timeout=3, type='PHD', url_path='/index.html') self.ref_pool = data_models.Pool( admin_state_up=True, description='Olympic swimming pool', healthmonitor=self.ref_healthmonitor, lb_algorithm='A_Fast_One', loadbalancer_id=self.loadbalancer_id, members=[self.ref_member], name='Osborn', pool_id=self.pool_id, protocol='avian', session_persistence={'type': 'glue'}) self.ref_l7rule = data_models.L7Rule( admin_state_up=True, compare_type='store_brand', invert=True, key='board', l7policy_id=self.l7policy_id, l7rule_id=self.l7rule_id, type='strict', value='gold') self.ref_l7policy = data_models.L7Policy( action='packed', admin_state_up=False, description='Corporate policy', l7policy_id=self.l7policy_id, listener_id=self.listener_id, name='more_policy', position=1, redirect_pool_id=self.pool_id, redirect_url='/hr', rules=[self.ref_l7rule]) self.ref_listener = data_models.Listener( admin_state_up=False, connection_limit=5, default_pool=self.ref_pool, default_pool_id=self.pool_id, default_tls_container_data=self.default_tls_container_data, default_tls_container_ref=self.default_tls_container_ref, description='The listener', insert_headers={'X-Forwarded-For': 'true'}, l7policies=[self.ref_l7policy], listener_id=self.listener_id, loadbalancer_id=self.loadbalancer_id, name='super_listener', protocol='avian', protocol_port=42, sni_container_data=['sni_cert_data_1', 'sni_cert_data_2'], sni_container_refs=[self.sni_container_ref_1, self.sni_container_ref_2]) self.ref_lb = data_models.LoadBalancer( admin_state_up=False, description='One great load balancer', flavor={'cake': 'chocolate'}, listeners=[self.ref_listener], loadbalancer_id=self.loadbalancer_id, name='favorite_lb', project_id=self.project_id, vip_address=self.vip_address, vip_network_id=self.vip_network_id, vip_port_id=self.vip_port_id, vip_subnet_id=self.vip_subnet_id) # start DB mocks mock.patch('octavia.db.api.get_session').start() mock.patch("octavia.api.drivers.utils.db_pool_to_provider_pool", return_value=self.ref_pool).start() @decorator.decorator def skip_no_octavia(f, *args, **kwargs): global code_ok if not code_ok: obj = args[0] return obj.skipTest('Octavia code not found') return f(*args, **kwargs) @skip_no_octavia def test_loadbalancer_create(self): with mock.patch.object(self.driver.client, 'cast') as cast_method: self.driver.loadbalancer_create(self.ref_lb) cast_method.assert_called_with({}, 'loadbalancer_create', loadbalancer=mock.ANY) driver_obj = cast_method.call_args[1]['loadbalancer'] self.assertIn('id', driver_obj) self.assertIn('project_id', driver_obj) self.assertIn('admin_state_up', driver_obj) self.assertIn('name', driver_obj) self.assertIn('listeners', driver_obj) self.assertEqual(1, len(driver_obj['listeners'])) self.assertEqual(self.ref_lb.vip_address, driver_obj['vip_address']) self.assertEqual(self.ref_lb.vip_network_id, driver_obj['vip_network_id']) self.assertEqual(self.ref_lb.vip_port_id, driver_obj['vip_port_id']) self.assertEqual(self.ref_lb.vip_subnet_id, driver_obj['vip_subnet_id']) @skip_no_octavia def test_loadbalancer_delete(self): with mock.patch.object(self.driver.client, 'cast') as cast_method: self.driver.loadbalancer_delete(self.ref_lb) cast_method.assert_called_with({}, 'loadbalancer_delete', cascade=False, loadbalancer=mock.ANY) driver_obj = cast_method.call_args[1]['loadbalancer'] self.assertIn('id', driver_obj) self.assertIn('project_id', driver_obj) @skip_no_octavia def test_loadbalancer_update(self): with mock.patch.object(self.driver.client, 'cast') as cast_method: self.driver.loadbalancer_update(self.ref_lb, self.ref_lb) cast_method.assert_called_with({}, 'loadbalancer_update', old_loadbalancer=mock.ANY, new_loadbalancer=mock.ANY) driver_obj = cast_method.call_args[1]['new_loadbalancer'] self.assertIn('id', driver_obj) self.assertIn('project_id', driver_obj) @skip_no_octavia def test_listener_create(self): with mock.patch.object(self.driver.client, 'cast') as cast_method: self.driver.listener_create(self.ref_listener) cast_method.assert_called_with( {}, 'listener_create', cert=self.default_tls_container_data, listener=mock.ANY) driver_obj = cast_method.call_args[1]['listener'] self.assertIn('id', driver_obj) self.assertIn('project_id', driver_obj) self.assertIn('admin_state_up', driver_obj) self.assertIn('name', driver_obj) self.assertIn('loadbalancer_id', driver_obj) self.assertIn('loadbalancer', driver_obj) self.assertEqual(self.ref_listener.protocol, driver_obj['protocol']) self.assertEqual(self.ref_listener.protocol_port, driver_obj['protocol_port']) self.assertEqual(self.ref_listener.connection_limit, driver_obj['connection_limit']) self.assertIn('l7policies', driver_obj) #TODO(asarfaty) add after the driver is fixed #self.assertIn('default_tls_container_id', driver_obj) @skip_no_octavia def test_listener_delete(self): with mock.patch.object(self.driver.client, 'cast') as cast_method: self.driver.listener_delete(self.ref_listener) cast_method.assert_called_with({}, 'listener_delete', listener=mock.ANY) driver_obj = cast_method.call_args[1]['listener'] self.assertIn('id', driver_obj) self.assertIn('project_id', driver_obj) @skip_no_octavia def test_listener_update(self): with mock.patch.object(self.driver.client, 'cast') as cast_method: self.driver.listener_update(self.ref_listener, self.ref_listener) cast_method.assert_called_with( {}, 'listener_update', cert=self.default_tls_container_data, old_listener=mock.ANY, new_listener=mock.ANY) driver_obj = cast_method.call_args[1]['new_listener'] self.assertIn('id', driver_obj) self.assertIn('project_id', driver_obj) @skip_no_octavia def test_pool_create(self): with mock.patch.object(self.driver.client, 'cast') as cast_method: self.driver.pool_create(self.ref_pool) cast_method.assert_called_with({}, 'pool_create', pool=mock.ANY) driver_obj = cast_method.call_args[1]['pool'] self.assertIn('id', driver_obj) self.assertIn('project_id', driver_obj) self.assertIn('admin_state_up', driver_obj) self.assertIn('name', driver_obj) self.assertIn('loadbalancer_id', driver_obj) self.assertIn('listener', driver_obj) self.assertIn('listeners', driver_obj) self.assertEqual(self.ref_pool.lb_algorithm, driver_obj['lb_algorithm']) self.assertEqual(self.ref_pool.session_persistence, driver_obj['session_persistence']) self.assertIn('members', driver_obj) @skip_no_octavia def test_pool_delete(self): with mock.patch.object(self.driver.client, 'cast') as cast_method: self.driver.pool_delete(self.ref_pool) cast_method.assert_called_with({}, 'pool_delete', pool=mock.ANY) driver_obj = cast_method.call_args[1]['pool'] self.assertIn('id', driver_obj) self.assertIn('project_id', driver_obj) @skip_no_octavia def test_pool_update(self): with mock.patch.object(self.driver.client, 'cast') as cast_method: self.driver.pool_update(self.ref_pool, self.ref_pool) cast_method.assert_called_with({}, 'pool_update', old_pool=mock.ANY, new_pool=mock.ANY) driver_obj = cast_method.call_args[1]['new_pool'] self.assertIn('id', driver_obj) self.assertIn('project_id', driver_obj) @skip_no_octavia def test_member_create(self): with mock.patch.object(self.driver.client, 'cast') as cast_method: self.driver.member_create(self.ref_member) cast_method.assert_called_with({}, 'member_create', member=mock.ANY) driver_obj = cast_method.call_args[1]['member'] self.assertIn('id', driver_obj) self.assertIn('project_id', driver_obj) self.assertIn('admin_state_up', driver_obj) self.assertIn('name', driver_obj) self.assertEqual(self.pool_id, driver_obj['pool_id']) self.assertIn('pool', driver_obj) self.assertIn('loadbalancer', driver_obj['pool']) #TODO(asarfaty) add when the driver is fixed #self.assertIn('listener', driver_obj['pool']) self.assertEqual(self.ref_member.subnet_id, driver_obj['subnet_id']) self.assertEqual(self.ref_member.address, driver_obj['address']) self.assertEqual(self.ref_member.protocol_port, driver_obj['protocol_port']) self.assertEqual(self.ref_member.weight, driver_obj['weight']) @skip_no_octavia def test_member_delete(self): with mock.patch.object(self.driver.client, 'cast') as cast_method: self.driver.member_delete(self.ref_member) cast_method.assert_called_with({}, 'member_delete', member=mock.ANY) driver_obj = cast_method.call_args[1]['member'] self.assertIn('id', driver_obj) self.assertIn('project_id', driver_obj) @skip_no_octavia def test_member_update(self): with mock.patch.object(self.driver.client, 'cast') as cast_method: self.driver.member_update(self.ref_member, self.ref_member) cast_method.assert_called_with({}, 'member_update', old_member=mock.ANY, new_member=mock.ANY) driver_obj = cast_method.call_args[1]['old_member'] self.assertIn('id', driver_obj) self.assertIn('project_id', driver_obj) @skip_no_octavia def test_health_monitor_create(self): with mock.patch.object(self.driver.client, 'cast') as cast_method: self.driver.health_monitor_create(self.ref_healthmonitor) cast_method.assert_called_with({}, 'healthmonitor_create', healthmonitor=mock.ANY) driver_obj = cast_method.call_args[1]['healthmonitor'] self.assertIn('id', driver_obj) self.assertIn('project_id', driver_obj) self.assertIn('admin_state_up', driver_obj) self.assertIn('name', driver_obj) self.assertEqual(self.ref_healthmonitor.type, driver_obj['type']) self.assertEqual(self.ref_healthmonitor.url_path, driver_obj['url_path']) self.assertEqual(self.ref_healthmonitor.delay, driver_obj['delay']) self.assertEqual(self.ref_healthmonitor.timeout, driver_obj['timeout']) self.assertEqual(self.ref_healthmonitor.max_retries, driver_obj['max_retries']) self.assertEqual(self.ref_healthmonitor.http_method, driver_obj['http_method']) self.assertIn('pool', driver_obj) self.assertEqual(self.pool_id, driver_obj['pool']['id']) self.assertEqual(self.loadbalancer_id, driver_obj['pool']['loadbalancer_id']) @skip_no_octavia def test_health_monitor_delete(self): with mock.patch.object(self.driver.client, 'cast') as cast_method: self.driver.health_monitor_delete(self.ref_healthmonitor) cast_method.assert_called_with({}, 'healthmonitor_delete', healthmonitor=mock.ANY) driver_obj = cast_method.call_args[1]['healthmonitor'] self.assertIn('id', driver_obj) self.assertIn('project_id', driver_obj) @skip_no_octavia def test_health_monitor_update(self): with mock.patch.object(self.driver.client, 'cast') as cast_method: self.driver.health_monitor_update(self.ref_healthmonitor, self.ref_healthmonitor) cast_method.assert_called_with({}, 'healthmonitor_update', old_healthmonitor=mock.ANY, new_healthmonitor=mock.ANY) driver_obj = cast_method.call_args[1]['new_healthmonitor'] self.assertIn('id', driver_obj) self.assertIn('project_id', driver_obj) @skip_no_octavia def test_l7policy_create(self): with mock.patch.object(self.driver.client, 'cast') as cast_method: self.driver.l7policy_create(self.ref_l7policy) cast_method.assert_called_with({}, 'l7policy_create', l7policy=mock.ANY) driver_obj = cast_method.call_args[1]['l7policy'] self.assertIn('id', driver_obj) self.assertIn('project_id', driver_obj) self.assertIn('admin_state_up', driver_obj) self.assertIn('name', driver_obj) self.assertIn('listener', driver_obj) self.assertEqual(self.listener_id, driver_obj['listener_id']) self.assertIn('rules', driver_obj) self.assertIn('position', driver_obj) self.assertEqual(self.ref_l7policy.action, driver_obj['action']) self.assertEqual(self.ref_l7policy.redirect_url, driver_obj['redirect_url']) self.assertEqual(self.ref_l7policy.redirect_pool_id, driver_obj['redirect_pool_id']) @skip_no_octavia def test_l7policy_delete(self): with mock.patch.object(self.driver.client, 'cast') as cast_method: self.driver.l7policy_delete(self.ref_l7policy) cast_method.assert_called_with({}, 'l7policy_delete', l7policy=mock.ANY) driver_obj = cast_method.call_args[1]['l7policy'] self.assertIn('id', driver_obj) self.assertIn('project_id', driver_obj) @skip_no_octavia def test_l7policy_update(self): with mock.patch.object(self.driver.client, 'cast') as cast_method: self.driver.l7policy_update(self.ref_l7policy, self.ref_l7policy) cast_method.assert_called_with({}, 'l7policy_update', old_l7policy=mock.ANY, new_l7policy=mock.ANY) driver_obj = cast_method.call_args[1]['new_l7policy'] self.assertIn('id', driver_obj) self.assertIn('project_id', driver_obj) @skip_no_octavia def test_l7rule_create(self): with mock.patch.object(self.driver.client, 'cast') as cast_method: self.driver.l7rule_create(self.ref_l7rule) cast_method.assert_called_with({}, 'l7rule_create', l7rule=mock.ANY) driver_obj = cast_method.call_args[1]['l7rule'] self.assertIn('id', driver_obj) self.assertIn('project_id', driver_obj) self.assertIn('admin_state_up', driver_obj) self.assertIn('name', driver_obj) self.assertIn('policy', driver_obj) self.assertIn('rules', driver_obj['policy']) self.assertEqual(self.ref_l7rule.type, driver_obj['type']) self.assertEqual(self.ref_l7rule.value, driver_obj['value']) self.assertEqual(self.ref_l7rule.invert, driver_obj['invert']) @skip_no_octavia def test_l7rule_delete(self): with mock.patch.object(self.driver.client, 'cast') as cast_method: self.driver.l7rule_delete(self.ref_l7rule) cast_method.assert_called_with({}, 'l7rule_delete', l7rule=mock.ANY) driver_obj = cast_method.call_args[1]['l7rule'] self.assertIn('id', driver_obj) self.assertIn('project_id', driver_obj) @skip_no_octavia def test_l7rule_update(self): with mock.patch.object(self.driver.client, 'cast') as cast_method: self.driver.l7rule_update(self.ref_l7rule, self.ref_l7rule) cast_method.assert_called_with({}, 'l7rule_update', old_l7rule=mock.ANY, new_l7rule=mock.ANY) driver_obj = cast_method.call_args[1]['new_l7rule'] self.assertIn('id', driver_obj) self.assertIn('project_id', driver_obj)