Files
vmware-nsx/quantum/plugins/linuxbridge/tests/unit/_test_linuxbridgeAgent.py
Gary Kotton be45b704ac blueprint agent-db-ha
bug 985470
bug 985646

The fixes enable the OVS and linuxbridge agenets to "keep alive" when the host running the server/plugin is down.

Fixes after comments. Better logging

Fixes after comments - added reconnect interval + cleanup

Fixes after comments - simplify code + ovs intervals moved to configuration file

Fixes after comments - move int conversion to configuration

Fixes after comments - if one of the polling interval or reconnect interval are not
defined in the relevant ini files then a default value is used.

Fixes after comments and merges with HACKING.rst fixes

Fixes after port binding comments

Fixes after comments from gongysh

Fixes after comments - align comments in agent ini files

Fixes - revert some code

Change-Id: I9194f142478b130e8ef198b019539357a9916d7f
2012-05-03 14:45:16 -04:00

458 lines
20 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 import LinuxBridgePlugin
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
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_port[lconst.PORT_ID], 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_port[lconst.PORT_ID], 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_port[lconst.PORT_ID], 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_port[lconst.PORT_ID], 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_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_port[lconst.PORT_ID], 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._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.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)
self._linuxbridge_quantum_agent = linux_agent.LinuxBridgeQuantumAgent(
self.br_name_prefix,
self.physical_interface,
self.polling_interval,
self.root_helper)
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)