summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSalvatore Orlando <salvatore.orlando@eu.citrix.com>2011-03-14 16:50:35 +0000
committerSalvatore Orlando <salvatore.orlando@eu.citrix.com>2011-03-14 16:50:35 +0000
commit7649963c7bcda67744988d6a65747c8b67d4a0f1 (patch)
treec60509a75e5024dacb6ec4d84c3af71a86f93322
parente2aed1036c0fb61a2924ffa28d66f87539d43ba1 (diff)
parent7fde254ec53aeb88301e5592853961b2b9c87ef4 (diff)
merge trunk
-rwxr-xr-xbin/nova-dhcpbridge2
-rw-r--r--nova/network/linux_net.py32
-rw-r--r--nova/tests/test_network.py26
-rwxr-xr-xplugins/xenserver/networking/etc/xensource/scripts/vif_rules.py34
4 files changed, 74 insertions, 20 deletions
diff --git a/bin/nova-dhcpbridge b/bin/nova-dhcpbridge
index 3dd9de367..7ef51feba 100755
--- a/bin/nova-dhcpbridge
+++ b/bin/nova-dhcpbridge
@@ -94,7 +94,7 @@ def init_leases(interface):
"""Get the list of hosts for an interface."""
ctxt = context.get_admin_context()
network_ref = db.network_get_by_bridge(ctxt, interface)
- return linux_net.get_dhcp_hosts(ctxt, network_ref['id'])
+ return linux_net.get_dhcp_leases(ctxt, network_ref['id'])
def main():
diff --git a/nova/network/linux_net.py b/nova/network/linux_net.py
index e69ed2f75..7106e6164 100644
--- a/nova/network/linux_net.py
+++ b/nova/network/linux_net.py
@@ -19,6 +19,7 @@ Implements vlans, bridges, and iptables rules using linux utilities.
import inspect
import os
+import calendar
from eventlet import semaphore
@@ -56,6 +57,8 @@ flags.DEFINE_string('routing_source_ip', '$my_ip',
'Public IP of network host')
flags.DEFINE_string('input_chain', 'INPUT',
'chain to add nova_input to')
+flags.DEFINE_integer('dhcp_lease_time', 120,
+ 'Lifetime of a DHCP lease')
flags.DEFINE_string('dns_server', None,
'if set, uses specific dns server for dnsmasq')
@@ -533,8 +536,17 @@ def ensure_bridge(bridge, interface, net_attrs=None):
bridge)
+def get_dhcp_leases(context, network_id):
+ """Return a network's hosts config in dnsmasq leasefile format"""
+ hosts = []
+ for fixed_ip_ref in db.network_get_associated_fixed_ips(context,
+ network_id):
+ hosts.append(_host_lease(fixed_ip_ref))
+ return '\n'.join(hosts)
+
+
def get_dhcp_hosts(context, network_id):
- """Get a string containing a network's hosts config in dnsmasq format"""
+ """Get a string containing a network's hosts config in dhcp-host format"""
hosts = []
for fixed_ip_ref in db.network_get_associated_fixed_ips(context,
network_id):
@@ -625,8 +637,24 @@ interface %s
utils.get_my_linklocal(network_ref['bridge'])})
+def _host_lease(fixed_ip_ref):
+ """Return a host string for an address in leasefile format"""
+ instance_ref = fixed_ip_ref['instance']
+ if instance_ref['updated_at']:
+ timestamp = instance_ref['updated_at']
+ else:
+ timestamp = instance_ref['created_at']
+
+ seconds_since_epoch = calendar.timegm(timestamp.utctimetuple())
+
+ return "%d %s %s %s *" % (seconds_since_epoch + FLAGS.dhcp_lease_time,
+ instance_ref['mac_address'],
+ fixed_ip_ref['address'],
+ instance_ref['hostname'] or '*')
+
+
def _host_dhcp(fixed_ip_ref):
- """Return a host string for an address"""
+ """Return a host string for an address in dhcp-host format"""
instance_ref = fixed_ip_ref['instance']
return "%s,%s.%s,%s" % (instance_ref['mac_address'],
instance_ref['hostname'],
diff --git a/nova/tests/test_network.py b/nova/tests/test_network.py
index 53e35ce7e..1e634b388 100644
--- a/nova/tests/test_network.py
+++ b/nova/tests/test_network.py
@@ -20,6 +20,7 @@ Unit Tests for network code
"""
import IPy
import os
+import time
from nova import context
from nova import db
@@ -463,6 +464,31 @@ class NetworkTestCase(test.TestCase):
network['id'])
self.assertEqual(ip_count, num_available_ips)
+ def test_dhcp_lease_output(self):
+ admin_ctxt = context.get_admin_context()
+ address = self._create_address(0, self.instance_id)
+ lease_ip(address)
+ network_ref = db.network_get_by_instance(admin_ctxt, self.instance_id)
+ leases = linux_net.get_dhcp_leases(context.get_admin_context(),
+ network_ref['id'])
+ for line in leases.split('\n'):
+ seconds, mac, ip, hostname, client_id = line.split(' ')
+ self.assertTrue(int(seconds) > time.time(), 'Lease expires in '
+ 'the past')
+ octets = mac.split(':')
+ self.assertEqual(len(octets), 6, "Wrong number of octets "
+ "in %s" % (max,))
+ for octet in octets:
+ self.assertEqual(len(octet), 2, "Oddly sized octet: %s"
+ % (octet,))
+ # This will throw an exception if the octet is invalid
+ int(octet, 16)
+
+ # And this will raise an exception in case of an invalid IP
+ IPy.IP(ip)
+
+ release_ip(address)
+
def is_allocated_in_project(address, project_id):
"""Returns true if address is in specified project"""
diff --git a/plugins/xenserver/networking/etc/xensource/scripts/vif_rules.py b/plugins/xenserver/networking/etc/xensource/scripts/vif_rules.py
index d2b2d61e6..48122e6d6 100755
--- a/plugins/xenserver/networking/etc/xensource/scripts/vif_rules.py
+++ b/plugins/xenserver/networking/etc/xensource/scripts/vif_rules.py
@@ -54,6 +54,7 @@ def main(dom_id, command, only_this_vif=None):
def execute(*command, return_stdout=False):
devnull = open(os.devnull, 'w')
+ command = map(str, command)
proc = subprocess.Popen(command, close_fds=True,
stdout=subprocess.PIPE, stderr=devnull)
devnull.close()
@@ -71,13 +72,13 @@ def apply_iptables_rules(command, params):
iptables = lambda *rule: execute('/sbin/iptables', *rule)
iptables('-D', 'FORWARD', '-m', 'physdev',
- '--physdev-in', '%(VIF)s' % params,
- '-s', '%(IP)s' % params,
+ '--physdev-in', params['VIF'],
+ '-s', params['IP'],
'-j', 'ACCEPT')
if command == 'online':
iptables('-A', 'FORWARD', '-m', 'physdev',
- '--physdev-in', '%(VIF)s' % params,
- '-s', '%(IP)s' % params,
+ '--physdev-in', params['VIF'],
+ '-s', params['IP'],
'-j', 'ACCEPT')
@@ -85,25 +86,24 @@ def apply_arptables_rules(command, params):
arptables = lambda *rule: execute('/sbin/arptables', *rule)
arptables('-D', 'FORWARD', '--opcode', 'Request',
- '--in-interface', '%(VIF)s' % params,
- '--source-ip', '%(IP)s' % params,
- '--source-mac', '%(MAC)s' % params,
+ '--in-interface', params['VIF'],
+ '--source-ip', params['IP'],
+ '--source-mac', params['MAC'],
'-j', 'ACCEPT')
arptables('-D', 'FORWARD', '--opcode', 'Reply',
- '--in-interface', '%(VIF)s' % params,
- '--source-ip', '%(IP)s' % params,
- '--source-mac', '%(MAC)s' % params,
+ '--in-interface', params['VIF'],
+ '--source-ip', params['IP'],
+ '--source-mac', params['MAC'],
'-j', 'ACCEPT')
if command == 'online':
arptables('-A', 'FORWARD', '--opcode', 'Request',
- '--in-interface', '%(VIF)s' % params
- '--source-ip', '%(IP)s' % params,
- '--source-mac', '%(MAC)s' % params,
+ '--in-interface', params['VIF'],
+ '--source-mac', params['MAC'],
'-j', 'ACCEPT')
arptables('-A', 'FORWARD', '--opcode', 'Reply',
- '--in-interface', '%(VIF)s' % params,
- '--source-ip', '%(IP)s' % params,
- '--source-mac', '%(MAC)s' % params,
+ '--in-interface', params['VIF'],
+ '--source-ip', params['IP'],
+ '--source-mac', params['MAC'],
'-j', 'ACCEPT')
@@ -130,7 +130,7 @@ def apply_ebtables_rules(command, params):
'-i', params['VIF'], '-j', 'DROP')
if command == 'online':
ebtables('-I', 'FORWARD', '1', '-s', '!', params['MAC'],
- '-i', '%(VIF)s', '-j', 'DROP')
+ '-i', params['VIF'], '-j', 'DROP')
if __name__ == "__main__":