Merge "Dynamically adjust max number of leases"
This commit is contained in:
commit
bff364fdbf
@ -62,6 +62,9 @@
|
|||||||
# Use another DNS server before any in /etc/resolv.conf.
|
# Use another DNS server before any in /etc/resolv.conf.
|
||||||
# dnsmasq_dns_server =
|
# dnsmasq_dns_server =
|
||||||
|
|
||||||
|
# Limit number of leases to prevent a denial-of-service.
|
||||||
|
# dnsmasq_lease_max = 16777216
|
||||||
|
|
||||||
# Location to DHCP lease relay UNIX domain socket
|
# Location to DHCP lease relay UNIX domain socket
|
||||||
# dhcp_lease_relay_socket = $state_path/dhcp/lease_relay
|
# dhcp_lease_relay_socket = $state_path/dhcp/lease_relay
|
||||||
|
|
||||||
|
@ -50,6 +50,10 @@ OPTS = [
|
|||||||
cfg.StrOpt('dnsmasq_dns_server',
|
cfg.StrOpt('dnsmasq_dns_server',
|
||||||
help=_('Use another DNS server before any in '
|
help=_('Use another DNS server before any in '
|
||||||
'/etc/resolv.conf.')),
|
'/etc/resolv.conf.')),
|
||||||
|
cfg.IntOpt(
|
||||||
|
'dnsmasq_lease_max',
|
||||||
|
default=(2 ** 24),
|
||||||
|
help=_('Limit number of leases to prevent a denial-of-service.')),
|
||||||
cfg.StrOpt('interface_driver',
|
cfg.StrOpt('interface_driver',
|
||||||
help=_("The driver used to manage the virtual interface.")),
|
help=_("The driver used to manage the virtual interface.")),
|
||||||
]
|
]
|
||||||
@ -309,13 +313,12 @@ class Dnsmasq(DhcpLocalProcess):
|
|||||||
'--except-interface=lo',
|
'--except-interface=lo',
|
||||||
'--pid-file=%s' % self.get_conf_file_name(
|
'--pid-file=%s' % self.get_conf_file_name(
|
||||||
'pid', ensure_conf_dir=True),
|
'pid', ensure_conf_dir=True),
|
||||||
#TODO (mark): calculate value from cidr (defaults to 150)
|
|
||||||
#'--dhcp-lease-max=%s' % ?,
|
|
||||||
'--dhcp-hostsfile=%s' % self._output_hosts_file(),
|
'--dhcp-hostsfile=%s' % self._output_hosts_file(),
|
||||||
'--dhcp-optsfile=%s' % self._output_opts_file(),
|
'--dhcp-optsfile=%s' % self._output_opts_file(),
|
||||||
'--leasefile-ro',
|
'--leasefile-ro',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
possible_leases = 0
|
||||||
for i, subnet in enumerate(self.network.subnets):
|
for i, subnet in enumerate(self.network.subnets):
|
||||||
# if a subnet is specified to have dhcp disabled
|
# if a subnet is specified to have dhcp disabled
|
||||||
if not subnet.enable_dhcp:
|
if not subnet.enable_dhcp:
|
||||||
@ -330,11 +333,20 @@ class Dnsmasq(DhcpLocalProcess):
|
|||||||
set_tag = 'set:'
|
set_tag = 'set:'
|
||||||
else:
|
else:
|
||||||
set_tag = ''
|
set_tag = ''
|
||||||
|
|
||||||
|
cidr = netaddr.IPNetwork(subnet.cidr)
|
||||||
|
|
||||||
cmd.append('--dhcp-range=%s%s,%s,%s,%ss' %
|
cmd.append('--dhcp-range=%s%s,%s,%s,%ss' %
|
||||||
(set_tag, self._TAG_PREFIX % i,
|
(set_tag, self._TAG_PREFIX % i,
|
||||||
netaddr.IPNetwork(subnet.cidr).network,
|
cidr.network,
|
||||||
mode,
|
mode,
|
||||||
self.conf.dhcp_lease_duration))
|
self.conf.dhcp_lease_duration))
|
||||||
|
possible_leases += cidr.size
|
||||||
|
|
||||||
|
# Cap the limit because creating lots of subnets can inflate
|
||||||
|
# this possible lease cap.
|
||||||
|
cmd.append('--dhcp-lease-max=%d' %
|
||||||
|
min(possible_leases, self.conf.dnsmasq_lease_max))
|
||||||
|
|
||||||
cmd.append('--conf-file=%s' % self.conf.dnsmasq_config_file)
|
cmd.append('--conf-file=%s' % self.conf.dnsmasq_config_file)
|
||||||
if self.conf.dnsmasq_dns_server:
|
if self.conf.dnsmasq_dns_server:
|
||||||
|
@ -142,12 +142,14 @@ class FakeV4Network:
|
|||||||
id = 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa'
|
id = 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa'
|
||||||
subnets = [FakeV4Subnet()]
|
subnets = [FakeV4Subnet()]
|
||||||
ports = [FakePort1()]
|
ports = [FakePort1()]
|
||||||
|
namespace = 'qdhcp-ns'
|
||||||
|
|
||||||
|
|
||||||
class FakeV6Network:
|
class FakeV6Network:
|
||||||
id = 'bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb'
|
id = 'bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb'
|
||||||
subnets = [FakeV6Subnet()]
|
subnets = [FakeV6Subnet()]
|
||||||
ports = [FakePort2()]
|
ports = [FakePort2()]
|
||||||
|
namespace = 'qdhcp-ns'
|
||||||
|
|
||||||
|
|
||||||
class FakeDualNetwork:
|
class FakeDualNetwork:
|
||||||
@ -534,9 +536,10 @@ class TestDhcpLocalProcess(TestBase):
|
|||||||
|
|
||||||
|
|
||||||
class TestDnsmasq(TestBase):
|
class TestDnsmasq(TestBase):
|
||||||
def _test_spawn(self, extra_options):
|
def _test_spawn(self, extra_options, network=FakeDualNetwork(),
|
||||||
|
max_leases=16777216):
|
||||||
def mock_get_conf_file_name(kind, ensure_conf_dir=False):
|
def mock_get_conf_file_name(kind, ensure_conf_dir=False):
|
||||||
return '/dhcp/cccccccc-cccc-cccc-cccc-cccccccccccc/%s' % kind
|
return '/dhcp/%s/%s' % (network.id, kind)
|
||||||
|
|
||||||
def fake_argv(index):
|
def fake_argv(index):
|
||||||
if index == 0:
|
if index == 0:
|
||||||
@ -550,7 +553,7 @@ class TestDnsmasq(TestBase):
|
|||||||
'exec',
|
'exec',
|
||||||
'qdhcp-ns',
|
'qdhcp-ns',
|
||||||
'env',
|
'env',
|
||||||
'NEUTRON_NETWORK_ID=cccccccc-cccc-cccc-cccc-cccccccccccc',
|
'NEUTRON_NETWORK_ID=%s' % network.id,
|
||||||
'dnsmasq',
|
'dnsmasq',
|
||||||
'--no-hosts',
|
'--no-hosts',
|
||||||
'--no-resolv',
|
'--no-resolv',
|
||||||
@ -558,12 +561,17 @@ class TestDnsmasq(TestBase):
|
|||||||
'--bind-interfaces',
|
'--bind-interfaces',
|
||||||
'--interface=tap0',
|
'--interface=tap0',
|
||||||
'--except-interface=lo',
|
'--except-interface=lo',
|
||||||
'--pid-file=/dhcp/cccccccc-cccc-cccc-cccc-cccccccccccc/pid',
|
'--pid-file=/dhcp/%s/pid' % network.id,
|
||||||
'--dhcp-hostsfile=/dhcp/cccccccc-cccc-cccc-cccc-cccccccccccc/host',
|
'--dhcp-hostsfile=/dhcp/%s/host' % network.id,
|
||||||
'--dhcp-optsfile=/dhcp/cccccccc-cccc-cccc-cccc-cccccccccccc/opts',
|
'--dhcp-optsfile=/dhcp/%s/opts' % network.id,
|
||||||
'--leasefile-ro',
|
'--leasefile-ro']
|
||||||
'--dhcp-range=set:tag0,192.168.0.0,static,86400s',
|
|
||||||
'--dhcp-range=set:tag1,fdca:3ba5:a17a:4ba3::,static,86400s']
|
expected.extend(
|
||||||
|
'--dhcp-range=set:tag%d,%s,static,86400s' %
|
||||||
|
(i, s.cidr.split('/')[0])
|
||||||
|
for i, s in enumerate(network.subnets)
|
||||||
|
)
|
||||||
|
expected.append('--dhcp-lease-max=%d' % max_leases)
|
||||||
expected.extend(extra_options)
|
expected.extend(extra_options)
|
||||||
|
|
||||||
self.execute.return_value = ('', '')
|
self.execute.return_value = ('', '')
|
||||||
@ -576,14 +584,13 @@ class TestDnsmasq(TestBase):
|
|||||||
with mock.patch.multiple(dhcp.Dnsmasq, **attrs_to_mock) as mocks:
|
with mock.patch.multiple(dhcp.Dnsmasq, **attrs_to_mock) as mocks:
|
||||||
mocks['get_conf_file_name'].side_effect = mock_get_conf_file_name
|
mocks['get_conf_file_name'].side_effect = mock_get_conf_file_name
|
||||||
mocks['_output_opts_file'].return_value = (
|
mocks['_output_opts_file'].return_value = (
|
||||||
'/dhcp/cccccccc-cccc-cccc-cccc-cccccccccccc/opts'
|
'/dhcp/%s/opts' % network.id
|
||||||
)
|
)
|
||||||
mocks['interface_name'].__get__ = mock.Mock(return_value='tap0')
|
mocks['interface_name'].__get__ = mock.Mock(return_value='tap0')
|
||||||
|
|
||||||
with mock.patch.object(dhcp.sys, 'argv') as argv:
|
with mock.patch.object(dhcp.sys, 'argv') as argv:
|
||||||
argv.__getitem__.side_effect = fake_argv
|
argv.__getitem__.side_effect = fake_argv
|
||||||
dm = dhcp.Dnsmasq(self.conf, FakeDualNetwork(),
|
dm = dhcp.Dnsmasq(self.conf, network, version=float(2.59))
|
||||||
version=float(2.59))
|
|
||||||
dm.spawn_process()
|
dm.spawn_process()
|
||||||
self.assertTrue(mocks['_output_opts_file'].called)
|
self.assertTrue(mocks['_output_opts_file'].called)
|
||||||
self.execute.assert_called_once_with(expected,
|
self.execute.assert_called_once_with(expected,
|
||||||
@ -607,6 +614,12 @@ class TestDnsmasq(TestBase):
|
|||||||
'--server=8.8.8.8',
|
'--server=8.8.8.8',
|
||||||
'--domain=openstacklocal'])
|
'--domain=openstacklocal'])
|
||||||
|
|
||||||
|
def test_spawn_max_leases_is_smaller_than_cap(self):
|
||||||
|
self._test_spawn(
|
||||||
|
['--conf-file=', '--domain=openstacklocal'],
|
||||||
|
network=FakeV4Network(),
|
||||||
|
max_leases=256)
|
||||||
|
|
||||||
def test_output_opts_file(self):
|
def test_output_opts_file(self):
|
||||||
fake_v6 = 'gdca:3ba5:a17a:4ba3::1'
|
fake_v6 = 'gdca:3ba5:a17a:4ba3::1'
|
||||||
fake_v6_cidr = 'gdca:3ba5:a17a:4ba3::/64'
|
fake_v6_cidr = 'gdca:3ba5:a17a:4ba3::/64'
|
||||||
|
Loading…
Reference in New Issue
Block a user