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

Proposed by Vish Ishaya
Status: Merged
Approved by: Devin Carlen
Approved revision: 651
Merged at revision: 655
Proposed branch: lp:~vishvananda/nova/lp710959
Merge into: lp:~hudson-openstack/nova/trunk
Diff against target: 95 lines (+57/-11)
1 file modified
nova/network/linux_net.py (+57/-11)
To merge this branch: bzr merge lp:~vishvananda/nova/lp710959
Reviewer Review Type Date Requested Status
Devin Carlen (community) Approve
Jay Pipes (community) Approve
Thierry Carrez (community) Abstain
Review via email: mp+48341@code.launchpad.net

Commit message

Automates the setup for FlatDHCP regardless of whether the interface has an ip address.

FlatDHCP only has worked until now if the underlying interface that you bridge into has no ip address. This branch will do the necessary setup to allow it to work by:

* Creating a bridge with the private address for dhcp
* Moving any existing ips from the interface onto the bridge
* Adding the interface to the bridge
* Recreating the default route if it was deleted by moving the interface

It will additionally add a route to compute hosts for bridges that it adds to the compute hosts. This seems to be necessary in some cases where the default route uses a different interface.

Description of the change

Automates the setup for FlatDHCP regardless of whether the interface has an ip address.

FlatDHCP only has worked until now if the underlying interface that you bridge into has no ip address. This branch will do the necessary setup to allow it to work by:

* Creating a bridge with the private address for dhcp
* Moving any existing ips from the interface onto the bridge
* Adding the interface to the bridge
* Recreating the default route if it was deleted by moving the interface

It will additionally add a route to compute hosts for bridges that it adds to the compute hosts. This seems to be necessary in some cases where the default route uses a different interface.

This is some pretty heavy-handed networking setup, so it only does this if --flat_interface is set in flags.

Important notes:

* route needs to be added to sudoers in the packaging when this branch is merged
* it is using text output from route and ip, so it should be verified that this works in internationalized environments.
* I couldn't verify whether the changes impacted IPv6. Specifically the following line:
206 if(FLAGS.use_ipv6):
207 _execute("sudo ip -f inet6 addr change %s dev %s" %
208 (net_attrs['cidr_v6'], bridge))
I'm not sure if this can be run more than once without throwing an error.
* It should be verified that adding the route on the compute host doesn't create any weird issues with vlan mode on multiple machines. I don't see any reason why it would, but I haven't been able to test every configuration.

To post a comment you must log in.
Revision history for this message
Jay Pipes (jaypipes) wrote :

Seems like a fairly risky patch to include in Bexar, no? Vishy, can we get a test case that verifies the bug fix, or is that not possible because of the faked out networking components?

review: Needs Information
Revision history for this message
Vish Ishaya (vishvananda) wrote :

I don't think it is reasonable to try and get this into Bexar. There is already a note in release notes saying the current limitations of flatdhcp. I might be able to mock out and write tests for parts of this, but the only way i actually feel comfortable that it is working is to run smoketests against a multinode deploy of it. There is too much that just happens to work on one machine that breaks against more than one. On the upside, I've successfully deployed this onto multiple vms with vagrant and it actually works! Patches for smoketests are coming soon, as well as instructions for doing a full multinode deploy and test.

Revision history for this message
Thierry Carrez (ttx) wrote :

I agree this is not a Bexar target, even if it's very annoying. TBH I suspect Bexar testing will uncover more of these types of bugs after release, and we'll be lucky if they are all that easily workaroundable :) Fix in cactus please.

review: Needs Resubmitting (rcfe)
Revision history for this message
Adrien Cunin (adri2000) wrote :

About using text output from commands, I'd suggest at least using route -n instead of route. I've encountered a problem with my gateway hostname being long enough for route to cut out the extra characters, and therefore nova extracting a wrong hostname.

Revision history for this message
Hisaharu Ishii (ishii-hisaharu) wrote :

