Skip to content

Commit

Permalink
populate dnsmasq lease db with valid leases
Browse files Browse the repository at this point in the history
At start dnsmasq retrieves its lease db by calling the nova-dhcpbridge
script with the init action.

Previously we were returning all allocated IPs in the network and
calculating the lease exirpation time based upon instances.updated_at
or instances.created_at.

Now we are only returning entries for IPs that are allocated and leased.
Additionally we set the lease expiration time to be i
now + CONF.dhcp_lease_time

Change-Id: Ie3b4fafd38094dc01ceea592ab5229e581193512
Fixes: bug #1103260
  • Loading branch information
Chet Burgess committed Jan 25, 2013
1 parent f24cfa8 commit e12339d
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 10 deletions.
6 changes: 5 additions & 1 deletion nova/db/sqlalchemy/api.py
Expand Up @@ -2245,7 +2245,9 @@ def network_get_associated_fixed_ips(context, network_id, host=None):
models.VirtualInterface.address,
models.Instance.hostname,
models.Instance.updated_at,
models.Instance.created_at).\
models.Instance.created_at,
models.FixedIp.allocated,
models.FixedIp.leased).\
filter(models.FixedIp.deleted == 0).\
filter(models.FixedIp.network_id == network_id).\
filter(models.FixedIp.allocated == True).\
Expand All @@ -2267,6 +2269,8 @@ def network_get_associated_fixed_ips(context, network_id, host=None):
cleaned['instance_hostname'] = datum[5]
cleaned['instance_updated'] = datum[6]
cleaned['instance_created'] = datum[7]
cleaned['allocated'] = datum[8]
cleaned['leased'] = datum[9]
data.append(cleaned)
return data

Expand Down
14 changes: 7 additions & 7 deletions nova/network/linux_net.py
Expand Up @@ -31,6 +31,7 @@
from nova.openstack.common import importutils
from nova.openstack.common import lockutils
from nova.openstack.common import log as logging
from nova.openstack.common import timeutils
from nova import paths
from nova import utils

Expand Down Expand Up @@ -735,7 +736,11 @@ def get_dhcp_leases(context, network_ref):
for data in db.network_get_associated_fixed_ips(context,
network_ref['id'],
host=host):
hosts.append(_host_lease(data))
# NOTE(cfb): Don't return a lease entry if the IP isn't
# already leased
if data['allocated'] and data['leased']:
hosts.append(_host_lease(data))

return '\n'.join(hosts)


Expand Down Expand Up @@ -988,13 +993,8 @@ def update_ra(context, dev, network_ref):

def _host_lease(data):
"""Return a host string for an address in leasefile format."""
if data['instance_updated']:
timestamp = data['instance_updated']
else:
timestamp = data['instance_created']

timestamp = timeutils.utcnow()
seconds_since_epoch = calendar.timegm(timestamp.utctimetuple())

return '%d %s %s %s *' % (seconds_since_epoch + CONF.dhcp_lease_time,
data['vif_address'],
data['address'],
Expand Down
50 changes: 48 additions & 2 deletions nova/tests/network/test_linux_net.py
Expand Up @@ -15,6 +15,7 @@
# License for the specific language governing permissions and limitations
# under the License.

import calendar
import os

import mox
Expand All @@ -25,6 +26,7 @@
from nova.network import linux_net
from nova.openstack.common import fileutils
from nova.openstack.common import log as logging
from nova.openstack.common import timeutils
from nova import test
from nova import utils

Expand Down Expand Up @@ -107,6 +109,7 @@
'address': '192.168.0.100',
'instance_id': 0,
'allocated': True,
'leased': True,
'virtual_interface_id': 0,
'instance_uuid': '00000000-0000-0000-0000-0000000000000000',
'floating_ips': []},
Expand All @@ -115,6 +118,7 @@
'address': '192.168.1.100',
'instance_id': 0,
'allocated': True,
'leased': True,
'virtual_interface_id': 1,
'instance_uuid': '00000000-0000-0000-0000-0000000000000000',
'floating_ips': []},
Expand All @@ -123,6 +127,7 @@
'address': '192.168.0.101',
'instance_id': 1,
'allocated': True,
'leased': True,
'virtual_interface_id': 2,
'instance_uuid': '00000000-0000-0000-0000-0000000000000001',
'floating_ips': []},
Expand All @@ -131,6 +136,7 @@
'address': '192.168.1.101',
'instance_id': 1,
'allocated': True,
'leased': True,
'virtual_interface_id': 3,
'instance_uuid': '00000000-0000-0000-0000-0000000000000001',
'floating_ips': []},
Expand All @@ -139,6 +145,7 @@
'address': '192.168.0.102',
'instance_id': 0,
'allocated': True,
'leased': False,
'virtual_interface_id': 4,
'instance_uuid': '00000000-0000-0000-0000-0000000000000000',
'floating_ips': []},
Expand All @@ -147,6 +154,7 @@
'address': '192.168.1.102',
'instance_id': 1,
'allocated': True,
'leased': False,
'virtual_interface_id': 5,
'instance_uuid': '00000000-0000-0000-0000-0000000000000001',
'floating_ips': []}]
Expand Down Expand Up @@ -184,7 +192,7 @@
'instance_uuid': '00000000-0000-0000-0000-0000000000000001'}]


