#
# @author: Oleg Bondarev (obondarev@mirantis.com)
+import contextlib
+import mock
import testtools
+from oslo.config import cfg as config
+
from quantum.plugins.services.agent_loadbalancer.drivers.haproxy import cfg
class TestHaproxyCfg(testtools.TestCase):
+ def test_save_config(self):
+ with contextlib.nested(
+ mock.patch('quantum.plugins.services.agent_loadbalancer.'
+ 'drivers.haproxy.cfg._build_global'),
+ mock.patch('quantum.plugins.services.agent_loadbalancer.'
+ 'drivers.haproxy.cfg._build_defaults'),
+ mock.patch('quantum.plugins.services.agent_loadbalancer.'
+ 'drivers.haproxy.cfg._build_frontend'),
+ mock.patch('quantum.plugins.services.agent_loadbalancer.'
+ 'drivers.haproxy.cfg._build_backend'),
+ mock.patch('quantum.agent.linux.utils.replace_file')
+ ) as (b_g, b_d, b_f, b_b, replace):
+ test_config = ['globals', 'defaults', 'frontend', 'backend']
+ b_g.return_value = [test_config[0]]
+ b_d.return_value = [test_config[1]]
+ b_f.return_value = [test_config[2]]
+ b_b.return_value = [test_config[3]]
+
+ cfg.save_config('test_path', mock.Mock())
+ replace.assert_called_once_with('test_path',
+ '\n'.join(test_config))
+
+ def test_build_global(self):
+ config.CONF.register_opt(config.StrOpt('user_group'))
+ config.CONF.set_override('user_group', 'test_group')
+ expected_opts = ['global',
+ '\tdaemon',
+ '\tuser nobody',
+ '\tgroup test_group',
+ '\tlog /dev/log local0',
+ '\tlog /dev/log local1 notice',
+ '\tstats socket test_path mode 0666 level user']
+ opts = cfg._build_global(mock.Mock(), 'test_path')
+ self.assertEqual(expected_opts, list(opts))
+ config.CONF.reset()
+
+ def test_build_defaults(self):
+ expected_opts = ['defaults',
+ '\tlog global',
+ '\tretries 3',
+ '\toption redispatch',
+ '\ttimeout connect 5000',
+ '\ttimeout client 50000',
+ '\ttimeout server 50000']
+ opts = cfg._build_defaults(mock.Mock())
+ self.assertEqual(expected_opts, list(opts))
+ config.CONF.reset()
+
+ def test_build_frontend(self):
+ test_config = {'vip': {'id': 'vip_id',
+ 'protocol': 'HTTP',
+ 'port': {'fixed_ips': [
+ {'ip_address': '10.0.0.2'}]
+ },
+ 'protocol_port': 80,
+ 'connection_limit': 2000,
+ },
+ 'pool': {'id': 'pool_id'}}
+ expected_opts = ['frontend vip_id',
+ '\toption tcplog',
+ '\tbind 10.0.0.2:80',
+ '\tmode http',
+ '\tdefault_backend pool_id',
+ '\tmaxconn 2000',
+ '\toption forwardfor']
+ opts = cfg._build_frontend(test_config)
+ self.assertEqual(expected_opts, list(opts))
+
+ test_config['vip']['connection_limit'] = -1
+ expected_opts.remove('\tmaxconn 2000')
+ opts = cfg._build_frontend(test_config)
+ self.assertEqual(expected_opts, list(opts))
+
+ def test_build_backend(self):
+ test_config = {'pool': {'id': 'pool_id',
+ 'protocol': 'HTTP',
+ 'lb_method': 'ROUND_ROBIN'},
+ 'members': [{'status': 'ACTIVE',
+ 'admin_state_up': True,
+ 'id': 'member1_id',
+ 'address': '10.0.0.3',
+ 'protocol_port': 80,
+ 'weight': 1}],
+ 'healthmonitors': [{'status': 'ACTIVE',
+ 'admin_state_up': True,
+ 'delay': 3,
+ 'max_retries': 4,
+ 'timeout': 2,
+ 'type': 'TCP'}],
+ 'vip': {'session_persistence': {'type': 'HTTP_COOKIE'}}}
+ expected_opts = ['backend pool_id',
+ '\tmode http',
+ '\tbalance roundrobin',
+ '\toption forwardfor',
+ '\ttimeout check 2s',
+ '\tcookie SRV insert indirect nocache',
+ '\tserver member1_id 10.0.0.3:80 weight 1 '
+ 'check inter 3s fall 4 cookie 0']
+ opts = cfg._build_backend(test_config)
+ self.assertEqual(expected_opts, list(opts))
+
+ def test_get_server_health_option(self):
+ test_config = {'healthmonitors': [{'status': 'ERROR',
+ 'admin_state_up': False,
+ 'delay': 3,
+ 'max_retries': 4,
+ 'timeout': 2,
+ 'type': 'TCP',
+ 'http_method': 'GET',
+ 'url_path': '/',
+ 'expected_codes': '200'}]}
+ self.assertEqual(('', []), cfg._get_server_health_option(test_config))
+
+ test_config['healthmonitors'][0]['status'] = 'ACTIVE'
+ self.assertEqual(('', []), cfg._get_server_health_option(test_config))
+
+ test_config['healthmonitors'][0]['admin_state_up'] = True
+ expected = (' check inter 3s fall 4', ['timeout check 2s'])
+ self.assertEqual(expected, cfg._get_server_health_option(test_config))
+
+ test_config['healthmonitors'][0]['type'] = 'HTTPS'
+ expected = (' check inter 3s fall 4',
+ ['timeout check 2s',
+ 'option httpchk GET /',
+ 'http-check expect rstatus 200',
+ 'option ssl-hello-chk'])
+ self.assertEqual(expected, cfg._get_server_health_option(test_config))
def test_has_http_cookie_persistence(self):
config = {'vip': {'session_persistence': {'type': 'HTTP_COOKIE'}}}
config = {'vip': {'session_persistence': {'type': 'UNSUPPORTED'}}}
self.assertEqual(cfg._get_session_persistence(config), [])
+
+ def test_expand_expected_codes(self):
+ exp_codes = ''
+ self.assertEqual(cfg._expand_expected_codes(exp_codes), set([]))
+ exp_codes = '200'
+ self.assertEqual(cfg._expand_expected_codes(exp_codes), set(['200']))
+ exp_codes = '200, 201'
+ self.assertEqual(cfg._expand_expected_codes(exp_codes),
+ set(['200', '201']))
+ exp_codes = '200, 201,202'
+ self.assertEqual(cfg._expand_expected_codes(exp_codes),
+ set(['200', '201', '202']))
+ exp_codes = '200-202'
+ self.assertEqual(cfg._expand_expected_codes(exp_codes),
+ set(['200', '201', '202']))
+ exp_codes = '200-202, 205'
+ self.assertEqual(cfg._expand_expected_codes(exp_codes),
+ set(['200', '201', '202', '205']))
+ exp_codes = '200, 201-203'
+ self.assertEqual(cfg._expand_expected_codes(exp_codes),
+ set(['200', '201', '202', '203']))
+ exp_codes = '200, 201-203, 205'
+ self.assertEqual(cfg._expand_expected_codes(exp_codes),
+ set(['200', '201', '202', '203', '205']))
+ exp_codes = '201-200, 205'
+ self.assertEqual(cfg._expand_expected_codes(exp_codes), set(['205']))
import mock
import testtools
+from quantum.common import exceptions
from quantum.plugins.services.agent_loadbalancer.drivers.haproxy import (
namespace_driver
)
socket.reset_mock()
self.assertEqual({}, self.driver.get_stats('pool_id'))
self.assertFalse(socket.called)
+
+ def test_plug(self):
+ test_port = {'id': 'port_id',
+ 'network_id': 'net_id',
+ 'mac_address': 'mac_addr',
+ 'fixed_ips': [{'ip_address': '10.0.0.2',
+ 'subnet': {'cidr': 'cidr'}}]}
+ with contextlib.nested(
+ mock.patch('quantum.agent.linux.ip_lib.device_exists'),
+ mock.patch('netaddr.IPNetwork'),
+ ) as (dev_exists, ip_net):
+ self.vif_driver.get_device_name.return_value = 'test_interface'
+ dev_exists.return_value = False
+ ip_net.return_value = ip_net
+ ip_net.prefixlen = 24
+
+ self.driver._plug('test_ns', test_port)
+ self.vip_plug_callback.assert_called_once_with('plug', test_port)
+ self.assertTrue(dev_exists.called)
+ self.vif_driver.plug.assert_called_once_with('net_id', 'port_id',
+ 'test_interface',
+ 'mac_addr',
+ namespace='test_ns')
+ self.vif_driver.init_l3.assert_called_once_with('test_interface',
+ ['10.0.0.2/24'],
+ namespace=
+ 'test_ns')
+
+ dev_exists.return_value = True
+ self.assertRaises(exceptions.PreexistingDeviceFailure,
+ self.driver._plug, 'test_ns', test_port, False)
+
+ def test_unplug(self):
+ self.vif_driver.get_device_name.return_value = 'test_interface'
+
+ self.driver._unplug('test_ns', 'port_id')
+ self.vip_plug_callback.assert_called_once_with('unplug',
+ {'id': 'port_id'})
+ self.vif_driver.unplug('test_interface', namespace='test_ns')
+
+ def test_kill_pids_in_file(self):
+ with contextlib.nested(
+ mock.patch('os.path.exists'),
+ mock.patch('__builtin__.open')
+ ) as (path_exists, mock_open):
+ file_mock = mock.MagicMock()
+ mock_open.return_value = file_mock
+ file_mock.__enter__.return_value = file_mock
+ file_mock.__iter__.return_value = iter(['123'])
+ ns_wrapper = mock.Mock()
+
+ path_exists.return_value = False
+ namespace_driver.kill_pids_in_file(ns_wrapper, 'test_path')
+ path_exists.assert_called_once_with('test_path')
+ self.assertFalse(mock_open.called)
+
+ path_exists.return_value = True
+ ns_wrapper.netns.execute.side_effect = RuntimeError
+ namespace_driver.kill_pids_in_file(ns_wrapper, 'test_path')
+ ns_wrapper.netns.execute.assert_called_once_with(['kill', '-9',
+ '123'])
+
+ def test_get_state_file_path(self):
+ with mock.patch('os.makedirs') as mkdir:
+ path = self.driver._get_state_file_path('pool_id', 'conf')
+ self.assertEqual('/the/path/pool_id/conf', path)
+ mkdir.assert_called_once_with('/the/path/pool_id', 0755)