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

bugs 985470 and 985646

Change-Id: Ia7174c80a0760d27fe36fb6e7764e3abe32ae8a6
This commit is contained in:
Gary Kotton 2012-04-24 02:02:03 -04:00
parent b226e0c7e9
commit ba72f9c735
6 changed files with 385 additions and 292 deletions

View File

@ -16,12 +16,14 @@ host = <hostname_or_IP_address_of_Quantum_server>
port = 3306
[LINUX_BRIDGE]
#this is the interface connected to the switch on your Quantum network
# This is the interface connected to the switch on your Quantum network
physical_interface = eth1
[AGENT]
#agent's polling interval in seconds
# Agent's polling interval in seconds
polling_interval = 2
# Agent's database reconnection interval in seconds - in event connectivity is lost
reconnect_interval = 2
# Change to "sudo quantum-rootwrap" to limit commands that can be run
# as root.
root_helper = sudo

View File

@ -32,6 +32,10 @@ integration-bridge = br-int
# local-ip = 10.0.0.3
[AGENT]
# Agent's polling interval in seconds
polling_interval = 2
# Agent's database reconnection interval in seconds - in event connectivity is lost
reconnect_interval = 2
# Change to "sudo quantum-rootwrap" to limit commands that can be run
# as root.
root_helper = sudo

View File

