Implementation of bp per-net-dhcp-enable
Change-Id: I81c2e6adb02921e8b80f8181a730b1cba9ffa649
This commit is contained in:
parent
ecaa605e4e
commit
e5307ebaea
@ -104,12 +104,21 @@ class DhcpAgent(object):
|
|||||||
|
|
||||||
subnets = {}
|
subnets = {}
|
||||||
subnet_hashes = set()
|
subnet_hashes = set()
|
||||||
|
|
||||||
|
network_admin_up = {}
|
||||||
|
for network in self.db.networks.all():
|
||||||
|
network_admin_up[network.id] = network.admin_state_up
|
||||||
|
|
||||||
for subnet in self.db.subnets.all():
|
for subnet in self.db.subnets.all():
|
||||||
|
if (not subnet.enable_dhcp or
|
||||||
|
not network_admin_up[subnet.network_id]):
|
||||||
|
continue
|
||||||
subnet_hashes.add((hash(str(subnet)), subnet.network_id))
|
subnet_hashes.add((hash(str(subnet)), subnet.network_id))
|
||||||
subnets[subnet.id] = subnet.network_id
|
subnets[subnet.id] = subnet.network_id
|
||||||
|
|
||||||
ipalloc_hashes = set([(hash(str(a)), subnets[a.subnet_id])
|
ipalloc_hashes = set([(hash(str(a)), subnets[a.subnet_id])
|
||||||
for a in self.db.ipallocations.all()])
|
for a in self.db.ipallocations.all()
|
||||||
|
if a.subnet_id in subnets])
|
||||||
|
|
||||||
networks = set(subnets.itervalues())
|
networks = set(subnets.itervalues())
|
||||||
|
|
||||||
|
@ -90,14 +90,20 @@ class DhcpBase(object):
|
|||||||
class DhcpLocalProcess(DhcpBase):
|
class DhcpLocalProcess(DhcpBase):
|
||||||
PORTS = []
|
PORTS = []
|
||||||
|
|
||||||
|
def _enable_dhcp(self):
|
||||||
|
"""check if there is a subnet within the network with dhcp enabled."""
|
||||||
|
for subnet in self.network.subnets:
|
||||||
|
if subnet.enable_dhcp:
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
def enable(self):
|
def enable(self):
|
||||||
"""Enables DHCP for this network by spawning a local process."""
|
"""Enables DHCP for this network by spawning a local process."""
|
||||||
if self.active:
|
if self.active:
|
||||||
self.reload_allocations()
|
self.reload_allocations()
|
||||||
return
|
elif self._enable_dhcp():
|
||||||
|
self.device_delegate.setup(self.network, reuse_existing=True)
|
||||||
self.device_delegate.setup(self.network, reuse_existing=True)
|
self.spawn_process()
|
||||||
self.spawn_process()
|
|
||||||
|
|
||||||
def disable(self):
|
def disable(self):
|
||||||
"""Disable DHCP for this network by killing the local process."""
|
"""Disable DHCP for this network by killing the local process."""
|
||||||
@ -193,6 +199,9 @@ class Dnsmasq(DhcpLocalProcess):
|
|||||||
]
|
]
|
||||||
|
|
||||||
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 not subnet.enable_dhcp:
|
||||||
|
continue
|
||||||
if subnet.ip_version == 4:
|
if subnet.ip_version == 4:
|
||||||
mode = 'static'
|
mode = 'static'
|
||||||
else:
|
else:
|
||||||
@ -213,6 +222,13 @@ class Dnsmasq(DhcpLocalProcess):
|
|||||||
utils.execute(cmd, self.root_helper)
|
utils.execute(cmd, self.root_helper)
|
||||||
|
|
||||||
def reload_allocations(self):
|
def reload_allocations(self):
|
||||||
|
"""If all subnets turn off dhcp, kill the process."""
|
||||||
|
if not self._enable_dhcp():
|
||||||
|
self.disable()
|
||||||
|
LOG.debug(_('Killing dhcpmasq for network since all subnets have \
|
||||||
|
turned off DHCP: %s') % self.network.id)
|
||||||
|
return
|
||||||
|
|
||||||
"""Rebuilds the dnsmasq config and signal the dnsmasq to reload."""
|
"""Rebuilds the dnsmasq config and signal the dnsmasq to reload."""
|
||||||
self._output_hosts_file()
|
self._output_hosts_file()
|
||||||
self._output_opts_file()
|
self._output_opts_file()
|
||||||
@ -240,9 +256,12 @@ class Dnsmasq(DhcpLocalProcess):
|
|||||||
# TODO (mark): add support for nameservers
|
# TODO (mark): add support for nameservers
|
||||||
options = []
|
options = []
|
||||||
for i, subnet in enumerate(self.network.subnets):
|
for i, subnet in enumerate(self.network.subnets):
|
||||||
if subnet.ip_version == 6:
|
if not subnet.enable_dhcp:
|
||||||
|
continue
|
||||||
|
elif subnet.ip_version == 6:
|
||||||
continue
|
continue
|
||||||
else:
|
else:
|
||||||
|
#NOTE(xchenum) need to handle no gw case
|
||||||
options.append((self._TAG_PREFIX % i,
|
options.append((self._TAG_PREFIX % i,
|
||||||
'option',
|
'option',
|
||||||
'router',
|
'router',
|
||||||
|
@ -228,5 +228,10 @@ RESOURCE_ATTRIBUTE_MAP = {
|
|||||||
'tenant_id': {'allow_post': True, 'allow_put': False,
|
'tenant_id': {'allow_post': True, 'allow_put': False,
|
||||||
'required_by_policy': True,
|
'required_by_policy': True,
|
||||||
'is_visible': True},
|
'is_visible': True},
|
||||||
|
'enable_dhcp': {'allow_post': True, 'allow_put': True,
|
||||||
|
'default': True,
|
||||||
|
'convert_to': convert_to_boolean,
|
||||||
|
'validate': {'type:boolean': None},
|
||||||
|
'is_visible': True},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -625,7 +625,8 @@ class QuantumDbPluginV2(quantum_plugin_base_v2.QuantumPluginBaseV2):
|
|||||||
'allocation_pools': [{'start': pool['first_ip'],
|
'allocation_pools': [{'start': pool['first_ip'],
|
||||||
'end': pool['last_ip']}
|
'end': pool['last_ip']}
|
||||||
for pool in subnet['allocation_pools']],
|
for pool in subnet['allocation_pools']],
|
||||||
'gateway_ip': subnet['gateway_ip']}
|
'gateway_ip': subnet['gateway_ip'],
|
||||||
|
'enable_dhcp': subnet['enable_dhcp']}
|
||||||
return self._fields(res, fields)
|
return self._fields(res, fields)
|
||||||
|
|
||||||
def _make_port_dict(self, port, fields=None):
|
def _make_port_dict(self, port, fields=None):
|
||||||
@ -702,7 +703,8 @@ class QuantumDbPluginV2(quantum_plugin_base_v2.QuantumPluginBaseV2):
|
|||||||
network_id=s['network_id'],
|
network_id=s['network_id'],
|
||||||
ip_version=s['ip_version'],
|
ip_version=s['ip_version'],
|
||||||
cidr=s['cidr'],
|
cidr=s['cidr'],
|
||||||
gateway_ip=s['gateway_ip'])
|
gateway_ip=s['gateway_ip'],
|
||||||
|
enable_dhcp=s['enable_dhcp'])
|
||||||
context.session.add(subnet)
|
context.session.add(subnet)
|
||||||
pools = self._allocate_pools_for_subnet(context, s)
|
pools = self._allocate_pools_for_subnet(context, s)
|
||||||
for pool in pools:
|
for pool in pools:
|
||||||
|
@ -112,6 +112,8 @@ class Subnet(model_base.BASEV2, HasId, HasTenant):
|
|||||||
allocation_pools = orm.relationship(IPAllocationPool,
|
allocation_pools = orm.relationship(IPAllocationPool,
|
||||||
backref='subnet',
|
backref='subnet',
|
||||||
lazy="dynamic")
|
lazy="dynamic")
|
||||||
|
enable_dhcp = sa.Column(sa.Boolean())
|
||||||
|
|
||||||
#TODO(danwent):
|
#TODO(danwent):
|
||||||
# - dns_namservers
|
# - dns_namservers
|
||||||
# - additional_routes
|
# - additional_routes
|
||||||
|
@ -752,7 +752,7 @@ class V2Views(unittest.TestCase):
|
|||||||
|
|
||||||
def test_subnet(self):
|
def test_subnet(self):
|
||||||
keys = ('id', 'network_id', 'tenant_id', 'gateway_ip',
|
keys = ('id', 'network_id', 'tenant_id', 'gateway_ip',
|
||||||
'ip_version', 'cidr')
|
'ip_version', 'cidr', 'enable_dhcp')
|
||||||
self._view(keys, 'subnets', 'subnet')
|
self._view(keys, 'subnets', 'subnet')
|
||||||
|
|
||||||
|
|
||||||
|
@ -137,12 +137,13 @@ class QuantumDbPluginV2TestCase(unittest2.TestCase):
|
|||||||
return network_req.get_response(self.api)
|
return network_req.get_response(self.api)
|
||||||
|
|
||||||
def _create_subnet(self, fmt, tenant_id, net_id, gateway_ip, cidr,
|
def _create_subnet(self, fmt, tenant_id, net_id, gateway_ip, cidr,
|
||||||
allocation_pools=None, ip_version=4):
|
allocation_pools=None, ip_version=4, enable_dhcp=True):
|
||||||
data = {'subnet': {'tenant_id': tenant_id,
|
data = {'subnet': {'tenant_id': tenant_id,
|
||||||
'network_id': net_id,
|
'network_id': net_id,
|
||||||
'cidr': cidr,
|
'cidr': cidr,
|
||||||
'ip_version': ip_version,
|
'ip_version': ip_version,
|
||||||
'tenant_id': self._tenant_id}}
|
'tenant_id': self._tenant_id,
|
||||||
|
'enable_dhcp': enable_dhcp}}
|
||||||
if gateway_ip:
|
if gateway_ip:
|
||||||
data['subnet']['gateway_ip'] = gateway_ip
|
data['subnet']['gateway_ip'] = gateway_ip
|
||||||
if allocation_pools:
|
if allocation_pools:
|
||||||
@ -165,14 +166,15 @@ class QuantumDbPluginV2TestCase(unittest2.TestCase):
|
|||||||
return port_req.get_response(self.api)
|
return port_req.get_response(self.api)
|
||||||
|
|
||||||
def _make_subnet(self, fmt, network, gateway, cidr,
|
def _make_subnet(self, fmt, network, gateway, cidr,
|
||||||
allocation_pools=None, ip_version=4):
|
allocation_pools=None, ip_version=4, enable_dhcp=True):
|
||||||
res = self._create_subnet(fmt,
|
res = self._create_subnet(fmt,
|
||||||
network['network']['tenant_id'],
|
network['network']['tenant_id'],
|
||||||
network['network']['id'],
|
network['network']['id'],
|
||||||
gateway,
|
gateway,
|
||||||
cidr,
|
cidr,
|
||||||
allocation_pools=allocation_pools,
|
allocation_pools=allocation_pools,
|
||||||
ip_version=ip_version)
|
ip_version=ip_version,
|
||||||
|
enable_dhcp=enable_dhcp)
|
||||||
# Things can go wrong - raise HTTP exc with res code only
|
# Things can go wrong - raise HTTP exc with res code only
|
||||||
# so it can be caught by unit tests
|
# so it can be caught by unit tests
|
||||||
if res.status_int >= 400:
|
if res.status_int >= 400:
|
||||||
@ -200,7 +202,8 @@ class QuantumDbPluginV2TestCase(unittest2.TestCase):
|
|||||||
cidr='10.0.0.0/24',
|
cidr='10.0.0.0/24',
|
||||||
fmt='json',
|
fmt='json',
|
||||||
ip_version=4,
|
ip_version=4,
|
||||||
allocation_pools=None):
|
allocation_pools=None,
|
||||||
|
enable_dhcp=True):
|
||||||
# TODO(anyone) DRY this
|
# TODO(anyone) DRY this
|
||||||
# NOTE(salvatore-orlando): we can pass the network object
|
# NOTE(salvatore-orlando): we can pass the network object
|
||||||
# to gen function anyway, and then avoid the repetition
|
# to gen function anyway, and then avoid the repetition
|
||||||
@ -211,7 +214,8 @@ class QuantumDbPluginV2TestCase(unittest2.TestCase):
|
|||||||
gateway_ip,
|
gateway_ip,
|
||||||
cidr,
|
cidr,
|
||||||
allocation_pools,
|
allocation_pools,
|
||||||
ip_version)
|
ip_version,
|
||||||
|
enable_dhcp)
|
||||||
yield subnet
|
yield subnet
|
||||||
self._delete('subnets', subnet['subnet']['id'])
|
self._delete('subnets', subnet['subnet']['id'])
|
||||||
else:
|
else:
|
||||||
@ -220,7 +224,8 @@ class QuantumDbPluginV2TestCase(unittest2.TestCase):
|
|||||||
gateway_ip,
|
gateway_ip,
|
||||||
cidr,
|
cidr,
|
||||||
allocation_pools,
|
allocation_pools,
|
||||||
ip_version)
|
ip_version,
|
||||||
|
enable_dhcp)
|
||||||
yield subnet
|
yield subnet
|
||||||
self._delete('subnets', subnet['subnet']['id'])
|
self._delete('subnets', subnet['subnet']['id'])
|
||||||
|
|
||||||
@ -876,6 +881,7 @@ class TestSubnetsV2(QuantumDbPluginV2TestCase):
|
|||||||
keys = kwargs.copy()
|
keys = kwargs.copy()
|
||||||
keys.setdefault('cidr', '10.0.0.0/24')
|
keys.setdefault('cidr', '10.0.0.0/24')
|
||||||
keys.setdefault('ip_version', 4)
|
keys.setdefault('ip_version', 4)
|
||||||
|
keys.setdefault('enable_dhcp', True)
|
||||||
with self.subnet(network=network, **keys) as subnet:
|
with self.subnet(network=network, **keys) as subnet:
|
||||||
# verify the response has each key with the correct value
|
# verify the response has each key with the correct value
|
||||||
for k in keys:
|
for k in keys:
|
||||||
@ -974,10 +980,12 @@ class TestSubnetsV2(QuantumDbPluginV2TestCase):
|
|||||||
cidr = '10.0.0.0/24'
|
cidr = '10.0.0.0/24'
|
||||||
allocation_pools = [{'start': '10.0.0.2',
|
allocation_pools = [{'start': '10.0.0.2',
|
||||||
'end': '10.0.0.254'}]
|
'end': '10.0.0.254'}]
|
||||||
|
enable_dhcp = True
|
||||||
subnet = self._test_create_subnet()
|
subnet = self._test_create_subnet()
|
||||||
# verify cidr & gw have been correctly generated
|
# verify cidr & gw have been correctly generated
|
||||||
self.assertEquals(subnet['subnet']['cidr'], cidr)
|
self.assertEquals(subnet['subnet']['cidr'], cidr)
|
||||||
self.assertEquals(subnet['subnet']['gateway_ip'], gateway)
|
self.assertEquals(subnet['subnet']['gateway_ip'], gateway)
|
||||||
|
self.assertEquals(subnet['subnet']['enable_dhcp'], enable_dhcp)
|
||||||
self.assertEquals(subnet['subnet']['allocation_pools'],
|
self.assertEquals(subnet['subnet']['allocation_pools'],
|
||||||
allocation_pools)
|
allocation_pools)
|
||||||
|
|
||||||
@ -1021,6 +1029,10 @@ class TestSubnetsV2(QuantumDbPluginV2TestCase):
|
|||||||
cidr=cidr,
|
cidr=cidr,
|
||||||
allocation_pools=allocation_pools)
|
allocation_pools=allocation_pools)
|
||||||
|
|
||||||
|
def test_create_subnet_with_dhcp_disabled(self):
|
||||||
|
enable_dhcp = False
|
||||||
|
self._test_create_subnet(enable_dhcp=enable_dhcp)
|
||||||
|
|
||||||
def test_create_subnet_gateway_in_allocation_pool_returns_409(self):
|
def test_create_subnet_gateway_in_allocation_pool_returns_409(self):
|
||||||
gateway_ip = '10.0.0.50'
|
gateway_ip = '10.0.0.50'
|
||||||
cidr = '10.0.0.0/24'
|
cidr = '10.0.0.0/24'
|
||||||
|
@ -70,6 +70,7 @@ class TestDhcpAgent(unittest.TestCase):
|
|||||||
self.dhcp.daemon_loop()
|
self.dhcp.daemon_loop()
|
||||||
|
|
||||||
def test_daemon_loop_completes_single_pass(self):
|
def test_daemon_loop_completes_single_pass(self):
|
||||||
|
self.dhcp._network_dhcp_enable = mock.Mock(return_value=True)
|
||||||
with mock.patch.object(self.dhcp, 'get_network_state_delta') as state:
|
with mock.patch.object(self.dhcp, 'get_network_state_delta') as state:
|
||||||
with mock.patch.object(self.dhcp, 'call_driver') as call_driver:
|
with mock.patch.object(self.dhcp, 'call_driver') as call_driver:
|
||||||
with mock.patch('quantum.agent.dhcp_agent.time') as time:
|
with mock.patch('quantum.agent.dhcp_agent.time') as time:
|
||||||
@ -84,18 +85,75 @@ class TestDhcpAgent(unittest.TestCase):
|
|||||||
mock.call('reload_allocations', 'updated_net'),
|
mock.call('reload_allocations', 'updated_net'),
|
||||||
mock.call('disable', 'deleted_net')])
|
mock.call('disable', 'deleted_net')])
|
||||||
|
|
||||||
def test_state_builder(self):
|
def test_state_builder_network_admin_down(self):
|
||||||
fake_subnet = [
|
fake_network1 = FakeModel(1, admin_state_up=True)
|
||||||
FakeModel(1, network_id=1),
|
fake_network2 = FakeModel(2, admin_state_up=False)
|
||||||
FakeModel(2, network_id=2),
|
|
||||||
]
|
fake_subnet1 = FakeModel(1, network_id=1, enable_dhcp=True)
|
||||||
|
fake_subnet2 = FakeModel(2, network_id=2, enable_dhcp=True)
|
||||||
|
fake_subnet3 = FakeModel(3, network_id=2, enable_dhcp=True)
|
||||||
|
|
||||||
|
fake_network1.subnets = [fake_subnet1]
|
||||||
|
fake_network2.subnets = [fake_subnet2, fake_subnet3]
|
||||||
|
|
||||||
|
fake_subnet1.network = fake_network1
|
||||||
|
fake_subnet2.network = fake_network2
|
||||||
|
fake_subnet3.network = fake_network2
|
||||||
|
|
||||||
fake_allocation = [
|
fake_allocation = [
|
||||||
FakeModel(2, subnet_id=1)
|
FakeModel(2, subnet_id=1),
|
||||||
|
FakeModel(3, subnet_id=2)
|
||||||
]
|
]
|
||||||
|
|
||||||
|
fake_subnets = [fake_subnet1, fake_subnet2, fake_subnet3]
|
||||||
|
fake_networks = [fake_network1, fake_network2]
|
||||||
|
|
||||||
db = mock.Mock()
|
db = mock.Mock()
|
||||||
db.subnets.all = mock.Mock(return_value=fake_subnet)
|
db.subnets.all = mock.Mock(return_value=fake_subnets)
|
||||||
|
db.networks.all = mock.Mock(return_value=fake_networks)
|
||||||
|
db.ipallocations.all = mock.Mock(return_value=fake_allocation)
|
||||||
|
self.dhcp.db = db
|
||||||
|
state = self.dhcp._state_builder()
|
||||||
|
|
||||||
|
self.assertEquals(state.networks, set([1]))
|
||||||
|
|
||||||
|
expected_subnets = set([
|
||||||
|
(hash(str(fake_subnets[0])), 1),
|
||||||
|
])
|
||||||
|
self.assertEquals(state.subnet_hashes, expected_subnets)
|
||||||
|
|
||||||
|
expected_ipalloc = set([
|
||||||
|
(hash(str(fake_allocation[0])), 1),
|
||||||
|
])
|
||||||
|
self.assertEquals(state.ipalloc_hashes, expected_ipalloc)
|
||||||
|
|
||||||
|
def test_state_builder_network_dhcp_partial_disable(self):
|
||||||
|
fake_network1 = FakeModel(1, admin_state_up=True)
|
||||||
|
fake_network2 = FakeModel(2, admin_state_up=True)
|
||||||
|
|
||||||
|
fake_subnet1 = FakeModel(1, network_id=1, enable_dhcp=True)
|
||||||
|
fake_subnet2 = FakeModel(2, network_id=2, enable_dhcp=False)
|
||||||
|
fake_subnet3 = FakeModel(3, network_id=2, enable_dhcp=True)
|
||||||
|
|
||||||
|
fake_network1.subnets = [fake_subnet1]
|
||||||
|
fake_network2.subnets = [fake_subnet2, fake_subnet3]
|
||||||
|
|
||||||
|
fake_subnet1.network = fake_network1
|
||||||
|
fake_subnet2.network = fake_network2
|
||||||
|
fake_subnet3.network = fake_network2
|
||||||
|
|
||||||
|
fake_allocation = [
|
||||||
|
FakeModel(2, subnet_id=1),
|
||||||
|
FakeModel(3, subnet_id=2),
|
||||||
|
FakeModel(4, subnet_id=3),
|
||||||
|
]
|
||||||
|
|
||||||
|
fake_subnets = [fake_subnet1, fake_subnet2, fake_subnet3]
|
||||||
|
fake_networks = [fake_network1, fake_network2]
|
||||||
|
|
||||||
|
db = mock.Mock()
|
||||||
|
db.subnets.all = mock.Mock(return_value=fake_subnets)
|
||||||
|
db.networks.all = mock.Mock(return_value=fake_networks)
|
||||||
db.ipallocations.all = mock.Mock(return_value=fake_allocation)
|
db.ipallocations.all = mock.Mock(return_value=fake_allocation)
|
||||||
self.dhcp.db = db
|
self.dhcp.db = db
|
||||||
state = self.dhcp._state_builder()
|
state = self.dhcp._state_builder()
|
||||||
@ -103,8 +161,95 @@ class TestDhcpAgent(unittest.TestCase):
|
|||||||
self.assertEquals(state.networks, set([1, 2]))
|
self.assertEquals(state.networks, set([1, 2]))
|
||||||
|
|
||||||
expected_subnets = set([
|
expected_subnets = set([
|
||||||
(hash(str(fake_subnet[0])), 1),
|
(hash(str(fake_subnets[0])), 1),
|
||||||
(hash(str(fake_subnet[1])), 2)
|
(hash(str(fake_subnets[2])), 2),
|
||||||
|
])
|
||||||
|
self.assertEquals(state.subnet_hashes, expected_subnets)
|
||||||
|
|
||||||
|
expected_ipalloc = set([
|
||||||
|
(hash(str(fake_allocation[0])), 1),
|
||||||
|
(hash(str(fake_allocation[2])), 2),
|
||||||
|
])
|
||||||
|
self.assertEquals(state.ipalloc_hashes, expected_ipalloc)
|
||||||
|
|
||||||
|
def test_state_builder_network_dhcp_all_disable(self):
|
||||||
|
fake_network1 = FakeModel(1, admin_state_up=True)
|
||||||
|
fake_network2 = FakeModel(2, admin_state_up=True)
|
||||||
|
|
||||||
|
fake_subnet1 = FakeModel(1, network_id=1, enable_dhcp=True)
|
||||||
|
fake_subnet2 = FakeModel(2, network_id=2, enable_dhcp=False)
|
||||||
|
fake_subnet3 = FakeModel(3, network_id=2, enable_dhcp=False)
|
||||||
|
|
||||||
|
fake_network1.subnets = [fake_subnet1]
|
||||||
|
fake_network2.subnets = [fake_subnet2, fake_subnet3]
|
||||||
|
|
||||||
|
fake_subnet1.network = fake_network1
|
||||||
|
fake_subnet2.network = fake_network2
|
||||||
|
fake_subnet3.network = fake_network2
|
||||||
|
|
||||||
|
fake_allocation = [
|
||||||
|
FakeModel(2, subnet_id=1),
|
||||||
|
FakeModel(3, subnet_id=2),
|
||||||
|
FakeModel(4, subnet_id=3),
|
||||||
|
]
|
||||||
|
|
||||||
|
fake_subnets = [fake_subnet1, fake_subnet2, fake_subnet3]
|
||||||
|
fake_networks = [fake_network1, fake_network2]
|
||||||
|
|
||||||
|
db = mock.Mock()
|
||||||
|
db.subnets.all = mock.Mock(return_value=fake_subnets)
|
||||||
|
db.networks.all = mock.Mock(return_value=fake_networks)
|
||||||
|
db.ipallocations.all = mock.Mock(return_value=fake_allocation)
|
||||||
|
self.dhcp.db = db
|
||||||
|
state = self.dhcp._state_builder()
|
||||||
|
|
||||||
|
self.assertEquals(state.networks, set([1]))
|
||||||
|
|
||||||
|
expected_subnets = set([
|
||||||
|
(hash(str(fake_subnets[0])), 1)
|
||||||
|
])
|
||||||
|
self.assertEquals(state.subnet_hashes, expected_subnets)
|
||||||
|
|
||||||
|
expected_ipalloc = set([
|
||||||
|
(hash(str(fake_allocation[0])), 1)
|
||||||
|
])
|
||||||
|
self.assertEquals(state.ipalloc_hashes, expected_ipalloc)
|
||||||
|
|
||||||
|
def test_state_builder_mixed(self):
|
||||||
|
fake_network1 = FakeModel(1, admin_state_up=True)
|
||||||
|
fake_network2 = FakeModel(2, admin_state_up=True)
|
||||||
|
fake_network3 = FakeModel(3, admin_state_up=False)
|
||||||
|
|
||||||
|
fake_subnet1 = FakeModel(1, network_id=1, enable_dhcp=True)
|
||||||
|
fake_subnet2 = FakeModel(2, network_id=2, enable_dhcp=False)
|
||||||
|
fake_subnet3 = FakeModel(3, network_id=3, enable_dhcp=True)
|
||||||
|
|
||||||
|
fake_network1.subnets = [fake_subnet1]
|
||||||
|
fake_network2.subnets = [fake_subnet2]
|
||||||
|
fake_network3.subnets = [fake_subnet3]
|
||||||
|
|
||||||
|
fake_subnet1.network = fake_network1
|
||||||
|
fake_subnet2.network = fake_network2
|
||||||
|
fake_subnet3.network = fake_network3
|
||||||
|
|
||||||
|
fake_allocation = [
|
||||||
|
FakeModel(2, subnet_id=1)
|
||||||
|
]
|
||||||
|
|
||||||
|
fake_subnets = [fake_subnet1, fake_subnet2, fake_subnet3]
|
||||||
|
fake_networks = [fake_network1, fake_network2, fake_network3]
|
||||||
|
|
||||||
|
db = mock.Mock()
|
||||||
|
db.subnets.all = mock.Mock(return_value=fake_subnets)
|
||||||
|
db.networks.all = mock.Mock(return_value=fake_networks)
|
||||||
|
db.ipallocations.all = mock.Mock(return_value=fake_allocation)
|
||||||
|
self.dhcp.db = db
|
||||||
|
state = self.dhcp._state_builder()
|
||||||
|
|
||||||
|
self.assertEquals(state.networks, set([1]))
|
||||||
|
|
||||||
|
expected_subnets = set([
|
||||||
|
(hash(str(fake_subnets[0])), 1),
|
||||||
])
|
])
|
||||||
self.assertEquals(state.subnet_hashes, expected_subnets)
|
self.assertEquals(state.subnet_hashes, expected_subnets)
|
||||||
|
|
||||||
@ -120,7 +265,8 @@ class TestDhcpAgent(unittest.TestCase):
|
|||||||
return self.dhcp.get_network_state_delta()
|
return self.dhcp.get_network_state_delta()
|
||||||
|
|
||||||
def test_get_network_state_fresh(self):
|
def test_get_network_state_fresh(self):
|
||||||
new_state = dhcp_agent.State(set([1]), set([(3, 1)]), set([(11, 1)]))
|
new_state = dhcp_agent.State(set([1]), set([(3, 1)]),
|
||||||
|
set([(11, 1)]))
|
||||||
|
|
||||||
delta = self._network_state_helper(self.dhcp.prev_state, new_state)
|
delta = self._network_state_helper(self.dhcp.prev_state, new_state)
|
||||||
self.assertEqual(delta,
|
self.assertEqual(delta,
|
||||||
|
@ -58,6 +58,7 @@ class FakeV4Subnet:
|
|||||||
ip_version = 4
|
ip_version = 4
|
||||||
cidr = '192.168.0.0/24'
|
cidr = '192.168.0.0/24'
|
||||||
gateway_ip = '192.168.0.1'
|
gateway_ip = '192.168.0.1'
|
||||||
|
enable_dhcp = True
|
||||||
|
|
||||||
|
|
||||||
class FakeV6Subnet:
|
class FakeV6Subnet:
|
||||||
@ -65,6 +66,15 @@ class FakeV6Subnet:
|
|||||||
ip_version = 6
|
ip_version = 6
|
||||||
cidr = 'fdca:3ba5:a17a:4ba3::/64'
|
cidr = 'fdca:3ba5:a17a:4ba3::/64'
|
||||||
gateway_ip = 'fdca:3ba5:a17a:4ba3::1'
|
gateway_ip = 'fdca:3ba5:a17a:4ba3::1'
|
||||||
|
enable_dhcp = True
|
||||||
|
|
||||||
|
|
||||||
|
class FakeV4SubnetNoDHCP:
|
||||||
|
id = 'eeeeeeee-eeee-eeee-eeee-eeeeeeeeeeee'
|
||||||
|
ip_version = 4
|
||||||
|
cidr = '192.168.1.0/24'
|
||||||
|
gateway_ip = '192.168.1.1'
|
||||||
|
enable_dhcp = False
|
||||||
|
|
||||||
|
|
||||||
class FakeV4Network:
|
class FakeV4Network:
|
||||||
@ -85,6 +95,12 @@ class FakeDualNetwork:
|
|||||||
ports = [FakePort1(), FakePort2(), FakePort3()]
|
ports = [FakePort1(), FakePort2(), FakePort3()]
|
||||||
|
|
||||||
|
|
||||||
|
class FakeDualNetworkSingleDHCP:
|
||||||
|
id = 'cccccccc-cccc-cccc-cccc-cccccccccccc'
|
||||||
|
subnets = [FakeV4Subnet(), FakeV4SubnetNoDHCP()]
|
||||||
|
ports = [FakePort1(), FakePort2(), FakePort3()]
|
||||||
|
|
||||||
|
|
||||||
class TestDhcpBase(unittest.TestCase):
|
class TestDhcpBase(unittest.TestCase):
|
||||||
def test_base_abc_error(self):
|
def test_base_abc_error(self):
|
||||||
self.assertRaises(TypeError, dhcp.DhcpBase, None)
|
self.assertRaises(TypeError, dhcp.DhcpBase, None)
|
||||||
@ -353,6 +369,15 @@ class TestDnsmasq(TestBase):
|
|||||||
|
|
||||||
self.safe.assert_called_once_with('/foo/opts', expected)
|
self.safe.assert_called_once_with('/foo/opts', expected)
|
||||||
|
|
||||||
|
def test_output_opts_file_single_dhcp(self):
|
||||||
|
expected = 'tag:tag0,option:router,192.168.0.1'
|
||||||
|
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_reload_allocations(self):
|
def test_reload_allocations(self):
|
||||||
exp_host_name = '/dhcp/cccccccc-cccc-cccc-cccc-cccccccccccc/host'
|
exp_host_name = '/dhcp/cccccccc-cccc-cccc-cccc-cccccccccccc/host'
|
||||||
exp_host_data = """
|
exp_host_data = """
|
||||||
|
Loading…
Reference in New Issue
Block a user