> * I couldn't verify whether the changes impacted IPv6. Specifically the following line:
> 206 if(FLAGS.use_ipv6):
> 207 _execute("sudo ip -f inet6 addr change %s dev %s" %
> 208 (net_attrs['cidr_v6'], bridge))
> I'm not sure if this can be run more than once without throwing an error.

I wrote above codes to fix bug #707908.
As you know, each network interfaces can have more than one ipv6 addresses.
When some interface A already has ipv6 address B
 "sudo ifconfig A add B" throws the "SIOCSIFADDR: File exists" error.
 "sudo ip -f inet6 addr change B dev A" does nothing without throwing the error.
And when interface A does not have address B
 "sudo ip -f inet6 addr change B dev A" adds address B to A.

lp:~vishvananda/nova/lp710959 updated
647. By Vish Ishaya

Don't need a route for guests. Turns out the issue with routing from the guests was due to duplicate macs

648. By Vish Ishaya

allow for bridge to be the public interface

Revision history for this message
Thierry Carrez (ttx) :
review: Abstain
Revision history for this message
Vish Ishaya (vishvananda) wrote :

merged trunk and got rid of calls to ifconfig. This should be ready for merge.

lp:~vishvananda/nova/lp710959 updated
649. By Vish Ishaya

use route -n instead of route to avoid chopped names

650. By Vish Ishaya

merge source and remove ifconfig

Revision history for this message
Jay Pipes (jaypipes) wrote :

Hi! Code looks good!

One question though (that can be fixed after merge, if necessary):

57 + if err and err != "RTNETLINK answers: File exists\n":
58 + raise exception.Error("Failed to add ip: %s" % err)

I don't think this i18n-proof. Is there a way to instead compare against an error code, instead of an English string?

Approving, though, since the above can be address later.

-jay

review: Approve
Revision history for this message
Vish Ishaya (vishvananda) wrote :

Yes that is one of the questions I raised earlier. Can we just set LC=ALL in the environment or something? I suppose I could check for process execution error and find the exit code instead, but I'll have to verify that the exit codes are actually meaningful.

Vish

On Feb 8, 2011, at 8:16 AM, Jay Pipes wrote:

> Review: Approve
> Hi! Code looks good!
>
> One question though (that can be fixed after merge, if necessary):
>
> 57 + if err and err != "RTNETLINK answers: File exists\n":
> 58 + raise exception.Error("Failed to add ip: %s" % err)
>
> I don't think this i18n-proof. Is there a way to instead compare against an error code, instead of an English string?
>
> Approving, though, since the above can be address later.
>
> -jay
> --
> https://code.launchpad.net/~vishvananda/nova/lp710959/+merge/48341
> You are the owner of lp:~vishvananda/nova/lp710959.

Revision history for this message
Jay Pipes (jaypipes) wrote :

On Tue, Feb 8, 2011 at 12:58 PM, Vish Ishaya <email address hidden> wrote:
> Yes that is one of the questions I raised earlier.  Can we just set LC=ALL in the environment or something?  I suppose I could check for process execution error and find the exit code instead, but I'll have to verify that the exit codes are actually meaningful.

Ya, I wasn't sure about it either, which is why I noted it instead of
marking anything as Needs Fixing :)

-jay

Revision history for this message
Devin Carlen (devcamcar) wrote :

This looks good but we could use some more detailed doc strings detailing what the higher level interactions here are. There are lots of notes but nothing that lets the reader infer a bigger picture.

review: Needs Fixing
lp:~vishvananda/nova/lp710959 updated
651. By Vish Ishaya

add docstring and revert set_ip changes as they are unnecessary

Revision history for this message
Vish Ishaya (vishvananda) wrote :

Devin:

added a docstring for you.

Revision history for this message
Devin Carlen (devcamcar) wrote :

