Squashed commit of the following: commit 6c4995736a56349923d34353031eb301780fc6d2 Author: Sumit Naiksatam <snaiksat@cisco.com> Date: Sat Jan 21 22:31:09 2012 -0800 Some more explanation in the README. Changing defaults in the conf file. commit 924b118468d7bd21737e9e2cf468ff83d0a20764 Author: Shweta <shpadubi@cisco.com> Date: Sat Jan 21 20:58:39 2012 -0500 Adding Unit Tests for LinuxBridge Agent commit 12115650257483172c5e2bc889634dbdf3596d27 Author: Sumit Naiksatam <snaiksat@cisco.com> Date: Sat Jan 21 05:21:24 2012 -0800 Adding sqlite requirement Changing default mysql port number Fixing log statement commit 0ad1400e5dfc445b94e9024d92321eb3cd0588a5 Merge: 1b7ba8f9c5c2caAuthor: Sumit Naiksatam <snaiksat@cisco.com> Date: Sat Jan 21 05:12:44 2012 -0800 Merge remote branch 'upstream/master' into snaiksat/linux-bridge-plugin commit 1b7ba8f7e7b6657734b669194ddfdcfcbfc833be Author: Sumit Naiksatam <snaiksat@cisco.com> Date: Sat Jan 21 04:04:50 2012 -0800 Fixes to get the tests to run correctly. Also incorporated changes to be able to run both sqlite and mysql DBs. commit 4cead17576c293319dfdfd363dd18e81ba196b3b Author: Sumit Naiksatam <snaiksat@cisco.com> Date: Fri Jan 20 15:32:35 2012 -0800 Fixed inccorect calls to the DB commit c4f325729fbd06ee3f5d3520da4d23b2cd8c353b Author: Sumit Naiksatam <snaiksat@cisco.com> Date: Fri Jan 20 12:18:18 2012 -0800 Removing the specialized db modules (which used InnoDB engine) and instead using the Quantum DB now. Incorporated changes to setup so that the Linux Bridge plugin can be installed. Other changes to README and tests. commit b9498939d723e353808cface87f4453e33e94b41 Author: Sumit Naiksatam <snaiksat@cisco.com> Date: Mon Jan 16 20:00:14 2012 -0800 Adding unit tests commit a0ab990fdcbf67a950d08c6b5b6d20ceb850619a Merge: 60e38ccf268b5eAuthor: Sumit Naiksatam <snaiksat@cisco.com> Date: Mon Jan 16 18:02:55 2012 -0800 Merge remote branch 'upstream/master' into snaiksat/linux-bridge-plugin commit 60e38cc44886b5c8c9e47d89d8912d1dee23fbd1 Author: Sumit Naiksatam <snaiksat@cisco.com> Date: Mon Jan 16 13:44:37 2012 -0800 This contains a fix for the earlier reported issue with the DHCP failing. The gateway IP address is now applied both to the bridge, and the gateway interface. commit ffea86a3465b8a5ed93b13f818e0afaefa6787ee Author: Sumit Naiksatam <snaiksat@cisco.com> Date: Sun Jan 15 20:00:38 2012 -0800 Fixing an issue in the agent, sometimes the bridges for deleted networks were not getting cleaned up commit 87f76fc34f1c70cd82576b8698d704853c892422 Merge: c8b097a60d171eAuthor: Sumit Naiksatam <snaiksat@cisco.com> Date: Sun Jan 15 19:40:33 2012 -0800 Merge remote branch 'upstream/master' into snaiksat/linux-bridge-plugin commit c8b097abc2060b2eae01d84f9fed2c89851d93fd Author: Sumit Naiksatam <snaiksat@cisco.com> Date: Sun Jan 15 19:37:08 2012 -0800 Simplified the logic for creating the bridge on the nova network host. commit 499dbacd4c5352c5320f3b6e5e8cd7f3629dbcc8 Author: Sumit Naiksatam <snaiksat@cisco.com> Date: Fri Jan 13 16:07:53 2012 -0800 Fix for the DHCP issue, now applying Gateway IP to the bridge Also MAC address from original tap device are applied to bridge and vlan subinterface commit 6b4a2aea59702e2c12eeacc86101df9f6770d5ec Author: Sumit Naiksatam <snaiksat@cisco.com> Date: Sat Jan 7 14:29:00 2012 -0800 Optimizations for processing in the loop commit 01aa47d3572439b193077432c63bf2b85c629edb Merge: 184f5dd 05df087 Author: Sumit Naiksatam <snaiksat@cisco.com> Date: Sun Jan 1 19:04:17 2012 -0800 Changes to incorporate Operational Status Merge remote branch 'origin' into snaiksat/linux-bridge-plugin Conflicts: quantum/db/api.py commit 05df0870191fac0353fe12a33efff68ef7ed0784 Merge: 31d586b5b23b5eAuthor: Sumit Naiksatam <snaiksat@cisco.com> Date: Fri Dec 30 12:30:05 2011 -0800 Merge remote branch 'upstream/master' commit 184f5dd8b73bc51025509792c15203ee73cd015e Author: Sumit Naiksatam <snaiksat@cisco.com> Date: Mon Dec 12 02:09:12 2011 -0800 Initial checkin for Linux Bridge L2 plugin. Change-Id: I5b27538be6a768a6f7eb77409197f7d8b4bbc628
471 lines
18 KiB
Python
Executable File
471 lines
18 KiB
Python
Executable File
#!/usr/bin/env 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.
|
|
#
|
|
#
|
|
# Performs per host Linux Bridge configuration for Quantum.
|
|
# 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 os
|
|
import signal
|
|
import sqlite3
|
|
import sys
|
|
import time
|
|
|
|
|
|
BRIDGE_NAME_PREFIX = "brq"
|
|
GATEWAY_INTERFACE_PREFIX = "gw-"
|
|
TAP_INTERFACE_PREFIX = "tap"
|
|
BRIDGE_FS = "/sys/devices/virtual/net/"
|
|
BRIDGE_NAME_PLACEHOLDER = "bridge_name"
|
|
BRIDGE_INTERFACES_FS = BRIDGE_FS + BRIDGE_NAME_PLACEHOLDER + "/brif/"
|
|
PORT_OPSTATUS_UPDATESQL = "UPDATE ports SET op_status = '%s' WHERE uuid = '%s'"
|
|
DEVICE_NAME_PLACEHOLDER = "device_name"
|
|
BRIDGE_PORT_FS_FOR_DEVICE = BRIDGE_FS + DEVICE_NAME_PLACEHOLDER + "/brport"
|
|
VLAN_BINDINGS = "vlan_bindings"
|
|
PORT_BINDINGS = "port_bindings"
|
|
OP_STATUS_UP = "UP"
|
|
OP_STATUS_DOWN = "DOWN"
|
|
DB_CONNECTION = None
|
|
|
|
|
|
class LinuxBridge:
|
|
def __init__(self, br_name_prefix, physical_interface):
|
|
self.br_name_prefix = br_name_prefix
|
|
self.physical_interface = physical_interface
|
|
|
|
def run_cmd(self, args):
|
|
LOG.debug("Running command: " + " ".join(args))
|
|
p = Popen(args, 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
|
|
|
|
def get_bridge_name(self, network_id):
|
|
if not network_id:
|
|
LOG.warning("Invalid Network ID, will lead to incorrect bridge" \
|
|
"name")
|
|
bridge_name = self.br_name_prefix + network_id[0:11]
|
|
return bridge_name
|
|
|
|
def get_subinterface_name(self, vlan_id):
|
|
if not vlan_id:
|
|
LOG.warning("Invalid VLAN ID, will lead to incorrect " \
|
|
"subinterface name")
|
|
subinterface_name = '%s.%s' % (self.physical_interface, vlan_id)
|
|
return subinterface_name
|
|
|
|
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_INTERFACE_PREFIX + interface_id[0:11]
|
|
return tap_device_name
|
|
|
|
def get_all_quantum_bridges(self):
|
|
quantum_bridge_list = []
|
|
bridge_list = os.listdir(BRIDGE_FS)
|
|
for bridge in bridge_list:
|
|
if bridge.startswith(BRIDGE_NAME_PREFIX):
|
|
quantum_bridge_list.append(bridge)
|
|
return quantum_bridge_list
|
|
|
|
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)
|
|
return os.listdir(bridge_interface_path)
|
|
|
|
def get_all_tap_devices(self):
|
|
tap_devices = []
|
|
retval = self.run_cmd(['ip', 'tuntap'])
|
|
rows = retval.split('\n')
|
|
for row in rows:
|
|
split_row = row.split(':')
|
|
if split_row[0].startswith(TAP_INTERFACE_PREFIX):
|
|
tap_devices.append(split_row[0])
|
|
|
|
return tap_devices
|
|
|
|
def get_all_gateway_devices(self):
|
|
gw_devices = []
|
|
retval = self.run_cmd(['ip', 'tuntap'])
|
|
rows = retval.split('\n')
|
|
for row in rows:
|
|
split_row = row.split(':')
|
|
if split_row[0].startswith(GATEWAY_INTERFACE_PREFIX):
|
|
gw_devices.append(split_row[0])
|
|
|
|
return gw_devices
|
|
|
|
def get_bridge_for_tap_device(self, tap_device_name):
|
|
bridges = self.get_all_quantum_bridges()
|
|
for bridge in bridges:
|
|
interfaces = self.get_interfaces_on_bridge(bridge)
|
|
if tap_device_name in interfaces:
|
|
return bridge
|
|
|
|
return None
|
|
|
|
def is_device_on_bridge(self, device_name):
|
|
if not device_name:
|
|
return False
|
|
else:
|
|
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):
|
|
"""Create a vlan and bridge unless they already exist."""
|
|
interface = self.ensure_vlan(vlan_id)
|
|
bridge_name = self.get_bridge_name(network_id)
|
|
self.ensure_bridge(bridge_name, interface)
|
|
return interface
|
|
|
|
def ensure_vlan(self, vlan_id):
|
|
"""Create a vlan unless it already exists."""
|
|
interface = self.get_subinterface_name(vlan_id)
|
|
if not self.device_exists(interface):
|
|
LOG.debug("Creating subinterface %s for VLAN %s on interface %s" %
|
|
(interface, vlan_id, self.physical_interface))
|
|
if self.run_cmd(['ip', 'link', 'add', 'link',
|
|
self.physical_interface,
|
|
'name', interface, 'type', 'vlan', 'id',
|
|
vlan_id]):
|
|
return
|
|
if self.run_cmd(['ip', 'link', 'set', interface, 'up']):
|
|
return
|
|
LOG.debug("Done creating subinterface %s" % interface)
|
|
return interface
|
|
|
|
def ensure_bridge(self, bridge_name, interface):
|
|
"""
|
|
Create a bridge unless it already exists.
|
|
"""
|
|
if not self.device_exists(bridge_name):
|
|
LOG.debug("Starting bridge %s for subinterface %s" % (bridge_name,
|
|
interface))
|
|
if self.run_cmd(['brctl', 'addbr', bridge_name]):
|
|
return
|
|
if self.run_cmd(['brctl', 'setfd', bridge_name, str(0)]):
|
|
return
|
|
if self.run_cmd(['brctl', 'stp', bridge_name, 'off']):
|
|
return
|
|
if self.run_cmd(['ip', 'link', 'set', bridge_name, 'up']):
|
|
return
|
|
LOG.debug("Done starting bridge %s for subinterface %s" %
|
|
(bridge_name, interface))
|
|
|
|
self.run_cmd(['brctl', 'addif', bridge_name, interface])
|
|
|
|
def add_tap_interface(self, network_id, vlan_id, tap_device_name):
|
|
"""
|
|
If a VIF has been plugged into a network, this function will
|
|
add the corresponding tap device to the relevant bridge
|
|
"""
|
|
if not tap_device_name:
|
|
return False
|
|
|
|
if not self.device_exists(tap_device_name):
|
|
LOG.debug("Tap device: %s does not exist on this host, skipped" %
|
|
tap_device_name)
|
|
return False
|
|
|
|
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
|
|
LOG.debug("Adding device %s to bridge %s" % (tap_device_name,
|
|
bridge_name))
|
|
if current_bridge_name:
|
|
if self.run_cmd(['brctl', 'delif', current_bridge_name,
|
|
tap_device_name]):
|
|
return False
|
|
|
|
self.ensure_vlan_bridge(network_id, vlan_id)
|
|
if self.run_cmd(['brctl', 'addif', bridge_name, tap_device_name]):
|
|
return False
|
|
LOG.debug("Done adding device %s to bridge %s" % (tap_device_name,
|
|
bridge_name))
|
|
return True
|
|
|
|
def add_interface(self, network_id, vlan_id, interface_id):
|
|
if not interface_id:
|
|
"""
|
|
Since the VIF id is null, no VIF is plugged into this port
|
|
no more processing is required
|
|
"""
|
|
return False
|
|
if interface_id.startswith(GATEWAY_INTERFACE_PREFIX):
|
|
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)
|
|
|
|
def delete_vlan_bridge(self, bridge_name):
|
|
if self.device_exists(bridge_name):
|
|
interfaces_on_bridge = self.get_interfaces_on_bridge(bridge_name)
|
|
for interface in interfaces_on_bridge:
|
|
self.remove_interface(bridge_name, interface)
|
|
if interface.startswith(self.physical_interface):
|
|
self.delete_vlan(interface)
|
|
|
|
LOG.debug("Deleting bridge %s" % bridge_name)
|
|
if self.run_cmd(['ip', 'link', 'set', bridge_name, 'down']):
|
|
return
|
|
if self.run_cmd(['brctl', 'delbr', bridge_name]):
|
|
return
|
|
LOG.debug("Done deleting bridge %s" % bridge_name)
|
|
|
|
else:
|
|
LOG.error("Cannot delete bridge %s, does not exist" % bridge_name)
|
|
|
|
def remove_interface(self, bridge_name, interface_name):
|
|
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" % \
|
|
(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" % \
|
|
(interface_name, bridge_name))
|
|
return True
|
|
else:
|
|
LOG.debug("Cannot remove device %s, bridge %s does not exist" % \
|
|
(interface_name, bridge_name))
|
|
return False
|
|
|
|
def delete_vlan(self, interface):
|
|
if self.device_exists(interface):
|
|
LOG.debug("Deleting subinterface %s for vlan" % interface)
|
|
if self.run_cmd(['ip', 'link', 'set', interface, 'down']):
|
|
return
|
|
if self.run_cmd(['ip', 'link', 'delete', interface]):
|
|
return
|
|
LOG.debug("Done deleting subinterface %s" % interface)
|
|
|
|
|
|
class LinuxBridgeQuantumAgent:
|
|
|
|
def __init__(self, br_name_prefix, physical_interface, polling_interval):
|
|
self.polling_interval = int(polling_interval)
|
|
self.setup_linux_bridge(br_name_prefix, physical_interface)
|
|
|
|
def setup_linux_bridge(self, br_name_prefix, physical_interface):
|
|
self.linux_br = LinuxBridge(br_name_prefix, physical_interface)
|
|
|
|
def process_port_binding(self, port_id, network_id, interface_id,
|
|
vlan_id):
|
|
return self.linux_br.add_interface(network_id, vlan_id, interface_id)
|
|
|
|
def process_unplugged_interfaces(self, plugged_interfaces):
|
|
"""
|
|
If there are any tap devices that are not corresponding to the
|
|
list of attached VIFs, then those are corresponding to recently
|
|
unplugged VIFs, so we need to remove those tap devices from their
|
|
current bridge association
|
|
"""
|
|
plugged_tap_device_names = []
|
|
plugged_gateway_device_names = []
|
|
for interface in plugged_interfaces:
|
|
if interface.startswith(GATEWAY_INTERFACE_PREFIX):
|
|
"""
|
|
The name for the gateway devices is set by the linux net
|
|
driver, hence we use the name as is
|
|
"""
|
|
plugged_gateway_device_names.append(interface)
|
|
else:
|
|
tap_device_name = self.linux_br.get_tap_device_name(interface)
|
|
plugged_tap_device_names.append(tap_device_name)
|
|
|
|
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)
|
|
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)
|
|
if current_bridge_name:
|
|
self.linux_br.remove_interface(current_bridge_name,
|
|
gw_device)
|
|
|
|
def process_deleted_networks(self, vlan_bindings):
|
|
current_quantum_networks = vlan_bindings.keys()
|
|
current_quantum_bridge_names = []
|
|
for network in current_quantum_networks:
|
|
bridge_name = self.linux_br.get_bridge_name(network)
|
|
current_quantum_bridge_names.append(bridge_name)
|
|
|
|
quantum_bridges_on_this_host = self.linux_br.get_all_quantum_bridges()
|
|
for bridge in quantum_bridges_on_this_host:
|
|
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,
|
|
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 = {}
|
|
vlans_string = ""
|
|
for row in rows:
|
|
vlan_bindings[row['network_id']] = row
|
|
vlans_string = "%s %s" % (vlans_string, row)
|
|
|
|
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'])
|
|
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()
|
|
plugged_interfaces.append(pb['interface_id'])
|
|
|
|
if old_port_bindings != port_bindings:
|
|
LOG.debug("Port-bindings: %s" % ports_string)
|
|
|
|
self.process_unplugged_interfaces(plugged_interfaces)
|
|
|
|
if old_vlan_bindings != vlan_bindings:
|
|
LOG.debug("VLAN-bindings: %s" % vlans_string)
|
|
|
|
self.process_deleted_networks(vlan_bindings)
|
|
|
|
conn.commit()
|
|
return {VLAN_BINDINGS: vlan_bindings,
|
|
PORT_BINDINGS: port_bindings}
|
|
|
|
def daemon_loop(self, conn):
|
|
old_vlan_bindings = {}
|
|
old_port_bindings = {}
|
|
|
|
while True:
|
|
bindings = self.manage_networks_on_host(conn,
|
|
old_vlan_bindings,
|
|
old_port_bindings)
|
|
old_vlan_bindings = bindings[VLAN_BINDINGS]
|
|
old_port_bindings = bindings[PORT_BINDINGS]
|
|
time.sleep(self.polling_interval)
|
|
|
|
if __name__ == "__main__":
|
|
usagestr = "%prog [OPTIONS] <config file>"
|
|
parser = OptionParser(usage=usagestr)
|
|
parser.add_option("-v", "--verbose", dest="verbose",
|
|
action="store_true", default=False, help="turn on verbose logging")
|
|
|
|
options, args = parser.parse_args()
|
|
|
|
if options.verbose:
|
|
LOG.basicConfig(level=LOG.DEBUG)
|
|
else:
|
|
LOG.basicConfig(level=LOG.WARN)
|
|
|
|
if len(args) != 1:
|
|
parser.print_help()
|
|
sys.exit(1)
|
|
|
|
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")
|
|
'Establish database connection and load models'
|
|
DB_CONNECTION = config.get("DATABASE", "connection")
|
|
if DB_CONNECTION == 'sqlite':
|
|
LOG.info("Connecting to sqlite DB")
|
|
conn = sqlite3.connect(":memory:")
|
|
conn.row_factory = sqlite3.Row
|
|
else:
|
|
db_name = config.get("DATABASE", "name")
|
|
db_user = config.get("DATABASE", "user")
|
|
db_pass = config.get("DATABASE", "pass")
|
|
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)))
|
|
sys.exit(1)
|
|
|
|
try:
|
|
plugin = LinuxBridgeQuantumAgent(br_name_prefix, physical_interface,
|
|
polling_interval)
|
|
LOG.info("Agent initialized successfully, now running...")
|
|
plugin.daemon_loop(conn)
|
|
finally:
|
|
if conn:
|
|
conn.close()
|
|
|
|
sys.exit(0)
|