From 6bcc236ea3f805a642e2800b334ba2147da1774e Mon Sep 17 00:00:00 2001 From: Gary Kotton Date: Sun, 6 May 2012 07:36:47 -0400 Subject: [PATCH] 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 --- .../plugins/linuxbridge/linuxbridge_conf.ini | 21 +++++++----------- .../openvswitch/ovs_quantum_plugin.ini | 7 +++--- quantum/db/api.py | 22 +++++++++++++++++-- .../agent/linuxbridge_quantum_agent.py | 21 +++++------------- .../plugins/linuxbridge/db/l2network_db.py | 12 ++-------- .../linuxbridge/plugin_configuration.py | 12 +++++----- .../tests/unit/_test_linuxbridgeAgent.py | 3 +++ .../openvswitch/agent/ovs_quantum_agent.py | 5 +++-- .../plugins/openvswitch/ovs_quantum_plugin.py | 6 +++++ 9 files changed, 57 insertions(+), 52 deletions(-) diff --git a/etc/quantum/plugins/linuxbridge/linuxbridge_conf.ini b/etc/quantum/plugins/linuxbridge/linuxbridge_conf.ini index 93b66d4d741..b2a3e3b8dcd 100644 --- a/etc/quantum/plugins/linuxbridge/linuxbridge_conf.ini +++ b/etc/quantum/plugins/linuxbridge/linuxbridge_conf.ini @@ -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 = -pass = -host = -# 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 diff --git a/etc/quantum/plugins/openvswitch/ovs_quantum_plugin.ini b/etc/quantum/plugins/openvswitch/ovs_quantum_plugin.ini index 12796aa0c53..2cb39b69c0d 100644 --- a/etc/quantum/plugins/openvswitch/ovs_quantum_plugin.ini +++ b/etc/quantum/plugins/openvswitch/ovs_quantum_plugin.ini @@ -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 diff --git a/quantum/db/api.py b/quantum/db/api.py index 455453816d0..da9f5982360 100644 --- a/quantum/db/api.py +++ b/quantum/db/api.py @@ -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(): diff --git a/quantum/plugins/linuxbridge/agent/linuxbridge_quantum_agent.py b/quantum/plugins/linuxbridge/agent/linuxbridge_quantum_agent.py index 0c1a896df0c..a65b19dc76b 100755 --- a/quantum/plugins/linuxbridge/agent/linuxbridge_quantum_agent.py +++ b/quantum/plugins/linuxbridge/agent/linuxbridge_quantum_agent.py @@ -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))) diff --git a/quantum/plugins/linuxbridge/db/l2network_db.py b/quantum/plugins/linuxbridge/db/l2network_db.py index c6d64a4ba6e..1dbf2950ad6 100644 --- a/quantum/plugins/linuxbridge/db/l2network_db.py +++ b/quantum/plugins/linuxbridge/db/l2network_db.py @@ -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() diff --git a/quantum/plugins/linuxbridge/plugin_configuration.py b/quantum/plugins/linuxbridge/plugin_configuration.py index cc6cdd66d64..dcb75a1fd16 100644 --- a/quantum/plugins/linuxbridge/plugin_configuration.py +++ b/quantum/plugins/linuxbridge/plugin_configuration.py @@ -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 diff --git a/quantum/plugins/linuxbridge/tests/unit/_test_linuxbridgeAgent.py b/quantum/plugins/linuxbridge/tests/unit/_test_linuxbridgeAgent.py index 21b142acb24..63acd55a0d6 100644 --- a/quantum/plugins/linuxbridge/tests/unit/_test_linuxbridgeAgent.py +++ b/quantum/plugins/linuxbridge/tests/unit/_test_linuxbridgeAgent.py @@ -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): diff --git a/quantum/plugins/openvswitch/agent/ovs_quantum_agent.py b/quantum/plugins/openvswitch/agent/ovs_quantum_agent.py index a01289d731f..fc87f9f51f5 100755 --- a/quantum/plugins/openvswitch/agent/ovs_quantum_agent.py +++ b/quantum/plugins/openvswitch/agent/ovs_quantum_agent.py @@ -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.") diff --git a/quantum/plugins/openvswitch/ovs_quantum_plugin.py b/quantum/plugins/openvswitch/ovs_quantum_plugin.py index aced08c3011..dced289ca40 100644 --- a/quantum/plugins/openvswitch/ovs_quantum_plugin.py +++ b/quantum/plugins/openvswitch/ovs_quantum_plugin.py @@ -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()