approve

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-02-08 06:07:05 +0000
3+++ nova/network/linux_net.py 2011-02-08 18:57:21 +0000
4@@ -20,6 +20,7 @@
5 import os
6
7 from nova import db
8+from nova import exception
9 from nova import flags
10 from nova import log as logging
11 from nova import utils
12@@ -185,27 +186,72 @@
13
14
15 def ensure_bridge(bridge, interface, net_attrs=None):
16- """Create a bridge unless it already exists"""
17+ """Create a bridge unless it already exists.
18+
19+ :param interface: the interface to create the bridge on.
20+ :param net_attrs: dictionary with attributes used to create the bridge.
21+
22+ If net_attrs is set, it will add the net_attrs['gateway'] to the bridge
23+ using net_attrs['broadcast'] and net_attrs['cidr']. It will also add
24+ the ip_v6 address specified in net_attrs['cidr_v6'] if use_ipv6 is set.
25+
26+ The code will attempt to move any ips that already exist on the interface
27+ onto the bridge and reset the default gateway if necessary.
28+ """
29 if not _device_exists(bridge):
30 LOG.debug(_("Starting Bridge interface for %s"), interface)
31 _execute("sudo brctl addbr %s" % bridge)
32 _execute("sudo brctl setfd %s 0" % bridge)
33 # _execute("sudo brctl setageing %s 10" % bridge)
34 _execute("sudo brctl stp %s off" % bridge)
35- if interface:
36- _execute("sudo brctl addif %s %s" % (bridge, interface))
37+ _execute("sudo ip link set %s up" % bridge)
38 if net_attrs:
39- _execute("sudo ip addr add %s/%s dev %s broadcast %s" % \
40- (net_attrs['gateway'],
41- net_attrs['netmask'],
42- bridge,
43- net_attrs['broadcast']))
44+ # NOTE(vish): The ip for dnsmasq has to be the first address on the
45+ # bridge for it to respond to reqests properly
46+ suffix = net_attrs['cidr'].rpartition('/')[2]
47+ out, err = _execute("sudo ip addr add %s/%s brd %s dev %s" %
48+ (net_attrs['gateway'],
49+ suffix,
50+ net_attrs['broadcast'],
51+ bridge),
52+ check_exit_code=False)
53+ if err and err != "RTNETLINK answers: File exists\n":
54+ raise exception.Error("Failed to add ip: %s" % err)
55 if(FLAGS.use_ipv6):
56 _execute("sudo ip -f inet6 addr change %s dev %s" %
57 (net_attrs['cidr_v6'], bridge))
58- _execute("sudo ip link set %s up" % bridge)
59- else:
60- _execute("sudo ip link set %s up" % bridge)
61+ # NOTE(vish): If the public interface is the same as the
62+ # bridge, then the bridge has to be in promiscuous
63+ # to forward packets properly.
64+ if(FLAGS.public_interface == bridge):
65+ _execute("sudo ip link set dev %s promisc on" % bridge)
66+ if interface:
67+ # NOTE(vish): This will break if there is already an ip on the
68+ # interface, so we move any ips to the bridge
69+ gateway = None
70+ out, err = _execute("sudo route -n")
71+ for line in out.split("\n"):
72+ fields = line.split()
73+ if fields and fields[0] == "0.0.0.0" and fields[-1] == interface:
74+ gateway = fields[1]
75+ out, err = _execute("sudo ip addr show dev %s scope global" %
76+ interface)
77+ for line in out.split("\n"):
78+ fields = line.split()
79+ if fields and fields[0] == "inet":
80+ params = ' '.join(fields[1:-1])
81+ _execute("sudo ip addr del %s dev %s" % (params, fields[-1]))
82+ _execute("sudo ip addr add %s dev %s" % (params, bridge))
83+ if gateway:
84+ _execute("sudo route add 0.0.0.0 gw %s" % gateway)
85+ out, err = _execute("sudo brctl addif %s %s" %
86+ (bridge, interface),
87+ check_exit_code=False)
88+
89+ if (err and err != "device %s is already a member of a bridge; can't "
90+ "enslave it to bridge %s.\n" % (interface, bridge)):
91+ raise exception.Error("Failed to add interface: %s" % err)
92+
93 if FLAGS.use_nova_chains:
94 (out, err) = _execute("sudo iptables -N nova_forward",
95 check_exit_code=False)