Merge lp:~vishvananda/nova/fix-dhcp into lp:~hudson-openstack/nova/trunk

Proposed by Vish Ishaya
Status: Merged
Approved by: Dan Prince
Approved revision: 1545
Merged at revision: 1607
Proposed branch: lp:~vishvananda/nova/fix-dhcp
Merge into: lp:~hudson-openstack/nova/trunk
Diff against target: 127 lines (+93/-16)
2 files modified
nova/network/linux_net.py (+24/-16)
nova/tests/test_linux_net.py (+69/-0)
To merge this branch: bzr merge lp:~vishvananda/nova/fix-dhcp
Reviewer Review Type Date Requested Status
Dan Prince (community) Approve
Soren Hansen (community) Approve
Review via email: mp+76360@code.launchpad.net

Description of the change

Makes sure ips are moved on the bridge for nodes running dnsmasq so that the gateway ip is always first.

To post a comment you must log in.
lp:~vishvananda/nova/fix-dhcp updated
1544. By Vish Ishaya

add tests and fix bug when no ip was set

Revision history for this message
Soren Hansen (soren) wrote :

lgtm

I do wonder, though, if this is a bug in dnsmasq of if it's by design? Have we talked to dnsmasq upstream at all? According to man ip(8), the addresses are not discriminated, so the order shouldn't matter, AFAICS.

review: Approve
Revision history for this message
Soren Hansen (soren) wrote :

> I do wonder, though, if this is a bug in dnsmasq of if it's by design?

That should have said:

I do wonder, though, if this is a bug in dnsmasq or if it's by design?

lp:~vishvananda/nova/fix-dhcp updated
1545. By Vish Ishaya

pep8

Revision history for this message
Dan Prince (dan-prince) wrote :

