vmware-nsx/quantum/plugins/linuxbridge/tests/unit/_test_linuxbridgeAgent.py
Gary Kotton 58d42b6558 RPC support for Linux Bridge Plugin and Agent
blueprint scalable-agent-comms

This is the first stage of the blueprint. This adds support to the linux bridge
plugin.

The development followed the design described in:
https://docs.google.com/document/d/1MbcBA2Os4b98ybdgAw2qe_68R1NG6KMh8zdZKgOlpvg/edit?pli=1

Change-Id: I4004c05a63ce49f020c2016c8763e73238b465a7
2012-08-08 10:09:47 -04:00

486 lines
22 KiB
Python

# 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)