diff options
author | Vishvananda Ishaya <vishvananda@gmail.com> | 2011-02-08 19:09:42 +0000 |
---|---|---|
committer | Tarmac <> | 2011-02-08 19:09:42 +0000 |
commit | 7c78d71eba66b64f2a2cac0309dcd01f2acf8b4d (patch) | |
tree | 670cb65da6324b3bf3a66fb03a7d2356afff4875 | |
parent | 035136525ef7944d3da4dcf8a4b0d28840bdfae3 (diff) | |
parent | 6f30cff7374e91c2920759e13971c0149d96d821 (diff) | |
download | nova-7c78d71eba66b64f2a2cac0309dcd01f2acf8b4d.tar.gz nova-7c78d71eba66b64f2a2cac0309dcd01f2acf8b4d.tar.xz nova-7c78d71eba66b64f2a2cac0309dcd01f2acf8b4d.zip |
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.
-rw-r--r-- | nova/network/linux_net.py | 68 |
1 files changed, 57 insertions, 11 deletions
diff --git a/nova/network/linux_net.py b/nova/network/linux_net.py index b740d0423..df54606db 100644 --- a/nova/network/linux_net.py +++ b/nova/network/linux_net.py @@ -20,6 +20,7 @@ Implements vlans, bridges, and iptables rules using linux utilities. import os from nova import db +from nova import exception from nova import flags from nova import log as logging from nova import utils @@ -185,27 +186,72 @@ def ensure_vlan(vlan_num): def ensure_bridge(bridge, interface, net_attrs=None): - """Create a bridge unless it already exists""" + """Create a bridge unless it already exists. + + :param interface: the interface to create the bridge on. + :param net_attrs: dictionary with attributes used to create the bridge. + + If net_attrs is set, it will add the net_attrs['gateway'] to the bridge + using net_attrs['broadcast'] and net_attrs['cidr']. It will also add + the ip_v6 address specified in net_attrs['cidr_v6'] if use_ipv6 is set. + + The code will attempt to move any ips that already exist on the interface + onto the bridge and reset the default gateway if necessary. + """ if not _device_exists(bridge): LOG.debug(_("Starting Bridge interface for %s"), interface) _execute("sudo brctl addbr %s" % bridge) _execute("sudo brctl setfd %s 0" % bridge) # _execute("sudo brctl setageing %s 10" % bridge) _execute("sudo brctl stp %s off" % bridge) - if interface: - _execute("sudo brctl addif %s %s" % (bridge, interface)) + _execute("sudo ip link set %s up" % bridge) if net_attrs: - _execute("sudo ip addr add %s/%s dev %s broadcast %s" % \ - (net_attrs['gateway'], - net_attrs['netmask'], - bridge, - net_attrs['broadcast'])) + # NOTE(vish): The ip for dnsmasq has to be the first address on the + # bridge for it to respond to reqests properly + suffix = net_attrs['cidr'].rpartition('/')[2] + out, err = _execute("sudo ip addr add %s/%s brd %s dev %s" % + (net_attrs['gateway'], + suffix, + net_attrs['broadcast'], + bridge), + check_exit_code=False) + if err and err != "RTNETLINK answers: File exists\n": + raise exception.Error("Failed to add ip: %s" % err) if(FLAGS.use_ipv6): _execute("sudo ip -f inet6 addr change %s dev %s" % (net_attrs['cidr_v6'], bridge)) - _execute("sudo ip link set %s up" % bridge) - else: - _execute("sudo ip link set %s up" % bridge) + # NOTE(vish): If the public interface is the same as the + # bridge, then the bridge has to be in promiscuous + # to forward packets properly. + if(FLAGS.public_interface == bridge): + _execute("sudo ip link set dev %s promisc on" % bridge) + if interface: + # NOTE(vish): This will break if there is already an ip on the + # interface, so we move any ips to the bridge + gateway = None + out, err = _execute("sudo route -n") + for line in out.split("\n"): + fields = line.split() + if fields and fields[0] == "0.0.0.0" and fields[-1] == interface: + gateway = fields[1] + out, err = _execute("sudo ip addr show dev %s scope global" % + interface) + for line in out.split("\n"): + fields = line.split() + if fields and fields[0] == "inet": + params = ' '.join(fields[1:-1]) + _execute("sudo ip addr del %s dev %s" % (params, fields[-1])) + _execute("sudo ip addr add %s dev %s" % (params, bridge)) + if gateway: + _execute("sudo route add 0.0.0.0 gw %s" % gateway) + out, err = _execute("sudo brctl addif %s %s" % + (bridge, interface), + check_exit_code=False) + + if (err and err != "device %s is already a member of a bridge; can't " + "enslave it to bridge %s.\n" % (interface, bridge)): + raise exception.Error("Failed to add interface: %s" % err) + if FLAGS.use_nova_chains: (out, err) = _execute("sudo iptables -N nova_forward", check_exit_code=False) |