def get_associated(context, network_id, host=None):
def get_associated(context, network_id, host=None, address=None):
result = []
for datum in fixed_ips:
if (datum['network_id'] == network_id and datum['allocated']
Expand All @@ -193,6 +201,8 @@ def get_associated(context, network_id, host=None):
instance = instances[datum['instance_uuid']]
if host and host != instance['host']:
continue
if address and address != datum['address']:
continue
cleaned = {}
cleaned['address'] = datum['address']
cleaned['instance_uuid'] = datum['instance_uuid']
Expand All @@ -203,6 +213,8 @@ def get_associated(context, network_id, host=None):
cleaned['instance_hostname'] = instance['hostname']
cleaned['instance_updated'] = instance['updated_at']
cleaned['instance_created'] = instance['created_at']
cleaned['allocated'] = datum['allocated']
cleaned['leased'] = datum['leased']
result.append(cleaned)
return result

Expand Down Expand Up @@ -299,7 +311,6 @@ def test_get_dhcp_hosts_for_nw01(self):
"192.168.1.102,net:NW-5"
)
actual_hosts = self.driver.get_dhcp_hosts(self.context, networks[1])

self.assertEquals(actual_hosts, expected)

def test_get_dns_hosts_for_nw00(self):
Expand Down Expand Up @@ -333,6 +344,41 @@ def test_get_dhcp_opts_for_nw01(self):

self.assertEquals(actual_opts, expected_opts)

def test_get_dhcp_leases_for_nw00(self):
timestamp = timeutils.utcnow()
seconds_since_epoch = calendar.timegm(timestamp.utctimetuple())

leases = self.driver.get_dhcp_leases(self.context, networks[0])
leases = leases.split('\n')
for lease in leases:
lease = lease.split(' ')
data = get_associated(self.context, 0, address=lease[2])[0]
self.assertTrue(data['allocated'])
self.assertTrue(data['leased'])
self.assertTrue(lease[0] > seconds_since_epoch)
self.assertTrue(lease[1] == data['vif_address'])
self.assertTrue(lease[2] == data['address'])
self.assertTrue(lease[3] == data['instance_hostname'])
self.assertTrue(lease[4] == '*')

def test_get_dhcp_leases_for_nw01(self):
self.flags(host='fake_instance01')
timestamp = timeutils.utcnow()
seconds_since_epoch = calendar.timegm(timestamp.utctimetuple())

leases = self.driver.get_dhcp_leases(self.context, networks[1])
leases = leases.split('\n')
for lease in leases:
lease = lease.split(' ')
data = get_associated(self.context, 1, address=lease[2])[0]
self.assertTrue(data['allocated'])
self.assertTrue(data['leased'])
self.assertTrue(lease[0] > seconds_since_epoch)
self.assertTrue(lease[1] == data['vif_address'])
self.assertTrue(lease[2] == data['address'])
self.assertTrue(lease[3] == data['instance_hostname'])
self.assertTrue(lease[4] == '*')

def test_dhcp_opts_not_default_gateway_network(self):
expected = "NW-0,3"
data = get_associated(self.context, 0)[0]
Expand Down

0 comments on commit e12339d

Please sign in to comment.