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 93b66d4d74..b2a3e3b8dc 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 12796aa0c5..2cb39b69c0 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 455453816d..da9f598236 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 0c1a896df0..a65b19dc76 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 c6d64a4ba6..1dbf2950ad 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 cc6cdd66d6..dcb75a1fd1 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 21b142acb2..63acd55a0d 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 a01289d731..fc87f9f51f 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 aced08c301..dced289ca4 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()