@ -21,21 +21,22 @@
# Based on the structure of the OpenVSwitch agent in the
# Quantum OpenVSwitch Plugin.
# @author: Sumit Naiksatam, Cisco Systems, Inc.
#
from optparse import OptionParser
from subprocess import *
import ConfigParser
import logging as LOG
import MySQLdb
import logging
from optparse import OptionParser
import os
import shlex
import signal
import sqlite3
import subprocess
import sys
import time
from sqlalchemy.ext.sqlsoup import SqlSoup
logging.basicConfig()
LOG = logging.getLogger(__name__)
BRIDGE_NAME_PREFIX = "brq"
GATEWAY_INTERFACE_PREFIX = "gw-"
@ -50,7 +51,9 @@ VLAN_BINDINGS = "vlan_bindings"
PORT_BINDINGS = "port_bindings"
OP_STATUS_UP = "UP"
OP_STATUS_DOWN = "DOWN"
DB_CONNECTION = None
# Default inteval values
DEFAULT_POLLING_INTERVAL = 2
DEFAULT_RECONNECT_INTERVAL = 2
class LinuxBridge:
@ -62,7 +65,7 @@ class LinuxBridge:
def run_cmd(self, args):
cmd = shlex.split(self.root_helper) + args
LOG.debug("Running command: " + " ".join(cmd))
p = Popen(cmd, stdout=PIPE)
p = subprocess.Popen(cmd, stdout=subprocess.PIPE)
retval = p.communicate()[0]
if p.returncode == -(signal.SIGALRM):
LOG.debug("Timeout running command: " + " ".join(cmd))
@ -81,7 +84,7 @@ class LinuxBridge:
def get_bridge_name(self, network_id):
if not network_id:
LOG.warning("Invalid Network ID, will lead to incorrect bridge" \
"name")
"name")
bridge_name = self.br_name_prefix + network_id[0:11]
return bridge_name
@ -95,7 +98,7 @@ class LinuxBridge:
def get_tap_device_name(self, interface_id):
if not interface_id:
LOG.warning("Invalid Interface ID, will lead to incorrect " \
"tap device name")
"tap device name")
tap_device_name = TAP_INTERFACE_PREFIX + interface_id[0:11]
return tap_device_name
@ -109,9 +112,8 @@ class LinuxBridge:
def get_interfaces_on_bridge(self, bridge_name):
if self.device_exists(bridge_name):
bridge_interface_path = \
BRIDGE_INTERFACES_FS.replace(BRIDGE_NAME_PLACEHOLDER,
bridge_name)
bridge_interface_path = BRIDGE_INTERFACES_FS.replace(
BRIDGE_NAME_PLACEHOLDER, bridge_name)
return os.listdir(bridge_interface_path)
def get_all_tap_devices(self):
@ -149,9 +151,8 @@ class LinuxBridge:
if not device_name:
return False
else:
bridge_port_path = \
BRIDGE_PORT_FS_FOR_DEVICE.replace(DEVICE_NAME_PLACEHOLDER,
device_name)
bridge_port_path = BRIDGE_PORT_FS_FOR_DEVICE.replace(
DEVICE_NAME_PLACEHOLDER, device_name)
return os.path.exists(bridge_port_path)
def ensure_vlan_bridge(self, network_id, vlan_id):
@ -183,7 +184,7 @@ class LinuxBridge:
"""
if not self.device_exists(bridge_name):
LOG.debug("Starting bridge %s for subinterface %s" % (bridge_name,
interface))
interface))
if self.run_cmd(['brctl', 'addbr', bridge_name]):
return
if self.run_cmd(['brctl', 'setfd', bridge_name, str(0)]):
@ -210,8 +211,7 @@ class LinuxBridge:
tap_device_name)
return False
current_bridge_name = \
self.get_bridge_for_tap_device(tap_device_name)
current_bridge_name = self.get_bridge_for_tap_device(tap_device_name)
bridge_name = self.get_bridge_name(network_id)
if bridge_name == current_bridge_name:
return False
@ -237,12 +237,10 @@ class LinuxBridge:
"""
return False
if interface_id.startswith(GATEWAY_INTERFACE_PREFIX):
return self.add_tap_interface(network_id, vlan_id,
interface_id)
return self.add_tap_interface(network_id, vlan_id, interface_id)
else:
tap_device_name = self.get_tap_device_name(interface_id)
return self.add_tap_interface(network_id, vlan_id,
tap_device_name)
return self.add_tap_interface(network_id, vlan_id, tap_device_name)
def delete_vlan_bridge(self, bridge_name):
if self.device_exists(bridge_name):
@ -266,15 +264,15 @@ class LinuxBridge:
if self.device_exists(bridge_name):
if not self.is_device_on_bridge(interface_name):
return True
LOG.debug("Removing device %s from bridge %s" % \
LOG.debug("Removing device %s from bridge %s" %
(interface_name, bridge_name))
if self.run_cmd(['brctl', 'delif', bridge_name, interface_name]):
return False
LOG.debug("Done removing device %s from bridge %s" % \
LOG.debug("Done removing device %s from bridge %s" %
(interface_name, bridge_name))
return True
else:
LOG.debug("Cannot remove device %s, bridge %s does not exist" % \
LOG.debug("Cannot remove device %s, bridge %s does not exist" %
(interface_name, bridge_name))
return False
@ -291,10 +289,12 @@ class LinuxBridge:
class LinuxBridgeQuantumAgent:
def __init__(self, br_name_prefix, physical_interface, polling_interval,
root_helper):
self.polling_interval = int(polling_interval)
reconnect_interval, root_helper):
self.polling_interval = polling_interval
self.reconnect_interval = reconnect_interval
self.root_helper = root_helper
self.setup_linux_bridge(br_name_prefix, physical_interface)
self.db_connected = False
def setup_linux_bridge(self, br_name_prefix, physical_interface):
self.linux_br = LinuxBridge(br_name_prefix, physical_interface,
@ -327,16 +327,16 @@ class LinuxBridgeQuantumAgent:
LOG.debug("plugged tap device names %s" % plugged_tap_device_names)
for tap_device in self.linux_br.get_all_tap_devices():
if tap_device not in plugged_tap_device_names:
current_bridge_name = \
self.linux_br.get_bridge_for_tap_device(tap_device)
current_bridge_name = (
self.linux_br.get_bridge_for_tap_device(tap_device))
if current_bridge_name:
self.linux_br.remove_interface(current_bridge_name,
tap_device)
for gw_device in self.linux_br.get_all_gateway_devices():
if gw_device not in plugged_gateway_device_names:
current_bridge_name = \
self.linux_br.get_bridge_for_tap_device(gw_device)
current_bridge_name = (
self.linux_br.get_bridge_for_tap_device(gw_device))
if current_bridge_name:
self.linux_br.remove_interface(current_bridge_name,
gw_device)
@ -353,42 +353,53 @@ class LinuxBridgeQuantumAgent:
if bridge not in current_quantum_bridge_names:
self.linux_br.delete_vlan_bridge(bridge)
def manage_networks_on_host(self, conn, old_vlan_bindings,
def manage_networks_on_host(self, db,
old_vlan_bindings,
old_port_bindings):
if DB_CONNECTION != 'sqlite':
cursor = MySQLdb.cursors.DictCursor(conn)
else:
cursor = conn.cursor()
cursor.execute("SELECT * FROM vlan_bindings")
rows = cursor.fetchall()
cursor.close()
vlan_bindings = {}
try:
vlan_binds = db.vlan_bindings.all()
except Exception as e:
LOG.info("Unable to get vlan bindings! Exception: %s" % e)
self.db_connected = False
return {VLAN_BINDINGS: {},
PORT_BINDINGS: []}
vlans_string = ""
for row in rows:
vlan_bindings[row['network_id']] = row
vlans_string = "%s %s" % (vlans_string, row)
for bind in vlan_binds:
entry = {'network_id': bind.network_id, 'vlan_id': bind.vlan_id}
vlan_bindings[bind.network_id] = entry
vlans_string = "%s %s" % (vlans_string, entry)
port_bindings = []
try:
port_binds = db.ports.all()
except Exception as e:
LOG.info("Unable to get port bindings! Exception: %s" % e)
self.db_connected = False
return {VLAN_BINDINGS: {},
PORT_BINDINGS: []}
all_bindings = {}
for bind in port_binds:
all_bindings[bind.uuid] = bind
entry = {'network_id': bind.network_id, 'state': bind.state,
'op_status': bind.op_status, 'uuid': bind.uuid,
'interface_id': bind.interface_id}
if bind.state == 'ACTIVE':
port_bindings.append(entry)
plugged_interfaces = []
cursor = MySQLdb.cursors.DictCursor(conn)
cursor.execute("SELECT * FROM ports where state = 'ACTIVE'")
port_bindings = cursor.fetchall()
cursor.close()
ports_string = ""
for pb in port_bindings:
ports_string = "%s %s" % (ports_string, pb)
if pb['interface_id']:
vlan_id = \
str(vlan_bindings[pb['network_id']]['vlan_id'])
vlan_id = str(vlan_bindings[pb['network_id']]['vlan_id'])
if self.process_port_binding(pb['uuid'],
pb['network_id'],
pb['interface_id'],
vlan_id):
cursor = MySQLdb.cursors.DictCursor(conn)
sql = PORT_OPSTATUS_UPDATESQL % (pb['uuid'],
OP_STATUS_UP)
cursor.execute(sql)
cursor.close()
all_bindings[pb['uuid']].op_status = OP_STATUS_UP
plugged_interfaces.append(pb['interface_id'])
if old_port_bindings != port_bindings:
@ -401,16 +412,30 @@ class LinuxBridgeQuantumAgent:
self.process_deleted_networks(vlan_bindings)
conn.commit()
try:
db.commit()
except Exception as e:
LOG.info("Unable to update database! Exception: %s" % e)
db.rollback()
vlan_bindings = {}
port_bindings = []
return {VLAN_BINDINGS: vlan_bindings,
PORT_BINDINGS: port_bindings}
def daemon_loop(self, conn):
def daemon_loop(self, db_connection_url):
old_vlan_bindings = {}
old_port_bindings = {}
old_port_bindings = []
self.db_connected = False
while True:
bindings = self.manage_networks_on_host(conn,
if not self.db_connected:
time.sleep(self.reconnect_interval)
db = SqlSoup(db_connection_url)
self.db_connected = True
LOG.info("Connecting to database \"%s\" on %s" %
(db.engine.url.database, db.engine.url.host))
bindings = self.manage_networks_on_host(db,
old_vlan_bindings,
old_port_bindings)
old_vlan_bindings = bindings[VLAN_BINDINGS]
@ -427,9 +452,9 @@ def main():
options, args = parser.parse_args()
if options.verbose:
LOG.basicConfig(level=LOG.DEBUG)
LOG.setLevel(logging.DEBUG)
else:
LOG.basicConfig(level=LOG.WARN)
LOG.setLevel(logging.WARNING)
if len(args) != 1:
parser.print_help()
@ -437,22 +462,28 @@ def main():
config_file = args[0]
config = ConfigParser.ConfigParser()
conn = None
try:
fh = open(config_file)
fh.close()
config.read(config_file)
br_name_prefix = BRIDGE_NAME_PREFIX
physical_interface = config.get("LINUX_BRIDGE", "physical_interface")
polling_interval = config.get("AGENT", "polling_interval")
if config.has_option("AGENT", "polling_interval"):
polling_interval = config.getint("AGENT", "polling_interval")
else:
polling_interval = DEFAULT_POLLING_INTERVAL
LOG.info("Polling interval not defined. Using default.")
if config.has_option("AGENT", "reconnect_interval"):
reconnect_interval = config.getint("AGENT", "reconnect_interval")
else:
reconnect_interval = DEFAULT_RECONNECT_INTERVAL
LOG.info("Reconnect interval not defined. Using default.")
root_helper = config.get("AGENT", "root_helper")
'Establish database connection and load models'
global DB_CONNECTION
DB_CONNECTION = config.get("DATABASE", "connection")
if DB_CONNECTION == 'sqlite':
connection = config.get("DATABASE", "connection")
if connection == 'sqlite':
LOG.info("Connecting to sqlite DB")
conn = sqlite3.connect(":memory:")
conn.row_factory = sqlite3.Row
db_connection_url = "sqlite:///:memory:"
else:
db_name = config.get("DATABASE", "name")
db_user = config.get("DATABASE", "user")
@ -460,21 +491,18 @@ def main():
db_host = config.get("DATABASE", "host")
db_port = int(config.get("DATABASE", "port"))
LOG.info("Connecting to database %s on %s" % (db_name, db_host))
conn = MySQLdb.connect(host=db_host, user=db_user, port=db_port,
passwd=db_pass, db=db_name)
except Exception, e:
LOG.error("Unable to parse config file \"%s\": \nException%s"
% (config_file, str(e)))
db_connection_url = ("%s://%s:%s@%s:%d/%s" %
(connection, db_user, db_pass, db_host, db_port, db_name))
except Exception as e:
LOG.error("Unable to parse config file \"%s\": \nException %s" %
(config_file, str(e)))
sys.exit(1)
try:
plugin = LinuxBridgeQuantumAgent(br_name_prefix, physical_interface,
polling_interval, root_helper)
LOG.info("Agent initialized successfully, now running...")
plugin.daemon_loop(conn)
finally:
if conn:
conn.close()
plugin = LinuxBridgeQuantumAgent(br_name_prefix, physical_interface,
polling_interval, reconnect_interval,
root_helper)
LOG.info("Agent initialized successfully, now running... ")
plugin.daemon_loop(db_connection_url)
sys.exit(0)

View File

@ -15,43 +15,43 @@
# under the License.
#
# @author: Shweta Padubidri, Cisco Systems, Inc.
#
import ConfigParser
import logging as LOG
import unittest
import sys
import logging
import os
import shlex
import signal
from subprocess import *
import subprocess
import sys
import unittest
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
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.getLogger(__name__)
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'):
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_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)
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)
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]
@ -61,15 +61,15 @@ class LinuxBridgeAgentTest(unittest.TestCase):
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)
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)
bridge_name, interface)
self.delete_device(interface)
self.delete_bridge(bridge_name)
self.tearDownUnplugInterface(tenant_id, new_network[lconst.NET_ID],
@ -78,18 +78,18 @@ class LinuxBridgeAgentTest(unittest.TestCase):
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'):
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_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)
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)
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]
@ -99,15 +99,15 @@ class LinuxBridgeAgentTest(unittest.TestCase):
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)
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)
bridge_name, interface)
self.delete_device(interface)
self.delete_bridge(bridge_name)
self.tearDownUnplugInterface(tenant_id, new_network[lconst.NET_ID],
@ -121,13 +121,13 @@ class LinuxBridgeAgentTest(unittest.TestCase):
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_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)
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)
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]
@ -137,19 +137,19 @@ class LinuxBridgeAgentTest(unittest.TestCase):
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)
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)
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)
bridge_name, interface)
self.delete_device(interface)
self.delete_device(device_name)
self.delete_bridge(bridge_name)
@ -159,34 +159,35 @@ class LinuxBridgeAgentTest(unittest.TestCase):
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'):
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_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)
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)
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()
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)
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)
bridge_name, interface)
self.delete_device(interface)
self.delete_bridge(bridge_name)
self.tearDownUnplugInterface(tenant_id, new_network[lconst.NET_ID],
@ -195,26 +196,26 @@ class LinuxBridgeAgentTest(unittest.TestCase):
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'):
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_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)
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)
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))
new_network[lconst.NET_ID], str(vlan_id))
self._linuxbridge_quantum_agent.linux_br.delete_vlan_bridge(
bridge_name)
bridge_name)
self.assertEquals(self.device_exists(vlan_subinterface), False)
self.assertEquals(self.device_exists(bridge_name), False)
@ -224,26 +225,26 @@ class LinuxBridgeAgentTest(unittest.TestCase):
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'):
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_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)
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)
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_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))
new_network[lconst.NET_ID], str(vlan_id))
self.tearDownUnplugInterface(tenant_id, new_network[lconst.NET_ID],
new_port[lconst.PORT_ID])
vlan_bindings = {}
@ -254,18 +255,18 @@ class LinuxBridgeAgentTest(unittest.TestCase):
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'):
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_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)
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)
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]
@ -275,43 +276,43 @@ class LinuxBridgeAgentTest(unittest.TestCase):
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))
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)
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)
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)
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])
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'):
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_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)
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)
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]
@ -321,27 +322,27 @@ class LinuxBridgeAgentTest(unittest.TestCase):
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)
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)
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)
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])
new_port[lconst.PORT_ID])
LOG.debug("test_test_process_unplugged_gw_interface -END")
@ -402,15 +403,15 @@ class LinuxBridgeAgentTest(unittest.TestCase):
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)
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)
p = subprocess.Popen(cmd, stdout=subprocess.PIPE)
retval = p.communicate()[0]
if p.returncode == -(signal.SIGALRM):
LOG.debug("Timeout running command: " + " ".join(args))

