vmware-nsx/quantum/plugins/linuxbridge/tests/unit/_test_linuxbridgeAgent.py
Bob Kukura f97e0148c1 Add root_helper to quantum agents.
When running commands that require root privileges, the linuxbridge,
openvswitch, and ryu agent now prepend the commands with the value of
the root_helper config variable. This is set to "sudo" in the plugins'
.ini files, allowing the agent to run as a non-root user with
appropriate sudo privilidges.

If root_helper is changed to "sudo quantum-rootwrap",
then the command being run will be filtered against lists of each
agent's valid commands in quantum/rootwrap. See
http://wiki.openstack.org/Packager/Rootwrap for details.

Fixes bug 948467.

Change-Id: I549515068a4ce8ae480905ec5eaab6257445d0c3
Signed-off-by: Bob Kukura <rkukura@redhat.com>
2012-03-14 19:44:19 -04:00

457 lines
21 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 as LOG
import unittest
import sys
import os
import shlex
import signal
from subprocess import *
import quantum.plugins.linuxbridge.agent.linuxbridge_quantum_agent\
as linux_agent
from quantum.plugins.linuxbridge.common import constants as lconst
from quantum.plugins.linuxbridge import LinuxBridgePlugin
from quantum.plugins.linuxbridge.db import l2network_db as cdb
import quantum.db.api as db
LOG.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 = Popen(cmd, stdout=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)