def test_reload_allocations(self): exp_host_name = '/dhcp/cccccccc-cccc-cccc-cccc-cccccccccccc/host' exp_host_data = """ 00:00:80:aa:bb:cc,192-168-0-2.openstacklocal,192.168.0.2 00:00:f3:aa:bb:cc,fdca-3ba5-a17a-4ba3--2.openstacklocal,fdca:3ba5:a17a:4ba3::2 00:00:0f:aa:bb:cc,192-168-0-3.openstacklocal,192.168.0.3 00:00:0f:aa:bb:cc,fdca-3ba5-a17a-4ba3--3.openstacklocal,fdca:3ba5:a17a:4ba3::3 """.lstrip() exp_opt_name = '/dhcp/cccccccc-cccc-cccc-cccc-cccccccccccc/opts' exp_opt_data = "tag:tag0,option:router,192.168.0.1" fake_v6 = 'gdca:3ba5:a17a:4ba3::1' fake_v6_cidr = 'gdca:3ba5:a17a:4ba3::/64' exp_opt_data = """ tag:tag0,option:dns-server,8.8.8.8 tag:tag0,option:classless-static-route,20.0.0.1/24,20.0.0.1 tag:tag0,option:router,192.168.0.1 tag:tag1,option:dns-server,%s tag:tag1,option:classless-static-route,%s,%s""".lstrip() % (fake_v6, fake_v6_cidr, fake_v6) exp_args = ['ip', 'netns', 'exec', 'qdhcp-ns', 'kill', '-HUP', 5] with mock.patch('os.path.isdir') as isdir: isdir.return_value = True with mock.patch.object(dhcp.Dnsmasq, 'pid') as pid: pid.__get__ = mock.Mock(return_value=5) dm = dhcp.Dnsmasq(self.conf, FakeDualNetwork(), namespace='qdhcp-ns') dm.reload_allocations() self.safe.assert_has_calls([mock.call(exp_host_name, exp_host_data), mock.call(exp_opt_name, exp_opt_data)]) self.execute.assert_called_once_with(exp_args, root_helper='sudo')
def test_output_opts_file_no_gateway(self): expected = "tag:tag0,option:router" with mock.patch.object(dhcp.Dnsmasq, 'get_conf_file_name') as conf_fn: conf_fn.return_value = '/foo/opts' dm = dhcp.Dnsmasq(self.conf, FakeV4NoGatewayNetwork()) dm._output_opts_file() self.safe.assert_called_once_with('/foo/opts', expected)
def test_output_opts_file_single_dhcp(self): expected = """ tag:tag0,option:dns-server,8.8.8.8 tag:tag0,option:classless-static-route,20.0.0.1/24,20.0.0.1 tag:tag0,option:router,192.168.0.1""".lstrip() with mock.patch.object(dhcp.Dnsmasq, 'get_conf_file_name') as conf_fn: conf_fn.return_value = '/foo/opts' dm = dhcp.Dnsmasq(self.conf, FakeDualNetworkSingleDHCP()) dm._output_opts_file() self.safe.assert_called_once_with('/foo/opts', expected)
def _test_spawn(self, extra_options): def mock_get_conf_file_name(kind, ensure_conf_dir=False): return '/dhcp/cccccccc-cccc-cccc-cccc-cccccccccccc/%s' % kind def fake_argv(index): if index == 0: return '/usr/local/bin/quantum-dhcp-agent' else: raise IndexError expected = [ 'QUANTUM_RELAY_SOCKET_PATH=/dhcp/lease_relay', 'QUANTUM_NETWORK_ID=cccccccc-cccc-cccc-cccc-cccccccccccc', 'ip', 'netns', 'exec', 'qdhcp-ns', 'dnsmasq', '--no-hosts', '--no-resolv', '--strict-order', '--bind-interfaces', '--interface=tap0', '--except-interface=lo', '--pid-file=/dhcp/cccccccc-cccc-cccc-cccc-cccccccccccc/pid', '--dhcp-hostsfile=/dhcp/cccccccc-cccc-cccc-cccc-cccccccccccc/host', '--dhcp-optsfile=/dhcp/cccccccc-cccc-cccc-cccc-cccccccccccc/opts', ('--dhcp-script=/usr/local/bin/quantum-dhcp-agent-' 'dnsmasq-lease-update'), '--leasefile-ro', '--dhcp-range=set:tag0,192.168.0.0,static,120s', '--dhcp-range=set:tag1,fdca:3ba5:a17a:4ba3::,static,120s' ] expected.extend(extra_options) self.execute.return_value = ('', '') delegate = mock.Mock() delegate.get_interface_name.return_value = 'tap0' attrs_to_mock = dict([ (a, mock.DEFAULT) for a in ['_output_opts_file', 'get_conf_file_name', 'interface_name'] ]) with mock.patch.multiple(dhcp.Dnsmasq, **attrs_to_mock) as mocks: mocks['get_conf_file_name'].side_effect = mock_get_conf_file_name mocks['_output_opts_file'].return_value = ( '/dhcp/cccccccc-cccc-cccc-cccc-cccccccccccc/opts') mocks['interface_name'].__get__ = mock.Mock(return_value='tap0') with mock.patch.object(dhcp.sys, 'argv') as argv: argv.__getitem__.side_effect = fake_argv dm = dhcp.Dnsmasq(self.conf, FakeDualNetwork(), device_delegate=delegate, namespace='qdhcp-ns', version=float(2.59)) dm.spawn_process() self.assertTrue(mocks['_output_opts_file'].called) self.execute.assert_called_once_with(expected, root_helper='sudo', check_exit_code=True)
def test_make_subnet_interface_ip_map(self): with mock.patch('quantum.agent.linux.ip_lib.IPDevice') as ip_dev: ip_dev.return_value.addr.list.return_value = [{ 'cidr': '192.168.0.1/24' }] dm = dhcp.Dnsmasq(self.conf, FakeDualNetwork(), namespace='qdhcp-ns') self.assertEqual(dm._make_subnet_interface_ip_map(), {FakeV4Subnet.id: '192.168.0.1'})
def test_output_opts_file_no_gateway(self): expected = """ tag:tag0,option:classless-static-route,169.254.169.254/32,192.168.1.1 tag:tag0,option:router""".lstrip() with mock.patch.object(dhcp.Dnsmasq, 'get_conf_file_name') as conf_fn: conf_fn.return_value = '/foo/opts' dm = dhcp.Dnsmasq(self.conf, FakeV4NoGatewayNetwork(), version=float(2.59)) with mock.patch.object(dm, '_make_subnet_interface_ip_map') as ipm: ipm.return_value = {FakeV4SubnetNoGateway.id: '192.168.1.1'} dm._output_opts_file() self.assertTrue(ipm.called) self.safe.assert_called_once_with('/foo/opts', expected)
def test_output_opts_file(self): fake_v6 = 'gdca:3ba5:a17a:4ba3::1' fake_v6_cidr = 'gdca:3ba5:a17a:4ba3::/64' expected = """ tag:tag0,option:dns-server,8.8.8.8 tag:tag0,option:classless-static-route,20.0.0.1/24,20.0.0.1 tag:tag0,option:router,192.168.0.1 tag:tag1,option:dns-server,%s tag:tag1,option:classless-static-route,%s,%s""".lstrip() % (fake_v6, fake_v6_cidr, fake_v6) with mock.patch.object(dhcp.Dnsmasq, 'get_conf_file_name') as conf_fn: conf_fn.return_value = '/foo/opts' dm = dhcp.Dnsmasq(self.conf, FakeDualNetwork()) dm._output_opts_file() self.safe.assert_called_once_with('/foo/opts', expected)
def test_reload_allocations_stale_pid(self): exp_host_name = '/dhcp/cccccccc-cccc-cccc-cccc-cccccccccccc/host' exp_host_data = """ 00:00:80:aa:bb:cc,192-168-0-2.openstacklocal,192.168.0.2 00:00:f3:aa:bb:cc,fdca-3ba5-a17a-4ba3--2.openstacklocal,fdca:3ba5:a17a:4ba3::2 00:00:0f:aa:bb:cc,192-168-0-3.openstacklocal,192.168.0.3 00:00:0f:aa:bb:cc,fdca-3ba5-a17a-4ba3--3.openstacklocal,fdca:3ba5:a17a:4ba3::3 """.lstrip() exp_opt_name = '/dhcp/cccccccc-cccc-cccc-cccc-cccccccccccc/opts' exp_opt_data = "tag:tag0,option:router,192.168.0.1" fake_v6 = 'gdca:3ba5:a17a:4ba3::1' fake_v6_cidr = 'gdca:3ba5:a17a:4ba3::/64' exp_opt_data = """ tag:tag0,option:dns-server,8.8.8.8 tag:tag0,option:classless-static-route,20.0.0.1/24,20.0.0.1 tag:tag0,option:router,192.168.0.1 tag:tag1,option:dns-server,%s tag:tag1,option:classless-static-route,%s,%s""".lstrip() % ( fake_v6, fake_v6_cidr, fake_v6) exp_args = ['cat', '/proc/5/cmdline'] with mock.patch('os.path.isdir') as isdir: isdir.return_value = True with mock.patch.object(dhcp.Dnsmasq, 'pid') as pid: pid.__get__ = mock.Mock(return_value=5) dm = dhcp.Dnsmasq(self.conf, FakeDualNetwork(), namespace='qdhcp-ns', version=float(2.59)) method_name = '_make_subnet_interface_ip_map' with mock.patch.object(dhcp.Dnsmasq, method_name) as ip_map: ip_map.return_value = {} dm.reload_allocations() self.assertTrue(ip_map.called) self.safe.assert_has_calls([ mock.call(exp_host_name, exp_host_data), mock.call(exp_opt_name, exp_opt_data) ]) self.execute.assert_called_once_with(exp_args, 'sudo')