Use vif_type='tap' for LinuxBridge for consistency

This adjusts the Linux Bridge mechanism driver to return
the 'tap' VIF type to Nova so the Linux Bridge agent is
responsible for plugging all ports into bridges.

This completely eliminates all of the work Nova was doing with
regard to bridges so we now have one consistent path how ports
(both compute and dhcp/l3) are connected into Linux Bridge
networks. Both Nova and the DHCP/L3 agents will now just create
a device and leave wiring to bridges to be completely the
responsibility of the L2 agent.

In order to preserve backwards compatibiliy with Ocata agents
that won't touch compute ports, we only report back vif_type='tap'
if the agent has a report_state value showing that it wires compute
ports.

This will also solve a longstanding bug (bug #1105488) that
is preventing Nova instances from using custom bridge mappings
since the agent will be guaranteed to be responsible for the
connection to the bridge.

Depends-On: I075595158d8f3b5a6811c4794aa7b91912940db5

Related-Bug: #1617447
Closes-Bug: #1673910
Closes-Bug: #1105488
Change-Id: I23c5faaeab69aede1fd038a36f4a0b8f928498ce
This commit is contained in:
Kevin Benton 2017-03-17 14:56:36 -07:00
parent 196e685278
commit 1b987be2b5
5 changed files with 40 additions and 31 deletions

View File

@ -489,25 +489,15 @@ class LinuxBridgeManager(amb.CommonAgentManagerBase):
# inherit from the bridge its plugged into, which will be 1500
# at the time. See bug/1684326 for details.
self._set_tap_mtu(tap_device_name, mtu)
# Avoid messing with plugging devices into a bridge that the agent
# does not own
if not device_owner.startswith(constants.DEVICE_OWNER_COMPUTE_PREFIX):
# Check if device needs to be added to bridge
if not bridge_lib.BridgeDevice.get_interface_bridge(
tap_device_name):
data = {'tap_device_name': tap_device_name,
'bridge_name': bridge_name}
LOG.debug("Adding device %(tap_device_name)s to bridge "
"%(bridge_name)s", data)
if bridge_lib.BridgeDevice(bridge_name).addif(tap_device_name):
return False
else:
# Check if device needs to be added to bridge
if not bridge_lib.BridgeDevice.get_interface_bridge(
tap_device_name):
data = {'tap_device_name': tap_device_name,
'device_owner': device_owner,
'bridge_name': bridge_name}
LOG.debug("Skip adding device %(tap_device_name)s to "
"%(bridge_name)s. It is owned by %(device_owner)s and "
"thus added elsewhere.", data)
LOG.debug("Adding device %(tap_device_name)s to bridge "
"%(bridge_name)s", data)
if bridge_lib.BridgeDevice(bridge_name).addif(tap_device_name):
return False
return True
def _set_tap_mtu(self, tap_device_name, mtu):
@ -744,8 +734,8 @@ class LinuxBridgeManager(amb.CommonAgentManagerBase):
def get_agent_configurations(self):
configurations = {'bridge_mappings': self.bridge_mappings,
'interface_mappings': self.interface_mappings
}
'interface_mappings': self.interface_mappings,
'wires_compute_ports': True}
if self.vxlan_mode != lconst.VXLAN_NONE:
configurations['tunneling_ip'] = self.local_ip
configurations['tunnel_types'] = [p_const.TYPE_VXLAN]

View File

@ -36,7 +36,7 @@ class LinuxbridgeMechanismDriver(mech_agent.SimpleAgentMechanismDriverBase):
sg_enabled = securitygroups_rpc.is_firewall_enabled()
super(LinuxbridgeMechanismDriver, self).__init__(
constants.AGENT_TYPE_LINUXBRIDGE,
portbindings.VIF_TYPE_BRIDGE,
'tap', # const merge in I718f514e1673544114063af5e1a14ec29bf3274d
{portbindings.CAP_PORT_FILTER: sg_enabled})
lb_qos_driver.register()
@ -50,6 +50,13 @@ class LinuxbridgeMechanismDriver(mech_agent.SimpleAgentMechanismDriverBase):
**agent['configurations'].get('bridge_mappings', {}))
return mappings
def get_vif_type(self, context, agent, segment):
# TODO(kevinbenton): remove this function after we no longer support
# Ocata agents
if not agent['configurations'].get('wires_compute_ports'):
return portbindings.VIF_TYPE_BRIDGE
return self.vif_type
def check_vlan_transparency(self, context):
"""Linuxbridge driver vlan transparency support."""
return True

View File

@ -488,15 +488,6 @@ class TestLinuxBridgeManager(base.BaseTestCase):
p_const.TYPE_VLAN, "physnet1", None, "tap1",
"foo", None)
def test_add_tap_interface_owner_compute(self):
with mock.patch.object(ip_lib, "device_exists"):
with mock.patch.object(self.lbm, "ensure_local_bridge"):
self.assertTrue(self.lbm.add_tap_interface("123",
p_const.TYPE_LOCAL,
"physnet1", None,
"tap1",
"compute:1", None))
def _test_add_tap_interface(self, dev_owner_prefix):
with mock.patch.object(ip_lib, "device_exists") as de_fn:
de_fn.return_value = False

View File

@ -13,6 +13,8 @@
# License for the specific language governing permissions and limitations
# under the License.
import copy
from neutron_lib.api.definitions import portbindings
from neutron_lib import constants
@ -22,13 +24,14 @@ from neutron.tests.unit.plugins.ml2 import _test_mech_agent as base
class LinuxbridgeMechanismBaseTestCase(base.AgentMechanismBaseTestCase):
VIF_TYPE = portbindings.VIF_TYPE_BRIDGE
VIF_TYPE = 'tap'
CAP_PORT_FILTER = True
AGENT_TYPE = constants.AGENT_TYPE_LINUXBRIDGE
GOOD_MAPPINGS = {'fake_physical_network': 'fake_interface'}
GOOD_TUNNEL_TYPES = ['gre', 'vxlan']
GOOD_CONFIGS = {'interface_mappings': GOOD_MAPPINGS,
GOOD_CONFIGS = {'wires_compute_ports': True,
'interface_mappings': GOOD_MAPPINGS,
'tunnel_types': GOOD_TUNNEL_TYPES}
BAD_MAPPINGS = {'wrong_physical_network': 'wrong_interface'}
@ -78,3 +81,11 @@ class LinuxbridgeMechanismVlanTestCase(LinuxbridgeMechanismBaseTestCase,
class LinuxbridgeMechanismGreTestCase(LinuxbridgeMechanismBaseTestCase,
base.AgentMechanismGreTestCase):
pass
class LegacyLinuxbridgeMechanismTestCase(LinuxbridgeMechanismBaseTestCase,
base.AgentMechanismVlanTestCase):
"""An old agent doesn't wire compute ports so it needs VIF_TYPE_BRIDGE."""
VIF_TYPE = portbindings.VIF_TYPE_BRIDGE
AGENTS = copy.deepcopy(LinuxbridgeMechanismBaseTestCase.AGENTS)
AGENTS[0]['configurations'].pop('wires_compute_ports')

View File

@ -0,0 +1,10 @@
---
prelude: >
The Linux Bridge driver now informs Nova to use the 'tap' interface type
to wire interfaces. This requires '/dev/net/tun' to be added to the
'cgroup_device_acl' in 'qemu.conf' before upgrading.
upgrade:
- |
The Linux Bridge driver now informs Nova to use the 'tap' interface type
to wire interfaces. This requires '/dev/net/tun' to be added to the
'cgroup_device_acl' in 'qemu.conf' before upgrading.