This looks good.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'nova/network/linux_net.py'
2--- nova/network/linux_net.py 2011-09-20 09:37:07 +0000
3+++ nova/network/linux_net.py 2011-09-21 13:00:32 +0000
4@@ -472,22 +472,30 @@
5
6 # NOTE(vish): The ip for dnsmasq has to be the first address on the
7 # bridge for it to respond to reqests properly
8- suffix = network_ref['cidr'].rpartition('/')[2]
9- out, err = _execute('ip', 'addr', 'add',
10- '%s/%s' %
11- (network_ref['dhcp_server'], suffix),
12- 'brd',
13- network_ref['broadcast'],
14- 'dev',
15- dev,
16- run_as_root=True,
17- check_exit_code=False)
18- if err and err != 'RTNETLINK answers: File exists\n':
19- raise exception.Error('Failed to add ip: %s' % err)
20- if FLAGS.send_arp_for_ha:
21- _execute('arping', '-U', network_ref['gateway'],
22- '-A', '-I', dev,
23- '-c', 1, run_as_root=True, check_exit_code=False)
24+ full_ip = '%s/%s' % (network_ref['dhcp_server'],
25+ network_ref['cidr'].rpartition('/')[2])
26+ new_ip_params = [[full_ip, 'brd', network_ref['broadcast']]]
27+ old_ip_params = []
28+ out, err = _execute('ip', 'addr', 'show', 'dev', dev,
29+ 'scope', 'global', run_as_root=True)
30+ for line in out.split('\n'):
31+ fields = line.split()
32+ if fields and fields[0] == 'inet':
33+ ip_params = fields[1:-1]
34+ old_ip_params.append(ip_params)
35+ if ip_params[0] != full_ip:
36+ new_ip_params.append(ip_params)
37+ if not old_ip_params or old_ip_params[0][0] != full_ip:
38+ for ip_params in old_ip_params:
39+ _execute(*_ip_bridge_cmd('del', ip_params, dev),
40+ run_as_root=True)
41+ for ip_params in new_ip_params:
42+ _execute(*_ip_bridge_cmd('add', ip_params, dev),
43+ run_as_root=True)
44+ if FLAGS.send_arp_for_ha:
45+ _execute('arping', '-U', network_ref['dhcp_server'],
46+ '-A', '-I', dev,
47+ '-c', 1, run_as_root=True, check_exit_code=False)
48 if(FLAGS.use_ipv6):
49 _execute('ip', '-f', 'inet6', 'addr',
50 'change', network_ref['cidr_v6'],
51
52=== modified file 'nova/tests/test_linux_net.py'
53--- nova/tests/test_linux_net.py 2011-09-07 20:37:58 +0000
54+++ nova/tests/test_linux_net.py 2011-09-21 13:00:32 +0000
55@@ -345,3 +345,72 @@
56 expected = ("10.0.0.1,fake_instance00.novalocal,192.168.0.100")
57 actual = self.driver._host_dhcp(fixed_ips[0])
58 self.assertEquals(actual, expected)
59+
60+ def _test_initialize_gateway(self, existing, expected):
61+ self.flags(fake_network=False)
62+ executes = []
63+
64+ def fake_execute(*args, **kwargs):
65+ executes.append(args)
66+ if args[0] == 'ip' and args[1] == 'addr' and args[2] == 'show':
67+ return existing, ""
68+ self.stubs.Set(utils, 'execute', fake_execute)
69+ network = {'dhcp_server': '192.168.1.1',
70+ 'cidr': '192.168.1.0/24',
71+ 'broadcast': '192.168.1.255',
72+ 'cidr_v6': '2001:db8::/64'}
73+ self.driver.initialize_gateway_device('eth0', network)
74+ self.assertEqual(executes, expected)
75+
76+ def test_initialize_gateway_moves_wrong_ip(self):
77+ existing = ("2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> "
78+ " mtu 1500 qdisc pfifo_fast state UNKNOWN qlen 1000\n"
79+ " link/ether de:ad:be:ef:be:ef brd ff:ff:ff:ff:ff:ff\n"
80+ " inet 192.168.0.1/24 brd 192.168.0.255 scope global eth0\n"
81+ " inet6 dead::beef:dead:beef:dead/64 scope link\n"
82+ " valid_lft forever preferred_lft forever\n")
83+ expected = [
84+ ('ip', 'addr', 'show', 'dev', 'eth0', 'scope', 'global'),
85+ ('ip', 'addr', 'del', '192.168.0.1/24',
86+ 'brd', '192.168.0.255', 'scope', 'global', 'dev', 'eth0'),
87+ ('ip', 'addr', 'add', '192.168.1.1/24',
88+ 'brd', '192.168.1.255', 'dev', 'eth0'),
89+ ('ip', 'addr', 'add', '192.168.0.1/24',
90+ 'brd', '192.168.0.255', 'scope', 'global', 'dev', 'eth0'),
91+ ('ip', '-f', 'inet6', 'addr', 'change',
92+ '2001:db8::/64', 'dev', 'eth0'),
93+ ('ip', 'link', 'set', 'dev', 'eth0', 'promisc', 'on'),
94+ ]
95+ self._test_initialize_gateway(existing, expected)
96+
97+ def test_initialize_gateway_no_move_right_ip(self):
98+ existing = ("2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> "
99+ " mtu 1500 qdisc pfifo_fast state UNKNOWN qlen 1000\n"
100+ " link/ether de:ad:be:ef:be:ef brd ff:ff:ff:ff:ff:ff\n"
101+ " inet 192.168.1.1/24 brd 192.168.1.255 scope global eth0\n"
102+ " inet 192.168.0.1/24 brd 192.168.0.255 scope global eth0\n"
103+ " inet6 dead::beef:dead:beef:dead/64 scope link\n"
104+ " valid_lft forever preferred_lft forever\n")
105+ expected = [
106+ ('ip', 'addr', 'show', 'dev', 'eth0', 'scope', 'global'),
107+ ('ip', '-f', 'inet6', 'addr', 'change',
108+ '2001:db8::/64', 'dev', 'eth0'),
109+ ('ip', 'link', 'set', 'dev', 'eth0', 'promisc', 'on'),
110+ ]
111+ self._test_initialize_gateway(existing, expected)
112+
113+ def test_initialize_gateway_add_if_blank(self):
114+ existing = ("2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> "
115+ " mtu 1500 qdisc pfifo_fast state UNKNOWN qlen 1000\n"
116+ " link/ether de:ad:be:ef:be:ef brd ff:ff:ff:ff:ff:ff\n"
117+ " inet6 dead::beef:dead:beef:dead/64 scope link\n"
118+ " valid_lft forever preferred_lft forever\n")
119+ expected = [
120+ ('ip', 'addr', 'show', 'dev', 'eth0', 'scope', 'global'),
121+ ('ip', 'addr', 'add', '192.168.1.1/24',
122+ 'brd', '192.168.1.255', 'dev', 'eth0'),
123+ ('ip', '-f', 'inet6', 'addr', 'change',
124+ '2001:db8::/64', 'dev', 'eth0'),
125+ ('ip', 'link', 'set', 'dev', 'eth0', 'promisc', 'on'),
126+ ]
127+ self._test_initialize_gateway(existing, expected)