View File

@ -20,16 +20,18 @@
# @author: Dave Lapsley, Nicira Networks, Inc.
import ConfigParser
import logging as LOG
import logging
from optparse import OptionParser
import shlex
import signal
import subprocess
import sys
import time
import signal
from optparse import OptionParser
from sqlalchemy.ext.sqlsoup import SqlSoup
from subprocess import *
logging.basicConfig()
LOG = logging.getLogger(__name__)
# Global constants.
OP_STATUS_UP = "UP"
@ -38,7 +40,9 @@ OP_STATUS_DOWN = "DOWN"
# A placeholder for dead vlans.
DEAD_VLAN_TAG = "4095"
REFRESH_INTERVAL = 2
# Default interval values
DEFAULT_POLLING_INTERVAL = 2
DEFAULT_RECONNECT_INTERVAL = 2
# A class to represent a VIF (i.e., a port that has 'iface-id' and 'vif-mac'
@ -52,9 +56,10 @@ class VifPort:
self.switch = switch
def __str__(self):
return "iface-id=" + self.vif_id + ", vif_mac=" + \
self.vif_mac + ", port_name=" + self.port_name + \
", ofport=" + self.ofport + ", bridge name = " + self.switch.br_name
return ("iface-id=" + self.vif_id + ", vif_mac=" +
self.vif_mac + ", port_name=" + self.port_name +
", ofport=" + self.ofport + ", bridge name = " +
self.switch.br_name)
class OVSBridge:
@ -65,7 +70,7 @@ class OVSBridge:
def run_cmd(self, args):
cmd = shlex.split(self.root_helper) + args
LOG.debug("## running command: " + " ".join(cmd))
p = Popen(cmd, stdout=PIPE)
p = subprocess.Popen(cmd, stdout=subprocess.PIPE)
retval = p.communicate()[0]
if p.returncode == -(signal.SIGALRM):
LOG.debug("## timeout running command: " + " ".join(cmd))
@ -127,17 +132,17 @@ class OVSBridge:
def add_tunnel_port(self, port_name, remote_ip):
self.run_vsctl(["add-port", self.br_name, port_name])
self.set_db_attribute("Interface", port_name, "type", "gre")
self.set_db_attribute("Interface", port_name, "options", "remote_ip=" +
remote_ip)
self.set_db_attribute("Interface", port_name, "options", "in_key=flow")
self.set_db_attribute("Interface", port_name, "options",
"out_key=flow")
self.set_db_attribute("Interface", port_name, "options:remote_ip",
remote_ip)
self.set_db_attribute("Interface", port_name, "options:in_key", "flow")
self.set_db_attribute("Interface", port_name, "options:out_key",
"flow")
return self.get_port_ofport(port_name)
def add_patch_port(self, local_name, remote_name):
self.run_vsctl(["add-port", self.br_name, local_name])
self.set_db_attribute("Interface", local_name, "type", "patch")
self.set_db_attribute("Interface", local_name, "options", "peer=" +
self.set_db_attribute("Interface", local_name, "options:peer",
remote_name)
return self.get_port_ofport(local_name)
@ -166,12 +171,13 @@ class OVSBridge:
return self.db_get_map("Interface", port_name, "statistics")
def get_xapi_iface_id(self, xs_vif_uuid):
return self.run_cmd(
["xe",
"vif-param-get",
"param-name=other-config",
"param-key=nicira-iface-id",
"uuid=%s" % xs_vif_uuid]).strip()
return self.run_cmd([
"xe",
"vif-param-get",
"param-name=other-config",
"param-key=nicira-iface-id",
"uuid=%s" % xs_vif_uuid,
]).strip()
# returns a VIF object for each VIF port
def get_vif_ports(self):
@ -184,8 +190,8 @@ class OVSBridge:
p = VifPort(name, ofport, external_ids["iface-id"],
external_ids["attached-mac"], self)
edge_ports.append(p)
elif "xs-vif-uuid" in external_ids and \
"attached-mac" in external_ids:
elif ("xs-vif-uuid" in external_ids and
"attached-mac" in external_ids):
# if this is a xenserver and iface-id is not automatically
# synced to OVS from XAPI, we grab it from XAPI directly
iface_id = self.get_xapi_iface_id(external_ids["xs-vif-uuid"])
@ -210,13 +216,16 @@ class LocalVLANMapping:
class OVSQuantumAgent(object):
def __init__(self, integ_br, root_helper):
def __init__(self, integ_br, root_helper,
polling_interval, reconnect_interval):
self.root_helper = root_helper
self.setup_integration_br(integ_br)
self.polling_interval = polling_interval
self.reconnect_interval = reconnect_interval
def port_bound(self, port, vlan_id):
self.int_br.set_db_attribute("Port", port.port_name, "tag",
str(vlan_id))
self.int_br.set_db_attribute("Port", port.port_name,
"tag", str(vlan_id))
self.int_br.delete_flows(match="in_port=%s" % port.ofport)
def port_unbound(self, port, still_exists):
@ -229,26 +238,39 @@ class OVSQuantumAgent(object):
# switch all traffic using L2 learning
self.int_br.add_flow(priority=1, actions="normal")
def daemon_loop(self, db):
def daemon_loop(self, db_connection_url):
self.local_vlan_map = {}
old_local_bindings = {}
old_vif_ports = {}
db_connected = False
while True:
if not db_connected:
time.sleep(self.reconnect_interval)
db = SqlSoup(db_connection_url)
db_connected = True
LOG.info("Connecting to database \"%s\" on %s" %
(db.engine.url.database, db.engine.url.host))
all_bindings = {}
try:
ports = db.ports.all()
except:
ports = []
except Exception as e:
LOG.info("Unable to get port bindings! Exception: %s" % e)
db_connected = False
continue
for port in ports:
all_bindings[port.interface_id] = port
vlan_bindings = {}
try:
vlan_binds = db.vlan_bindings.all()
except:
vlan_binds = []
except Exception as e:
LOG.info("Unable to get vlan bindings! Exception: %s" % e)
db_connected = False
continue
for bind in vlan_binds:
vlan_bindings[bind.network_id] = bind.vlan_id
@ -265,7 +287,8 @@ class OVSQuantumAgent(object):
self.int_br.set_db_attribute("Port", p.port_name, "tag",
DEAD_VLAN_TAG)
self.int_br.add_flow(priority=2,
match="in_port=%s" % p.ofport, actions="drop")
match="in_port=%s" % p.ofport,
actions="drop")
old_b = old_local_bindings.get(p.vif_id, None)
new_b = new_local_bindings.get(p.vif_id, None)
@ -285,8 +308,9 @@ class OVSQuantumAgent(object):
self.port_bound(p, vlan_id)
if p.vif_id in all_bindings:
all_bindings[p.vif_id].op_status = OP_STATUS_UP
LOG.info("Adding binding to net-id = %s " \
"for %s on vlan %s" % (new_b, str(p), vlan_id))
LOG.info(("Adding binding to net-id = %s "
"for %s on vlan %s") %
(new_b, str(p), vlan_id))
for vif_id in old_vif_ports:
if vif_id not in new_vif_ports:
@ -299,8 +323,15 @@ class OVSQuantumAgent(object):
old_vif_ports = new_vif_ports
old_local_bindings = new_local_bindings
db.commit()
time.sleep(REFRESH_INTERVAL)
try:
db.commit()
except Exception as e:
LOG.info("Unable to commit to database! Exception: %s" % e)
db.rollback()
old_local_bindings = {}
old_vif_ports = {}
time.sleep(self.polling_interval)
class OVSQuantumTunnelAgent(object):
@ -328,7 +359,7 @@ class OVSQuantumTunnelAgent(object):
MAX_VLAN_TAG = 4094
def __init__(self, integ_br, tun_br, remote_ip_file, local_ip,
root_helper):
root_helper, polling_interval, reconnect_interval):
'''Constructor.
:param integ_br: name of the integration bridge.
@ -342,6 +373,9 @@ class OVSQuantumTunnelAgent(object):
self.setup_integration_br(integ_br)
self.local_vlan_map = {}
self.setup_tunnel_br(tun_br, remote_ip_file, local_ip)
self.db_connected = False
self.polling_interval = polling_interval
self.reconnect_interval = reconnect_interval
def provision_local_vlan(self, net_uuid, lsw_id):
'''Provisions a local VLAN.
@ -356,13 +390,13 @@ class OVSQuantumTunnelAgent(object):
# outbound
self.tun_br.add_flow(priority=4, match="in_port=%s,dl_vlan=%s" %
(self.patch_int_ofport, lvid),
(self.patch_int_ofport, lvid),
actions="set_tunnel:%s,normal" % (lsw_id))
# inbound
self.tun_br.add_flow(priority=3, match="tun_id=%s" % lsw_id,
actions="mod_vlan_vid:%s,output:%s" % (lvid,
self.patch_int_ofport))
actions="mod_vlan_vid:%s,output:%s" %
(lvid, self.patch_int_ofport))
def reclaim_local_vlan(self, net_uuid, lvm):
'''Reclaim a local VLAN.
@ -401,8 +435,8 @@ class OVSQuantumTunnelAgent(object):
:param port: a VifPort object.
:param net_uuid: the net_uuid this port is associated with.'''
if net_uuid not in self.local_vlan_map:
LOG.info('port_unbound() net_uuid %s not in local_vlan_map'
% net_uuid)
LOG.info('port_unbound() net_uuid %s not in local_vlan_map' %
net_uuid)
return
lvm = self.local_vlan_map[net_uuid]
@ -459,9 +493,9 @@ class OVSQuantumTunnelAgent(object):
tunnel_ips = (x for x in clean_ips if x != local_ip and x)
for i, remote_ip in enumerate(tunnel_ips):
self.tun_br.add_tunnel_port("gre-" + str(i), remote_ip)
except Exception, e:
LOG.error("Error configuring tunnels: '%s' %s"
% (remote_ip_file, str(e)))
except Exception as e:
LOG.error("Error configuring tunnels: '%s' %s" %
(remote_ip_file, str(e)))
raise
self.tun_br.remove_all_flows()
@ -478,8 +512,10 @@ class OVSQuantumTunnelAgent(object):
ports = []
try:
ports = db.ports.all()
except Exception, e:
LOG.info("Exception accessing db.ports: %s" % e)
except Exceptioni as e:
LOG.info("Unable to get port bindings! Exception: %s" % e)
self.db_connected = False
return {}
return dict([(port.interface_id, port) for port in ports])
@ -493,25 +529,39 @@ class OVSQuantumTunnelAgent(object):
lsw_id_binds = []
try:
lsw_id_binds.extend(db.vlan_bindings.all())
except Exception, e:
LOG.info("Exception accessing db.vlan_bindings: %s" % e)
except Exception as e:
LOG.info("Unable to get vlan bindings! Exception: %s" % e)
self.db_connected = False
return {}
return dict([(bind.network_id, bind.vlan_id)
for bind in lsw_id_binds])
def daemon_loop(self, db):
def daemon_loop(self, db_connection_url):
'''Main processing loop (not currently used).
:param db: reference to database layer.
:param options: database information - in the event need to reconnect
'''
old_local_bindings = {}
old_vif_ports = {}
self.db_connected = False
while True:
if not self.db_connected:
time.sleep(self.reconnect_interval)
db = SqlSoup(db_connection_url)
self.db_connected = True
LOG.info("Connecting to database \"%s\" on %s" %
(db.engine.url.database, db.engine.url.host))
# Get bindings from db.
all_bindings = self.get_db_port_bindings(db)
if not self.db_connected:
continue
all_bindings_vif_port_ids = set(all_bindings.keys())
lsw_id_bindings = self.get_db_vlan_bindings(db)
if not self.db_connected:
continue
# Get bindings from OVS bridge.
vif_ports = self.int_br.get_vif_ports()
@ -525,11 +575,11 @@ class OVSQuantumTunnelAgent(object):
new_local_bindings_ids = all_bindings_vif_port_ids.intersection(
new_vif_ports_ids)
new_local_bindings = dict([(p, all_bindings.get(p))
for p in new_vif_ports_ids])
new_bindings = set((p, old_local_bindings.get(p),
new_local_bindings.get(p)) for p in new_vif_ports_ids)
changed_bindings = set([b for b in new_bindings
if b[2] != b[1]])
for p in new_vif_ports_ids])
new_bindings = set(
(p, old_local_bindings.get(p),
new_local_bindings.get(p)) for p in new_vif_ports_ids)
changed_bindings = set([b for b in new_bindings if b[2] != b[1]])
LOG.debug('all_bindings: %s' % all_bindings)
LOG.debug('lsw_id_bindings: %s' % lsw_id_bindings)
@ -563,7 +613,7 @@ class OVSQuantumTunnelAgent(object):
new_net_uuid = new_port.network_id
if new_net_uuid not in lsw_id_bindings:
LOG.warn("No ls-id binding found for net-id '%s'" %
new_net_uuid)
new_net_uuid)
continue
lsw_id = lsw_id_bindings[new_net_uuid]
@ -572,10 +622,10 @@ class OVSQuantumTunnelAgent(object):
LOG.info("Port " + str(p) + " on net-id = "
+ new_net_uuid + " bound to " +
str(self.local_vlan_map[new_net_uuid]))
except Exception, e:
except Exception as e:
LOG.info("Unable to bind Port " + str(p) +
" on netid = " + new_net_uuid + " to "
+ str(self.local_vlan_map[new_net_uuid]))
" on netid = " + new_net_uuid + " to "
+ str(self.local_vlan_map[new_net_uuid]))
for vif_id in disappeared_vif_ports_ids:
LOG.info("Port Disappeared: " + vif_id)
@ -590,7 +640,7 @@ class OVSQuantumTunnelAgent(object):
old_vif_ports = new_vif_ports
old_local_bindings = new_local_bindings
time.sleep(REFRESH_INTERVAL)
time.sleep(self.polling_interval)
def main():
@ -602,9 +652,9 @@ def main():
options, args = parser.parse_args()
if options.verbose:
LOG.basicConfig(level=LOG.DEBUG)
LOG.setLevel(logging.DEBUG)
else:
LOG.basicConfig(level=LOG.WARN)
LOG.setLevel(logging.WARNING)
if len(args) != 1:
parser.print_help()
@ -614,16 +664,16 @@ def main():
config = ConfigParser.ConfigParser()
try:
config.read(config_file)
except Exception, e:
LOG.error("Unable to parse config file \"%s\": %s"
% (config_file, str(e)))
except Exception as e:
LOG.error("Unable to parse config file \"%s\": %s" %
(config_file, str(e)))
raise e
# Determine which agent type to use.
enable_tunneling = False
try:
enable_tunneling = config.getboolean("OVS", "enable-tunneling")
except Exception, e:
except Exception as e:
pass
# Get common parameters.
@ -636,11 +686,21 @@ def main():
if not len(db_connection_url):
raise Exception('Empty db_connection_url in configuration file.')
if config.has_option("AGENT", "polling_interval"):
polling_interval = config.getint("AGENT", "polling_interval")
else:
polling_interval = DEFAULT_POLLING_INTERVAL
LOG.info("Polling interval not defined. Using default.")
if config.has_option("AGENT", "reconnect_interval"):
reconnect_interval = config.getint("AGENT", "reconnect_interval")
else:
reconnect_interval = DEFAULT_RECONNECT_INTERVAL
LOG.info("Reconnect interval not defined. Using default.")
root_helper = config.get("AGENT", "root_helper")
except Exception, e:
LOG.error("Error parsing common params in config_file: '%s': %s"
% (config_file, str(e)))
except Exception as e:
LOG.error("Error parsing common params in config_file: '%s': %s" %
(config_file, str(e)))
sys.exit(1)
if enable_tunneling:
@ -661,24 +721,22 @@ def main():
local_ip = config.get("OVS", "local-ip")
if not len(local_ip):
raise Exception('Empty local-ip in configuration file.')
except Exception, e:
LOG.error("Error parsing tunnel params in config_file: '%s': %s"
% (config_file, str(e)))
except Exception as e:
LOG.error("Error parsing tunnel params in config_file: '%s': %s" %
(config_file, str(e)))
sys.exit(1)
plugin = OVSQuantumTunnelAgent(integ_br, tun_br, remote_ip_file,
local_ip, root_helper)
local_ip, root_helper,
polling_interval, reconnect_interval)
else:
# Get parameters for OVSQuantumAgent.
plugin = OVSQuantumAgent(integ_br, root_helper)
plugin = OVSQuantumAgent(integ_br, root_helper,
polling_interval, reconnect_interval)
# Start everything.
options = {"sql_connection": db_connection_url}
db = SqlSoup(options["sql_connection"])
LOG.info("Connecting to database \"%s\" on %s" %
(db.engine.url.database, db.engine.url.host))
plugin.daemon_loop(db)
plugin.daemon_loop(db_connection_url)
sys.exit(0)

