Part of the patch set that enables VM's to use libvirts bridge type.

Fixes bug 1078210

The bridge will be created by Nova and not by the agent. This is the first
part for the blueprint vif-plugin-improvements

This patch supports Nova managing bridges too.

In addition to this it cleans gateway code no longer used.

Change-Id: Ia621ba5edd12d8eb7ea412a2993fea43189bd511
This commit is contained in:
Gary Kotton
2012-10-25 03:22:03 +00:00
parent 6830ff4d94
commit f9c1e087dd
2 changed files with 100 additions and 67 deletions

View File

@@ -47,7 +47,6 @@ from quantum.plugins.linuxbridge.common import constants as lconst
LOG = logging.getLogger(__name__) LOG = logging.getLogger(__name__)
BRIDGE_NAME_PREFIX = "brq" BRIDGE_NAME_PREFIX = "brq"
GATEWAY_INTERFACE_PREFIX = "gw-"
TAP_INTERFACE_PREFIX = "tap" TAP_INTERFACE_PREFIX = "tap"
BRIDGE_FS = "/sys/devices/virtual/net/" BRIDGE_FS = "/sys/devices/virtual/net/"
BRIDGE_NAME_PLACEHOLDER = "bridge_name" BRIDGE_NAME_PLACEHOLDER = "bridge_name"
@@ -141,12 +140,6 @@ class LinuxBridge:
except RuntimeError: except RuntimeError:
return self._get_prefixed_ip_link_devices(TAP_INTERFACE_PREFIX) return self._get_prefixed_ip_link_devices(TAP_INTERFACE_PREFIX)
def get_all_gateway_devices(self):
try:
return self._get_prefixed_tap_devices(GATEWAY_INTERFACE_PREFIX)
except RuntimeError:
return self._get_prefixed_ip_link_devices(GATEWAY_INTERFACE_PREFIX)
def get_bridge_for_tap_device(self, tap_device_name): def get_bridge_for_tap_device(self, tap_device_name):
bridges = self.get_all_quantum_bridges() bridges = self.get_all_quantum_bridges()
for bridge in bridges: for bridge in bridges:
@@ -275,72 +268,64 @@ class LinuxBridge:
bridge_name, e) bridge_name, e)
return return
def ensure_physical_in_bridge(self, network_id,
physical_network,
vlan_id):
physical_interface = self.interface_mappings.get(physical_network)
if not physical_interface:
LOG.error("No mapping for physical network %s" %
physical_network)
return False
if int(vlan_id) == lconst.FLAT_VLAN_ID:
self.ensure_flat_bridge(network_id, physical_interface)
else:
self.ensure_vlan_bridge(network_id, physical_interface,
vlan_id)
return True
def add_tap_interface(self, network_id, physical_network, vlan_id, def add_tap_interface(self, network_id, physical_network, vlan_id,
tap_device_name): tap_device_name):
""" """
If a VIF has been plugged into a network, this function will If a VIF has been plugged into a network, this function will
add the corresponding tap device to the relevant bridge add the corresponding tap device to the relevant bridge
""" """
if not tap_device_name:
return False
if not self.device_exists(tap_device_name): if not self.device_exists(tap_device_name):
LOG.debug("Tap device: %s does not exist on this host, skipped" % LOG.debug(_("Tap device: %s does not exist on "
tap_device_name) "this host, skipped" % tap_device_name))
return False return False
current_bridge_name = self.get_bridge_for_tap_device(tap_device_name)
bridge_name = self.get_bridge_name(network_id) bridge_name = self.get_bridge_name(network_id)
if bridge_name == current_bridge_name:
return False
LOG.debug("Adding device %s to bridge %s" % (tap_device_name,
bridge_name))
if current_bridge_name:
if utils.execute(['brctl', 'delif', current_bridge_name,
tap_device_name], root_helper=self.root_helper):
return False
if int(vlan_id) == lconst.LOCAL_VLAN_ID: if int(vlan_id) == lconst.LOCAL_VLAN_ID:
self.ensure_local_bridge(network_id) self.ensure_local_bridge(network_id)
else: else:
physical_interface = self.interface_mappings.get(physical_network) result = self.ensure_physical_in_bridge(network_id,
if not physical_interface: physical_network,
LOG.error("No mapping for physical network %s" % vlan_id)
physical_network) if not result:
return False return False
if int(vlan_id) == lconst.FLAT_VLAN_ID: # Check if device needs to be added to bridge
self.ensure_flat_bridge(network_id, physical_interface) tap_device_in_bridge = self.get_bridge_for_tap_device(tap_device_name)
else: if not tap_device_in_bridge:
self.ensure_vlan_bridge(network_id, physical_interface, msg = _("Adding device %(tap_device_name)s to bridge "
vlan_id) "%(bridge_name)s") % locals()
LOG.debug(msg)
if utils.execute(['brctl', 'addif', bridge_name, tap_device_name], if utils.execute(['brctl', 'addif', bridge_name, tap_device_name],
root_helper=self.root_helper): root_helper=self.root_helper):
return False return False
else:
LOG.debug("Done adding device %s to bridge %s" % (tap_device_name, msg = _("%(tap_device_name)s already exists on bridge "
bridge_name)) "%(bridge_name)s") % locals()
LOG.debug(msg)
return True return True
def add_interface(self, network_id, physical_network, vlan_id, def add_interface(self, network_id, physical_network, vlan_id,
interface_id): port_id):
if not interface_id: tap_device_name = self.get_tap_device_name(port_id)
""" return self.add_tap_interface(network_id,
Since the VIF id is null, no VIF is plugged into this port physical_network, vlan_id,
no more processing is required tap_device_name)
"""
return False
if interface_id.startswith(GATEWAY_INTERFACE_PREFIX):
return self.add_tap_interface(network_id,
physical_network, vlan_id,
interface_id)
else:
tap_device_name = self.get_tap_device_name(interface_id)
return self.add_tap_interface(network_id,
physical_network, vlan_id,
tap_device_name)
def delete_vlan_bridge(self, bridge_name): def delete_vlan_bridge(self, bridge_name):
if self.device_exists(bridge_name): if self.device_exists(bridge_name):
@@ -487,12 +472,6 @@ class LinuxBridgeQuantumAgentRPC:
def setup_linux_bridge(self, interface_mappings): def setup_linux_bridge(self, interface_mappings):
self.linux_br = LinuxBridge(interface_mappings, self.root_helper) self.linux_br = LinuxBridge(interface_mappings, self.root_helper)
def process_port_binding(self, network_id, interface_id,
physical_network, vlan_id):
return self.linux_br.add_interface(network_id,
physical_network, vlan_id,
interface_id)
def remove_port_binding(self, network_id, interface_id): def remove_port_binding(self, network_id, interface_id):
bridge_name = self.linux_br.get_bridge_name(network_id) bridge_name = self.linux_br.get_bridge_name(network_id)
tap_device_name = self.linux_br.get_tap_device_name(interface_id) tap_device_name = self.linux_br.get_tap_device_name(interface_id)
@@ -535,7 +514,7 @@ class LinuxBridgeQuantumAgentRPC:
def treat_devices_added(self, devices): def treat_devices_added(self, devices):
resync = False resync = False
for device in devices: for device in devices:
LOG.info("Port %s added", device) LOG.debug("Port %s added", device)
try: try:
details = self.plugin_rpc.get_device_details(self.context, details = self.plugin_rpc.get_device_details(self.context,
device, device,
@@ -548,15 +527,15 @@ class LinuxBridgeQuantumAgentRPC:
LOG.info("Port %s updated. Details: %s", device, details) LOG.info("Port %s updated. Details: %s", device, details)
if details['admin_state_up']: if details['admin_state_up']:
# create the networking for the port # create the networking for the port
self.process_port_binding(details['network_id'], self.linux_br.add_interface(details['network_id'],
details['port_id'], details['physical_network'],
details['physical_network'], details['vlan_id'],
details['vlan_id']) details['port_id'])
else: else:
self.remove_port_binding(details['network_id'], self.remove_port_binding(details['network_id'],
details['port_id']) details['port_id'])
else: else:
LOG.debug("Device %s not defined on plugin", device) LOG.info("Device %s not defined on plugin", device)
return resync return resync
def treat_devices_removed(self, devices): def treat_devices_removed(self, devices):

View File

@@ -0,0 +1,54 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright (c) 2012 OpenStack, LLC.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import mock
import unittest2 as unittest
from quantum.openstack.common import cfg
from quantum.plugins.linuxbridge.agent import linuxbridge_quantum_agent
from quantum.plugins.linuxbridge.common import config
from quantum.plugins.linuxbridge.common import constants as lconst
class TestLinuxBridge(unittest.TestCase):
def setUp(self):
self.addCleanup(cfg.CONF.reset)
interface_mappings = {'physnet1': 'eth1'}
root_helper = cfg.CONF.AGENT.root_helper
self.linux_bridge = linuxbridge_quantum_agent.LinuxBridge(
interface_mappings, root_helper)
def test_ensure_physical_in_bridge_invalid(self):
result = self.linux_bridge.ensure_physical_in_bridge('network_id',
'physnetx',
7)
self.assertFalse(result)
def test_ensure_physical_in_bridge_flat(self):
with mock.patch.object(self.linux_bridge,
'ensure_flat_bridge') as flat_bridge_func:
result = self.linux_bridge.ensure_physical_in_bridge(
'network_id', 'physnet1', lconst.FLAT_VLAN_ID)
self.assertTrue(flat_bridge_func.called)
def test_ensure_physical_in_bridge_vlan(self):
with mock.patch.object(self.linux_bridge,
'ensure_vlan_bridge') as vlan_bridge_func:
result = self.linux_bridge.ensure_physical_in_bridge(
'network_id', 'physnet1', 7)
self.assertTrue(vlan_bridge_func.called)