# vim: tabstop=4 shiftwidth=4 softtabstop=4 # # Copyright 2012 Cisco Systems, Inc. All rights reserved. # # 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. # # @author: Shweta Padubidri, Cisco Systems, Inc. import ConfigParser import logging import os import shlex import signal import subprocess import sys import unittest import quantum.db.api as db from quantum.plugins.linuxbridge.agent import ( linuxbridge_quantum_agent as linux_agent, ) from quantum.plugins.linuxbridge.common import constants as lconst from quantum.plugins.linuxbridge.db import l2network_db as cdb from quantum.plugins.linuxbridge import LinuxBridgePlugin LOG = logging.getLogger(__name__) class LinuxBridgeAgentTest(unittest.TestCase): def test_add_gateway_interface(self, tenant_id="test_tenant", network_name="test_network", interface_id='fe701ddf-26a2-42ea-' 'b9e6-7313d1c522cc', mac_address='fe:16:3e:51:60:dd'): LOG.debug("test_tap_gateway_interface - START") new_network = ( self._linuxbridge_plugin.create_network(tenant_id, network_name)) new_port = self._linuxbridge_plugin.create_port( tenant_id, new_network[lconst.NET_ID], lconst.PORT_UP) self._linuxbridge_plugin.plug_interface( tenant_id, new_network[lconst.NET_ID], new_port[lconst.PORT_ID], interface_id) bridge_name = self.br_name_prefix + new_network[lconst.NET_ID][0:11] self.create_bridge(bridge_name) device_name = self.gw_name_prefix + new_network[lconst.NET_ID][0:11] self.create_device(device_name, mac_address) vlan_bind = cdb.get_vlan_binding(new_network[lconst.NET_ID]) vlan_id = vlan_bind[lconst.VLANID] self._linuxbridge_quantum_agent.process_port_binding( new_network[lconst.NET_ID], device_name, str(vlan_id)) list_interface = (self._linuxbridge_quantum_agent.linux_br. get_interfaces_on_bridge(bridge_name)) self.assertTrue(device_name in list_interface) for interface in list_interface: self._linuxbridge_quantum_agent.linux_br.remove_interface( bridge_name, interface) self.delete_device(interface) self.delete_bridge(bridge_name) self.tearDownUnplugInterface(tenant_id, new_network[lconst.NET_ID], new_port[lconst.PORT_ID]) LOG.debug("test_add_gateway_interface - END") def test_add_tap_interface(self, tenant_id="test_tenant", network_name="test_network", interface_id='fe701ddf-26a2-42ea-' 'b9e6-7313d1c522cc', mac_address='fe:16:3e:51:60:dd'): LOG.debug("test_add_tap_interface - START") new_network = ( self._linuxbridge_plugin.create_network(tenant_id, network_name)) new_port = self._linuxbridge_plugin.create_port( tenant_id, new_network[lconst.NET_ID], lconst.PORT_UP) self._linuxbridge_plugin.plug_interface( tenant_id, new_network[lconst.NET_ID], new_port[lconst.PORT_ID], interface_id) bridge_name = self.br_name_prefix + new_network[lconst.NET_ID][0:11] self.create_bridge(bridge_name) device_name = self.tap_name_prefix + interface_id[0:11] self.create_device(device_name, mac_address) vlan_bind = cdb.get_vlan_binding(new_network[lconst.NET_ID]) vlan_id = vlan_bind[lconst.VLANID] self._linuxbridge_quantum_agent.process_port_binding( new_network[lconst.NET_ID], interface_id, str(vlan_id)) list_interface = (self._linuxbridge_quantum_agent.linux_br. get_interfaces_on_bridge(bridge_name)) self.assertTrue(device_name in list_interface) for interface in list_interface: self._linuxbridge_quantum_agent.linux_br.remove_interface( bridge_name, interface) self.delete_device(interface) self.delete_bridge(bridge_name) self.tearDownUnplugInterface(tenant_id, new_network[lconst.NET_ID], new_port[lconst.PORT_ID]) LOG.debug("test_add_tap_interface -END") def test_remove_interface(self, tenant_id="test_tenant", network_name="test_network", interface_id='fe701ddf-26a2-42ea-' 'b9e6-7313d1c522cc', mac_address='fe:16:3e:51:60:dd'): LOG.debug("test_remove_interface - START") new_network = ( self._linuxbridge_plugin.create_network(tenant_id, network_name)) new_port = self._linuxbridge_plugin.create_port( tenant_id, new_network[lconst.NET_ID], lconst.PORT_UP) self._linuxbridge_plugin.plug_interface( tenant_id, new_network[lconst.NET_ID], new_port[lconst.PORT_ID], interface_id) bridge_name = self.br_name_prefix + new_network[lconst.NET_ID][0:11] self.create_bridge(bridge_name) device_name = self.tap_name_prefix + interface_id[0:11] self.create_device(device_name, mac_address) vlan_bind = cdb.get_vlan_binding(new_network[lconst.NET_ID]) vlan_id = vlan_bind[lconst.VLANID] self._linuxbridge_quantum_agent.process_port_binding( new_network[lconst.NET_ID], interface_id, str(vlan_id)) list_interface = (self._linuxbridge_quantum_agent.linux_br. get_interfaces_on_bridge(bridge_name)) self._linuxbridge_quantum_agent.linux_br.remove_interface(bridge_name, device_name) list_interface = (self._linuxbridge_quantum_agent.linux_br. get_interfaces_on_bridge(bridge_name)) self.assertFalse(device_name in list_interface) for interface in list_interface: self._linuxbridge_quantum_agent.linux_br.remove_interface( bridge_name, interface) self.delete_device(interface) self.delete_device(device_name) self.delete_bridge(bridge_name) self.tearDownUnplugInterface(tenant_id, new_network[lconst.NET_ID], new_port[lconst.PORT_ID]) LOG.debug("test_remove_interface -END") def test_ensure_vlan_bridge(self, tenant_id="test_tenant", network_name="test_network", interface_id='fe701ddf-26a2-42ea-' 'b9e6-7313d1c522cc'): LOG.debug("test_ensure_vlan_bridge - START") new_network = ( self._linuxbridge_plugin.create_network(tenant_id, network_name)) new_port = self._linuxbridge_plugin.create_port( tenant_id, new_network[lconst.NET_ID], lconst.PORT_UP) self._linuxbridge_plugin.plug_interface( tenant_id, new_network[lconst.NET_ID], new_port[lconst.PORT_ID], interface_id) bridge_name = self.br_name_prefix + new_network[lconst.NET_ID][0:11] vlan_bind = cdb.get_vlan_binding(new_network[lconst.NET_ID]) vlan_id = vlan_bind[lconst.VLANID] vlan_subinterface = self.physical_interface + '.' + str(vlan_id) self._linuxbridge_quantum_agent.linux_br.ensure_vlan_bridge( new_network[lconst.NET_ID], str(vlan_id)) list_quantum_bridges = (self._linuxbridge_quantum_agent.linux_br. get_all_quantum_bridges()) self.assertTrue(bridge_name in list_quantum_bridges) list_interface = (self._linuxbridge_quantum_agent.linux_br. get_interfaces_on_bridge(bridge_name)) self.assertTrue(vlan_subinterface in list_interface) for interface in list_interface: self._linuxbridge_quantum_agent.linux_br.remove_interface( bridge_name, interface) self.delete_device(interface) self.delete_bridge(bridge_name) self.tearDownUnplugInterface(tenant_id, new_network[lconst.NET_ID], new_port[lconst.PORT_ID]) LOG.debug("test_ensure_vlan_bridge -END") def test_delete_vlan_bridge(self, tenant_id="test_tenant", network_name="test_network", interface_id='fe701ddf-26a2-42ea-' 'b9e6-7313d1c522cc'): LOG.debug("test_delete_vlan_bridge - START") new_network = ( self._linuxbridge_plugin.create_network(tenant_id, network_name)) new_port = self._linuxbridge_plugin.create_port( tenant_id, new_network[lconst.NET_ID], lconst.PORT_UP) self._linuxbridge_plugin.plug_interface( tenant_id, new_network[lconst.NET_ID], new_port[lconst.PORT_ID], interface_id) bridge_name = self.br_name_prefix + new_network[lconst.NET_ID][0:11] vlan_bind = cdb.get_vlan_binding(new_network[lconst.NET_ID]) vlan_id = vlan_bind[lconst.VLANID] vlan_subinterface = self.physical_interface + '.' + str(vlan_id) self._linuxbridge_quantum_agent.linux_br.ensure_vlan_bridge( new_network[lconst.NET_ID], str(vlan_id)) self._linuxbridge_quantum_agent.linux_br.delete_vlan_bridge( bridge_name) self.assertEquals(self.device_exists(vlan_subinterface), False) self.assertEquals(self.device_exists(bridge_name), False) self.tearDownUnplugInterface(tenant_id, new_network[lconst.NET_ID], new_port[lconst.PORT_ID]) LOG.debug("test_delete_vlan_bridge - END") def test_process_deleted_networks(self, tenant_id="test_tenant", network_name="test_network", interface_id='fe701ddf-26a2-42ea-' 'b9e6-7313d1c522cc'): LOG.debug("test_delete_vlan_bridge - START") new_network = ( self._linuxbridge_plugin.create_network(tenant_id, network_name)) new_port = self._linuxbridge_plugin.create_port( tenant_id, new_network[lconst.NET_ID], lconst.PORT_UP) self._linuxbridge_plugin.plug_interface( tenant_id, new_network[lconst.NET_ID], new_port[lconst.PORT_ID], interface_id) bridge_name = self.br_name_prefix + new_network[lconst.NET_ID][0:11] vlan_bindings = {} vlan_bindings[new_network[lconst.NET_ID]] = ( cdb.get_vlan_binding(new_network[lconst.NET_ID])) vlan_id = vlan_bindings[new_network[lconst.NET_ID]][lconst.VLANID] vlan_subinterface = self.physical_interface + '.' + str(vlan_id) self._linuxbridge_quantum_agent.linux_br.ensure_vlan_bridge( new_network[lconst.NET_ID], str(vlan_id)) self.tearDownUnplugInterface(tenant_id, new_network[lconst.NET_ID], new_port[lconst.PORT_ID]) vlan_bindings = {} self._linuxbridge_quantum_agent.process_deleted_networks(vlan_bindings) self.assertEquals(self.device_exists(vlan_subinterface), False) self.assertEquals(self.device_exists(bridge_name), False) LOG.debug("test_delete_vlan_bridge - END") def test_process_unplugged_tap_interface(self, tenant_id="test_tenant", network_name="test_network", interface_id='fe701ddf-26a2-' '42ea-b9e6-' '7313d1c522cc', mac_address='fe:16:3e:51:60:dd'): LOG.debug("test_process_unplugged_tap_interface - START") new_network = ( self._linuxbridge_plugin.create_network(tenant_id, network_name)) new_port = self._linuxbridge_plugin.create_port( tenant_id, new_network[lconst.NET_ID], lconst.PORT_UP) self._linuxbridge_plugin.plug_interface( tenant_id, new_network[lconst.NET_ID], new_port[lconst.PORT_ID], interface_id) bridge_name = self.br_name_prefix + new_network[lconst.NET_ID][0:11] self.create_bridge(bridge_name) device_name = self.tap_name_prefix + interface_id[0:11] self.create_device(device_name, mac_address) vlan_bind = cdb.get_vlan_binding(new_network[lconst.NET_ID]) vlan_id = vlan_bind[lconst.VLANID] self._linuxbridge_quantum_agent.process_port_binding( new_network[lconst.NET_ID], interface_id, str(vlan_id)) list_interface = (self._linuxbridge_quantum_agent.linux_br. get_interfaces_on_bridge(bridge_name)) self._linuxbridge_plugin.unplug_interface(tenant_id, new_network[lconst.NET_ID], new_port[lconst.PORT_ID]) plugged_interface = [] self._linuxbridge_quantum_agent.process_unplugged_interfaces( plugged_interface) list_interface = (self._linuxbridge_quantum_agent.linux_br. get_interfaces_on_bridge(bridge_name)) self.assertFalse(device_name in list_interface) for interface in list_interface: self._linuxbridge_quantum_agent.linux_br.remove_interface( bridge_name, interface) self.delete_device(interface) self.delete_device(device_name) self.delete_bridge(bridge_name) self.tearDownNetworkPort(tenant_id, new_network[lconst.NET_ID], new_port[lconst.PORT_ID]) LOG.debug("test_test_process_unplugged_tap_interface -END") def test_process_unplugged_interface_empty(self, tenant_id="test_tenant", network_name="test_network"): """ test to unplug not plugged port. It should not raise exception """ LOG.debug("test_process_unplugged_interface_empty - START") new_network = ( self._linuxbridge_plugin.create_network(tenant_id, network_name)) new_port = self._linuxbridge_plugin.create_port( tenant_id, new_network[lconst.NET_ID], lconst.PORT_UP) self._linuxbridge_plugin.unplug_interface(tenant_id, new_network[lconst.NET_ID], new_port[lconst.PORT_ID]) self.tearDownNetworkPort(tenant_id, new_network[lconst.NET_ID], new_port[lconst.PORT_ID]) LOG.debug("test_process_unplugged_interface_empty -END") def test_process_unplugged_gw_interface(self, tenant_id="test_tenant", network_name="test_network", interface_id='fe701ddf-26a2-42ea-' 'b9e6-7313d1c522cc', mac_address='fe:16:3e:51:60:dd'): LOG.debug("test_process_unplugged_gw_interface - START") new_network = ( self._linuxbridge_plugin.create_network(tenant_id, network_name)) new_port = self._linuxbridge_plugin.create_port( tenant_id, new_network[lconst.NET_ID], lconst.PORT_UP) self._linuxbridge_plugin.plug_interface( tenant_id, new_network[lconst.NET_ID], new_port[lconst.PORT_ID], interface_id) bridge_name = self.br_name_prefix + new_network[lconst.NET_ID][0:11] self.create_bridge(bridge_name) device_name = self.gw_name_prefix + new_network[lconst.NET_ID][0:11] self.create_device(device_name, mac_address) vlan_bind = cdb.get_vlan_binding(new_network[lconst.NET_ID]) vlan_id = vlan_bind[lconst.VLANID] self._linuxbridge_quantum_agent.process_port_binding( new_network[lconst.NET_ID], interface_id, str(vlan_id)) list_interface = (self._linuxbridge_quantum_agent.linux_br. get_interfaces_on_bridge(bridge_name)) self._linuxbridge_plugin.unplug_interface(tenant_id, new_network[lconst.NET_ID], new_port[lconst.PORT_ID]) plugged_interface = [] self._linuxbridge_quantum_agent.process_unplugged_interfaces( plugged_interface) list_interface = (self._linuxbridge_quantum_agent.linux_br. get_interfaces_on_bridge(bridge_name)) self.assertFalse(device_name in list_interface) for interface in list_interface: self._linuxbridge_quantum_agent.linux_br.remove_interface( bridge_name, interface) self.delete_device(interface) self.delete_device(device_name) self.delete_bridge(bridge_name) self.tearDownNetworkPort(tenant_id, new_network[lconst.NET_ID], new_port[lconst.PORT_ID]) LOG.debug("test_test_process_unplugged_gw_interface -END") def create_bridge(self, bridge_name): """ Create a bridge """ self.run_cmd(['brctl', 'addbr', bridge_name]) self.run_cmd(['brctl', 'setfd', bridge_name, str(0)]) self.run_cmd(['brctl', 'stp', bridge_name, 'off']) self.run_cmd(['ip', 'link', 'set', bridge_name, 'up']) def delete_bridge(self, bridge_name): """ Delete a bridge """ self.run_cmd(['ip', 'link', 'set', bridge_name, 'down']) self.run_cmd(['brctl', 'delbr', bridge_name]) def create_device(self, dev, mac_address): self.run_cmd(['ip', 'tuntap', 'add', dev, 'mode', 'tap']) self.run_cmd(['ip', 'link', 'set', dev, "address", mac_address]) self.run_cmd(['ip', 'link', 'set', dev, 'up']) def delete_device(self, dev): self.run_cmd(['ip', 'link', 'delete', dev]) def setUp(self): """ Set up function """ self.tenant_id = "test_tenant" self.network_name = "test_network" self.config_file = os.path.join(os.path.dirname(__file__), os.pardir, os.pardir, os.pardir, os.pardir, os.pardir, "etc", "quantum", "plugins", "linuxbridge", "linuxbridge_conf.ini") config = ConfigParser.ConfigParser() self.br_name_prefix = "brq" self.gw_name_prefix = "gw-" self.tap_name_prefix = "tap" self.v2 = True self.db_connection = 'sqlite://' self._linuxbridge_plugin = LinuxBridgePlugin.LinuxBridgePlugin() try: fh = open(self.config_file) fh.close() config.read(self.config_file) self.physical_interface = config.get("LINUX_BRIDGE", "physical_interface") self.polling_interval = config.get("AGENT", "polling_interval") self.reconnect_interval = config.get("DATABASE", "reconnect_interval") self.root_helper = config.get("AGENT", "root_helper") except Exception, e: LOG.error("Unable to parse config file \"%s\": \nException%s" % (self.config_file, str(e))) sys.exit(1) self._linuxbridge = linux_agent.LinuxBridge(self.br_name_prefix, self.physical_interface, self.root_helper) plugin = linux_agent.LinuxBridgeQuantumAgentDB( self.br_name_prefix, self.physical_interface, self.polling_interval, self.reconnect_interval, self.root_helper, self.v2, self.db_connection) self._linuxbridge_quantum_agent = plugin def run_cmd(self, args): cmd = shlex.split(self.root_helper) + args LOG.debug("Running command: " + " ".join(cmd)) p = subprocess.Popen(cmd, stdout=subprocess.PIPE) retval = p.communicate()[0] if p.returncode == -(signal.SIGALRM): LOG.debug("Timeout running command: " + " ".join(args)) if retval: LOG.debug("Command returned: %s" % retval) return retval def device_exists(self, device): """Check if ethernet device exists.""" retval = self.run_cmd(['ip', 'link', 'show', 'dev', device]) if retval: return True else: return False """ Clean up functions after the tests """ def tearDown(self): """Clear the test environment(Clean the Database)""" db.clear_db() def tearDownNetwork(self, tenant_id, network_dict_id): """ Tear down the Network """ self._linuxbridge_plugin.delete_network(tenant_id, network_dict_id) def tearDownUnplugInterface(self, tenant_id, network_dict_id, port_id): """ Tear down the port """ self._linuxbridge_plugin.unplug_interface(tenant_id, network_dict_id, port_id) self.tearDownNetworkPort(tenant_id, network_dict_id, port_id) def tearDownNetworkPort(self, tenant_id, network_dict_id, port_id): """ Tear down Network Port """ self._linuxbridge_plugin.delete_port(tenant_id, network_dict_id, port_id) self.tearDownNetwork(tenant_id, network_dict_id)