View File

@ -89,7 +89,7 @@ class TunnelTest(unittest.TestCase):
self.TUN_BRIDGE,
REMOTE_IP_FILE,
'10.0.0.1',
'sudo')
'sudo', 2, 2)
self.mox.VerifyAll()
def testProvisionLocalVlan(self):
@ -109,7 +109,7 @@ class TunnelTest(unittest.TestCase):
self.TUN_BRIDGE,
REMOTE_IP_FILE,
'10.0.0.1',
'sudo')
'sudo', 2, 2)
a.available_local_vlans = set([LV_ID])
a.provision_local_vlan(NET_UUID, LS_ID)
self.mox.VerifyAll()
@ -126,7 +126,7 @@ class TunnelTest(unittest.TestCase):
self.TUN_BRIDGE,
REMOTE_IP_FILE,
'10.0.0.1',
'sudo')
'sudo', 2, 2)
a.available_local_vlans = set()
a.local_vlan_map[NET_UUID] = LVM
a.reclaim_local_vlan(NET_UUID, LVM)
@ -143,7 +143,7 @@ class TunnelTest(unittest.TestCase):
self.TUN_BRIDGE,
REMOTE_IP_FILE,
'10.0.0.1',
'sudo')
'sudo', 2, 2)
a.local_vlan_map[NET_UUID] = LVM
a.port_bound(VIF_PORT, NET_UUID, LS_ID)
self.mox.VerifyAll()
@ -154,7 +154,7 @@ class TunnelTest(unittest.TestCase):
self.TUN_BRIDGE,
REMOTE_IP_FILE,
'10.0.0.1',
'sudo')
'sudo', 2, 2)
a.available_local_vlans = set([LV_ID])
a.local_vlan_map[NET_UUID] = LVM
a.port_unbound(VIF_PORT, NET_UUID)
@ -173,7 +173,7 @@ class TunnelTest(unittest.TestCase):
self.TUN_BRIDGE,
REMOTE_IP_FILE,
'10.0.0.1',
'sudo')
'sudo', 2, 2)
a.available_local_vlans = set([LV_ID])
a.local_vlan_map[NET_UUID] = LVM
a.port_dead(VIF_PORT)
@ -196,7 +196,7 @@ class TunnelTest(unittest.TestCase):
self.TUN_BRIDGE,
REMOTE_IP_FILE,
'10.0.0.1',
'sudo')
'sudo', 2, 2)
all_bindings = a.get_db_port_bindings(db)
lsw_id_bindings = a.get_db_vlan_bindings(db)