blueprint database-common

This fixes bug 995438. If there is an database failure, for example, the
mysql service is down, then the agent or the service will attempt to
reconnect to the database every 'reconnect_interval'.

Change-Id: Iaee24b08e07a4f4dde5e27f31d3a5f81f5101466
This commit is contained in:
Gary Kotton 2012-05-06 07:36:47 -04:00
parent a90d63cbb0
commit 6bcc236ea3
9 changed files with 57 additions and 52 deletions

View File

@ -3,17 +3,14 @@ vlan_start=1000
vlan_end=3000
[DATABASE]
# Use the following when running the tests for the in-memory DB
connection = sqlite
# Uncomment the following for using the MySQL DB when actually running the plugin,
# also remove the earlier sqlite connection configuration
#connection = mysql
name = quantum_linux_bridge
user = <mysql_user_name_here>
pass = <mysql_password_here>
host = <hostname_or_IP_address_of_Quantum_server>
# If you use a non-default port for the DB, change the following
port = 3306
# This line MUST be changed to actually run the plugin.
# Example:
# sql_connection = mysql://root:nova@127.0.0.1:3306/quantum_linux_bridge
# Replace 127.0.0.1 above with the IP address of the database used by the
# main quantum server. (Leave it as is if the database runs on this host.)
sql_connection = sqlite://
# Database reconnection interval in seconds - in event connectivity is lost
reconnect_interval = 2
[LINUX_BRIDGE]
# This is the interface connected to the switch on your Quantum network
@ -22,8 +19,6 @@ physical_interface = eth1
[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

@ -1,9 +1,12 @@
[DATABASE]
# This line MUST be changed to actually run the plugin.
# Example: sql_connection = mysql://root:nova@127.0.0.1:3306/ovs_quantum
# Example:
# sql_connection = mysql://root:nova@127.0.0.1:3306/ovs_quantum
# Replace 127.0.0.1 above with the IP address of the database used by the
# main quantum server. (Leave it as is if the database runs on this host.)
sql_connection = sqlite://
# Database reconnection interval in seconds - in event connectivity is lost
reconnect_interval = 2
[OVS]
# This enables the new OVSQuantumTunnelAgent which enables tunneling
@ -34,8 +37,6 @@ integration-bridge = br-int
[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

@ -18,6 +18,8 @@
# @author: Dan Wendlandt, Nicira Networks, Inc.
import logging
import time
import sqlalchemy as sql
from sqlalchemy import create_engine
from sqlalchemy.exc import DisconnectionError
@ -75,7 +77,9 @@ def configure_db(options):
engine_args['listeners'] = [MySQLPingListener()]
_ENGINE = create_engine(options['sql_connection'], **engine_args)
register_models()
if not register_models():
if 'reconnect_interval' in options:
retry_registration(options['reconnect_interval'])
def clear_db():
@ -96,11 +100,25 @@ def get_session(autocommit=True, expire_on_commit=False):
return _MAKER()
def retry_registration(reconnect_interval):
while True:
LOG.info("Unable to connect to database. Retrying in %s seconds" %
reconnect_interval)
time.sleep(reconnect_interval)
if register_models():
break
def register_models():
"""Register Models and create properties"""
global _ENGINE
assert _ENGINE
BASE.metadata.create_all(_ENGINE)
try:
BASE.metadata.create_all(_ENGINE)
except sql.exc.OperationalError as e:
LOG.info("Database registration exception: %s" % e)
return False
return True
def unregister_models():

View File

@ -473,26 +473,17 @@ def main():
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")
if config.has_option("DATABASE", "reconnect_interval"):
reconnect_interval = config.getint("DATABASE",
"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'
connection = config.get("DATABASE", "connection")
if connection == 'sqlite':
LOG.info("Connecting to sqlite DB")
db_connection_url = "sqlite:///:memory:"
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))
db_connection_url = ("%s://%s:%s@%s:%d/%s" %
(connection, db_user, db_pass, db_host, db_port, db_name))
db_connection_url = config.get("DATABASE", "sql_connection")
LOG.info("Connecting to %s" % (db_connection_url))
except Exception as e:
LOG.error("Unable to parse config file \"%s\": \nException %s" %
(config_file, str(e)))

View File

@ -32,16 +32,8 @@ LOG = logging.getLogger(__name__)
def initialize():
'Establish database connection and load models'
if conf.DB_CONNECTION == 'sqlite':
options = {"sql_connection": "sqlite://"}
else:
options = {"sql_connection": "mysql://%s:%s@%s:%s/%s" % (conf.DB_USER,
conf.DB_PASS,
conf.DB_HOST,
conf.DB_PORT,
conf.DB_NAME)}
options = {"sql_connection": "%s" % conf.DB_SQL_CONNECTION}
options.update({"reconnect_interval": conf.DB_RECONNECT_INTERVAL})
db.configure_db(options)
create_vlanids()

View File

@ -39,10 +39,8 @@ VLAN_END = SECTION_CONF['vlan_end']
SECTION_CONF = CONF_PARSER_OBJ['DATABASE']
DB_CONNECTION = SECTION_CONF['connection']
if DB_CONNECTION != 'sqlite':
DB_NAME = SECTION_CONF['name']
DB_USER = SECTION_CONF['user']
DB_PASS = SECTION_CONF['pass']
DB_HOST = SECTION_CONF['host']
DB_PORT = SECTION_CONF['port']
DB_SQL_CONNECTION = SECTION_CONF['sql_connection']
if 'reconnect_interval' in SECTION_CONF:
DB_RECONNECT_INTERVAL = int(SECTION_CONF['reconnect_interval'])
else:
DB_RECONNECT_INTERVAL = 2

View File

@ -394,6 +394,8 @@ class LinuxBridgeAgentTest(unittest.TestCase):
self.physical_interface = config.get("LINUX_BRIDGE",
"physical_interface")
self.polling_interval = config.get("AGENT", "polling_interval")
self.reconnect_interval = config.get("DATABASE",
"reconnect_interval")
self.root_helper = config.get("AGENT", "root_helper")
except Exception, e:
LOG.error("Unable to parse config file \"%s\": \nException%s"
@ -406,6 +408,7 @@ class LinuxBridgeAgentTest(unittest.TestCase):
self.br_name_prefix,
self.physical_interface,
self.polling_interval,
self.reconnect_interval,
self.root_helper)
def run_cmd(self, args):

View File

@ -691,8 +691,9 @@ def main():
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")
if config.has_option("DATABASE", "reconnect_interval"):
reconnect_interval = config.getint("DATABASE",
"reconnect_interval")
else:
reconnect_interval = DEFAULT_RECONNECT_INTERVAL
LOG.info("Reconnect interval not defined. Using default.")

View File

@ -105,6 +105,12 @@ class OVSQuantumPlugin(QuantumPluginBase):
LOG.debug("Config: %s" % config)
options = {"sql_connection": config.get("DATABASE", "sql_connection")}
if config.has_option("DATABASE", "reconnect_interval"):
reconnect_interval = config.getint("DATABASE",
"reconnect_interval")
else:
reconnect_interval = 2
options.update({"reconnect_interval": reconnect_interval})
db.configure_db(options)
self.vmap = VlanMap()