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
=== modified file 'nova/network/linux_net.py'
--- nova/network/linux_net.py 2011-09-20 09:37:07 +0000
+++ nova/network/linux_net.py 2011-09-21 13:00:32 +0000
@@ -472,22 +472,30 @@
472472
473 # NOTE(vish): The ip for dnsmasq has to be the first address on the473 # NOTE(vish): The ip for dnsmasq has to be the first address on the
474 # bridge for it to respond to reqests properly474 # bridge for it to respond to reqests properly
475 suffix = network_ref['cidr'].rpartition('/')[2]475 full_ip = '%s/%s' % (network_ref['dhcp_server'],
476 out, err = _execute('ip', 'addr', 'add',476 network_ref['cidr'].rpartition('/')[2])
477 '%s/%s' %477 new_ip_params = [[full_ip, 'brd', network_ref['broadcast']]]
478 (network_ref['dhcp_server'], suffix),478 old_ip_params = []
479 'brd',479 out, err = _execute('ip', 'addr', 'show', 'dev', dev,
480 network_ref['broadcast'],480 'scope', 'global', run_as_root=True)
481 'dev',481 for line in out.split('\n'):
482 dev,482 fields = line.split()
483 run_as_root=True,483 if fields and fields[0] == 'inet':
484 check_exit_code=False)484 ip_params = fields[1:-1]
485 if err and err != 'RTNETLINK answers: File exists\n':485 old_ip_params.append(ip_params)
486 raise exception.Error('Failed to add ip: %s' % err)486 if ip_params[0] != full_ip:
487 if FLAGS.send_arp_for_ha:487 new_ip_params.append(ip_params)
488 _execute('arping', '-U', network_ref['gateway'],488 if not old_ip_params or old_ip_params[0][0] != full_ip:
489 '-A', '-I', dev,489 for ip_params in old_ip_params:
490 '-c', 1, run_as_root=True, check_exit_code=False)490 _execute(*_ip_bridge_cmd('del', ip_params, dev),
491 run_as_root=True)
492 for ip_params in new_ip_params:
493 _execute(*_ip_bridge_cmd('add', ip_params, dev),
494 run_as_root=True)
495 if FLAGS.send_arp_for_ha:
496 _execute('arping', '-U', network_ref['dhcp_server'],
497 '-A', '-I', dev,
498 '-c', 1, run_as_root=True, check_exit_code=False)
491 if(FLAGS.use_ipv6):499 if(FLAGS.use_ipv6):
492 _execute('ip', '-f', 'inet6', 'addr',500 _execute('ip', '-f', 'inet6', 'addr',
493 'change', network_ref['cidr_v6'],501 'change', network_ref['cidr_v6'],
494502
=== modified file 'nova/tests/test_linux_net.py'
--- nova/tests/test_linux_net.py 2011-09-07 20:37:58 +0000
+++ nova/tests/test_linux_net.py 2011-09-21 13:00:32 +0000
@@ -345,3 +345,72 @@
345 expected = ("10.0.0.1,fake_instance00.novalocal,192.168.0.100")345 expected = ("10.0.0.1,fake_instance00.novalocal,192.168.0.100")
346 actual = self.driver._host_dhcp(fixed_ips[0])346 actual = self.driver._host_dhcp(fixed_ips[0])
347 self.assertEquals(actual, expected)347 self.assertEquals(actual, expected)
348
349 def _test_initialize_gateway(self, existing, expected):
350 self.flags(fake_network=False)
351 executes = []
352
353 def fake_execute(*args, **kwargs):
354 executes.append(args)
355 if args[0] == 'ip' and args[1] == 'addr' and args[2] == 'show':
356 return existing, ""
357 self.stubs.Set(utils, 'execute', fake_execute)
358 network = {'dhcp_server': '192.168.1.1',
359 'cidr': '192.168.1.0/24',
360 'broadcast': '192.168.1.255',
361 'cidr_v6': '2001:db8::/64'}
362 self.driver.initialize_gateway_device('eth0', network)
363 self.assertEqual(executes, expected)
364
365 def test_initialize_gateway_moves_wrong_ip(self):
366 existing = ("2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> "
367 " mtu 1500 qdisc pfifo_fast state UNKNOWN qlen 1000\n"
368 " link/ether de:ad:be:ef:be:ef brd ff:ff:ff:ff:ff:ff\n"
369 " inet 192.168.0.1/24 brd 192.168.0.255 scope global eth0\n"
370 " inet6 dead::beef:dead:beef:dead/64 scope link\n"
371 " valid_lft forever preferred_lft forever\n")
372 expected = [
373 ('ip', 'addr', 'show', 'dev', 'eth0', 'scope', 'global'),
374 ('ip', 'addr', 'del', '192.168.0.1/24',
375 'brd', '192.168.0.255', 'scope', 'global', 'dev', 'eth0'),
376 ('ip', 'addr', 'add', '192.168.1.1/24',
377 'brd', '192.168.1.255', 'dev', 'eth0'),
378 ('ip', 'addr', 'add', '192.168.0.1/24',
379 'brd', '192.168.0.255', 'scope', 'global', 'dev', 'eth0'),
380 ('ip', '-f', 'inet6', 'addr', 'change',
381 '2001:db8::/64', 'dev', 'eth0'),
382 ('ip', 'link', 'set', 'dev', 'eth0', 'promisc', 'on'),
383 ]
384 self._test_initialize_gateway(existing, expected)
385
386 def test_initialize_gateway_no_move_right_ip(self):
387 existing = ("2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> "
388 " mtu 1500 qdisc pfifo_fast state UNKNOWN qlen 1000\n"
389 " link/ether de:ad:be:ef:be:ef brd ff:ff:ff:ff:ff:ff\n"
390 " inet 192.168.1.1/24 brd 192.168.1.255 scope global eth0\n"
391 " inet 192.168.0.1/24 brd 192.168.0.255 scope global eth0\n"
392 " inet6 dead::beef:dead:beef:dead/64 scope link\n"
393 " valid_lft forever preferred_lft forever\n")
394 expected = [
395 ('ip', 'addr', 'show', 'dev', 'eth0', 'scope', 'global'),
396 ('ip', '-f', 'inet6', 'addr', 'change',
397 '2001:db8::/64', 'dev', 'eth0'),
398 ('ip', 'link', 'set', 'dev', 'eth0', 'promisc', 'on'),
399 ]
400 self._test_initialize_gateway(existing, expected)
401
402 def test_initialize_gateway_add_if_blank(self):
403 existing = ("2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> "
404 " mtu 1500 qdisc pfifo_fast state UNKNOWN qlen 1000\n"
405 " link/ether de:ad:be:ef:be:ef brd ff:ff:ff:ff:ff:ff\n"
406 " inet6 dead::beef:dead:beef:dead/64 scope link\n"
407 " valid_lft forever preferred_lft forever\n")
408 expected = [
409 ('ip', 'addr', 'show', 'dev', 'eth0', 'scope', 'global'),
410 ('ip', 'addr', 'add', '192.168.1.1/24',
411 'brd', '192.168.1.255', 'dev', 'eth0'),
412 ('ip', '-f', 'inet6', 'addr', 'change',
413 '2001:db8::/64', 'dev', 'eth0'),
414 ('ip', 'link', 'set', 'dev', 'eth0', 'promisc', 'on'),
415 ]
416 self._test_initialize_gateway(existing, expected)