Parse linuxbridge plugins using openstack.common.cfg

Implements the blueprint use-common-cfg

In order for the linuxbridge plugin to use the rpc code soon to be merged into
openstack-common, we need to parse our configuration using cfg. Here we
make the most simple, backwards compatible change in that direction.

The same is relevant for the openvswitch implementation

Fixes after comments.

Change-Id: I70fc1898a802cb4198f72741453283d114added2
This commit is contained in:
Gary Kotton 2012-05-29 08:19:45 -04:00
parent d2a21ec921
commit a86c31ba15
14 changed files with 1762 additions and 155 deletions

View File

@ -0,0 +1,25 @@
..
Copyright 2010-2011 United States Government as represented by the
Administrator of the National Aeronautics and Space Administration.
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.
Open Stack Common
=================
A number of modules used are from the openstack-common project.
The imported files are in 'quantum/openstack-common.conf'.
More information can be found at `OpenStack Common`_.
.. _`OpenStack Common`: https://launchpad.net/openstack-common

View File

@ -45,6 +45,7 @@ Development Documents
:maxdepth: 1
devref/index
devref/common
Man Pages
---------

View File

@ -11,22 +11,22 @@ reconnect_interval = 2
[OVS]
# This enables the new OVSQuantumTunnelAgent which enables tunneling
# between hybervisors. Leave it set to False or omit for legacy behavior.
enable-tunneling = False
enable_tunneling = False
# Do not change this parameter unless you have a good reason to.
# This is the name of the OVS integration bridge. There is one per hypervisor.
# The integration bridge acts as a virtual "patch port". All VM VIFs are
# attached to this bridge and then "patched" according to their network
# connectivity.
integration-bridge = br-int
integration_bridge = br-int
# Only used if enable-tunneling (above) is True.
# In most cases, the default value should be fine.
tunnel-bridge = br-tun
tunnel_bridge = br-tun
# Uncomment this line if enable-tunneling is True above.
# Set local-ip to be the local IP address of this hypervisor.
# local-ip = 10.0.0.3
# local_ip = 10.0.0.3
[AGENT]
# Agent's polling interval in seconds
@ -43,8 +43,8 @@ root_helper = sudo
# [DATABASE]
# sql_connection = mysql://root:nova@127.0.0.1:3306/ovs_quantum
# [OVS]
# enable-tunneling = False
# integration-bridge = br-int
# enable_tunneling = False
# integration_bridge = br-int
# [AGENT]
# root_helper = sudo
#
@ -52,10 +52,10 @@ root_helper = sudo
# [DATABASE]
# sql_connection = mysql://root:nova@127.0.0.1:3306/ovs_quantum
# [OVS]
# enable-tunneling = True
# integration-bridge = br-int
# tunnel-bridge = br-tun
# enable_tunneling = True
# integration_bridge = br-int
# tunnel_bridge = br-tun
# remote-ip-file = /opt/stack/remote-ips.txt
# local-ip = 10.0.0.3
# local_ip = 10.0.0.3
# [AGENT]
# root_helper = sudo

View File

@ -1,7 +1,7 @@
[DEFAULT]
# The list of modules to copy from openstack-common
modules=setup
modules=cfg,iniparser,setup
# The base module to hold the copy of openstack.common
base=quantum

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,126 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2012 OpenStack LLC.
#
# 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.
class ParseError(Exception):
def __init__(self, message, lineno, line):
self.msg = message
self.line = line
self.lineno = lineno
def __str__(self):
return 'at line %d, %s: %r' % (self.lineno, self.msg, self.line)
class BaseParser(object):
lineno = 0
parse_exc = ParseError
def _assignment(self, key, value):
self.assignment(key, value)
return None, []
def _get_section(self, line):
if line[-1] != ']':
return self.error_no_section_end_bracket(line)
if len(line) <= 2:
return self.error_no_section_name(line)
return line[1:-1]
def _split_key_value(self, line):
colon = line.find(':')
equal = line.find('=')
if colon < 0 and equal < 0:
return self.error_invalid_assignment(line)
if colon < 0 or (equal >= 0 and equal < colon):
key, value = line[:equal], line[equal + 1:]
else:
key, value = line[:colon], line[colon + 1:]
return key.strip(), [value.strip()]
def parse(self, lineiter):
key = None
value = []
for line in lineiter:
self.lineno += 1
line = line.rstrip()
if not line:
# Blank line, ends multi-line values
if key:
key, value = self._assignment(key, value)
continue
elif line[0] in (' ', '\t'):
# Continuation of previous assignment
if key is None:
self.error_unexpected_continuation(line)
else:
value.append(line.lstrip())
continue
if key:
# Flush previous assignment, if any
key, value = self._assignment(key, value)
if line[0] == '[':
# Section start
section = self._get_section(line)
if section:
self.new_section(section)
elif line[0] in '#;':
self.comment(line[1:].lstrip())
else:
key, value = self._split_key_value(line)
if not key:
return self.error_empty_key(line)
if key:
# Flush previous assignment, if any
self._assignment(key, value)
def assignment(self, key, value):
"""Called when a full assignment is parsed"""
raise NotImplementedError()
def new_section(self, section):
"""Called when a new section is started"""
raise NotImplementedError()
def comment(self, comment):
"""Called when a comment is parsed"""
pass
def error_invalid_assignment(self, line):
raise self.parse_exc("No ':' or '=' found in assignment",
self.lineno, line)
def error_empty_key(self, line):
raise self.parse_exc('Key cannot be empty', self.lineno, line)
def error_unexpected_continuation(self, line):
raise self.parse_exc('Unexpected continuation line',
self.lineno, line)
def error_no_section_end_bracket(self, line):
raise self.parse_exc('Invalid section (must end with ])',
self.lineno, line)
def error_no_section_name(self, line):
raise self.parse_exc('Empty section name', self.lineno, line)

View File

@ -23,7 +23,6 @@ from quantum.db import api as db
from quantum.plugins.linuxbridge.common import constants as const
from quantum.plugins.linuxbridge.common import utils as cutil
from quantum.plugins.linuxbridge.db import l2network_db as cdb
from quantum.plugins.linuxbridge import plugin_configuration as conf
from quantum.quantum_plugin_base import QuantumPluginBase

View File

@ -22,7 +22,6 @@
# Quantum OpenVSwitch Plugin.
# @author: Sumit Naiksatam, Cisco Systems, Inc.
import ConfigParser
import logging
from optparse import OptionParser
import os
@ -35,11 +34,12 @@ import time
from sqlalchemy.ext.sqlsoup import SqlSoup
from quantum.common import exceptions as exception
from quantum.plugins.linuxbridge.common import config
logging.basicConfig()
LOG = logging.getLogger(__name__)
BRIDGE_NAME_PREFIX = "brq"
GATEWAY_INTERFACE_PREFIX = "gw-"
TAP_INTERFACE_PREFIX = "tap"
@ -479,33 +479,15 @@ def main():
sys.exit(1)
config_file = args[0]
config = ConfigParser.ConfigParser()
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")
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("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'
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)))
sys.exit(1)
conf = config.parse(config_file)
br_name_prefix = BRIDGE_NAME_PREFIX
physical_interface = conf.BRIDGE.physical_interface
polling_interval = conf.AGENT.polling_interval
reconnect_interval = conf.DATABASE.reconnect_interval
root_helper = conf.AGENT.root_helper
'Establish database connection and load models'
db_connection_url = conf.DATABASE.sql_connection
LOG.info("Connecting to %s" % (db_connection_url))
plugin = LinuxBridgeQuantumAgent(br_name_prefix, physical_interface,
polling_interval, reconnect_interval,

View File

@ -17,28 +17,34 @@
# @author: Sumit Naiksatam, Cisco Systems, Inc.
# @author: Rohit Agarwalla, Cisco Systems, Inc.
import os
from quantum.common.config import find_config_file
from quantum.plugins.linuxbridge.common import configparser as confp
from quantum.openstack.common import cfg
CONF_FILE = find_config_file({'plugin': 'linuxbridge'}, None,
"linuxbridge_conf.ini")
CONF_PARSER_OBJ = confp.ConfigParser(CONF_FILE)
vlan_opts = [
cfg.IntOpt('vlan_start', default=1000),
cfg.IntOpt('vlan_end', default=3000),
]
database_opts = [
cfg.StrOpt('sql_connection', default='sqlite://'),
cfg.IntOpt('reconnect_interval', default=2),
]
bridge_opts = [
cfg.StrOpt('physical_interface', default='eth1'),
]
agent_opts = [
cfg.IntOpt('polling_interval', default=2),
cfg.StrOpt('root_helper', default='sudo'),
]
"""
Reading the conf for the linuxbridge_plugin
"""
SECTION_CONF = CONF_PARSER_OBJ['VLANS']
VLAN_START = SECTION_CONF['vlan_start']
VLAN_END = SECTION_CONF['vlan_end']
SECTION_CONF = CONF_PARSER_OBJ['DATABASE']
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
def parse(config_file):
conf = cfg.ConfigOpts(default_config_files=[config_file])
conf(args=[])
conf.register_opts(vlan_opts, "VLANS")
conf.register_opts(database_opts, "DATABASE")
conf.register_opts(bridge_opts, "BRIDGE")
conf.register_opts(agent_opts, "AGENT")
return conf

View File

@ -21,18 +21,21 @@ from sqlalchemy import func
from sqlalchemy.orm import exc
from quantum.common import exceptions as q_exc
from quantum.common.config import find_config_file
import quantum.db.api as db
from quantum.plugins.linuxbridge.common import exceptions as c_exc
from quantum.plugins.linuxbridge.db import l2network_models
from quantum.plugins.linuxbridge import plugin_configuration as conf
from quantum.plugins.linuxbridge.common import config
LOG = logging.getLogger(__name__)
CONF_FILE = find_config_file({'plugin': 'linuxbridge'}, None,
"linuxbridge_conf.ini")
CONF = config.parse(CONF_FILE)
def initialize():
options = {"sql_connection": "%s" % conf.DB_SQL_CONNECTION}
options.update({"reconnect_interval": conf.DB_RECONNECT_INTERVAL})
options = {"sql_connection": "%s" % CONF.DATABASE.sql_connection}
options.update({"reconnect_interval": CONF.DATABASE.reconnect_interval})
db.configure_db(options)
create_vlanids()
@ -41,8 +44,8 @@ def create_vlanids():
"""Prepopulates the vlan_bindings table"""
LOG.debug("create_vlanids() called")
session = db.get_session()
start = int(conf.VLAN_START)
end = int(conf.VLAN_END)
start = CONF.VLANS.vlan_start
end = CONF.VLANS.vlan_end
try:
vlanid = session.query(l2network_models.VlanID).\
one()

View File

@ -19,7 +19,6 @@
# @author: Dan Wendlandt, Nicira Networks, Inc.
# @author: Dave Lapsley, Nicira Networks, Inc.
import ConfigParser
import logging
from optparse import OptionParser
import shlex
@ -31,6 +30,9 @@ import time
import sqlalchemy
from sqlalchemy.ext import sqlsoup
from quantum.plugins.openvswitch.common import config
logging.basicConfig()
LOG = logging.getLogger(__name__)
@ -688,67 +690,21 @@ def main():
sys.exit(1)
config_file = args[0]
config = ConfigParser.ConfigParser()
try:
config.read(config_file)
except Exception as e:
LOG.error("Unable to parse config file \"%s\": %s" %
(config_file, str(e)))
raise e
conf = config.parse(config_file)
# Determine which agent type to use.
enable_tunneling = False
try:
enable_tunneling = config.getboolean("OVS", "enable-tunneling")
except Exception as e:
pass
# Get common parameters.
try:
integ_br = config.get("OVS", "integration-bridge")
if not len(integ_br):
raise Exception('Empty integration-bridge in configuration file.')
db_connection_url = config.get("DATABASE", "sql_connection")
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("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")
except Exception as e:
LOG.error("Error parsing common params in config_file: '%s': %s" %
(config_file, str(e)))
sys.exit(1)
enable_tunneling = conf.OVS.enable_tunneling
integ_br = conf.OVS.integration_bridge
db_connection_url = conf.DATABASE.sql_connection
polling_interval = conf.AGENT.polling_interval
reconnect_interval = conf.DATABASE.reconnect_interval
root_helper = conf.AGENT.root_helper
if enable_tunneling:
# Get parameters for OVSQuantumTunnelAgent
try:
# Mandatory parameter.
tun_br = config.get("OVS", "tunnel-bridge")
if not len(tun_br):
raise Exception('Empty tunnel-bridge in configuration file.')
# Mandatory parameter.
local_ip = config.get("OVS", "local-ip")
if not len(local_ip):
raise Exception('Empty local-ip in configuration file.')
except Exception as e:
LOG.error("Error parsing tunnel params in config_file: '%s': %s" %
(config_file, str(e)))
sys.exit(1)
tun_br = conf.OVS.tunnel_bridge
# Mandatory parameter.
local_ip = conf.OVS.local_ip
plugin = OVSQuantumTunnelAgent(integ_br, tun_br, local_ip, root_helper,
polling_interval, reconnect_interval)
else:

View File

@ -1,6 +1,6 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
#
# Copyright 2012 Cisco Systems, Inc. All rights reserved.
# Copyright 2012 Red Hat, Inc.
#
# 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
@ -13,19 +13,3 @@
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
# @author: Sumit Naiksatam, Cisco Systems, Inc.
from configobj import ConfigObj
class ConfigParser(ConfigObj):
"""Config Parser based on the ConfigObj module"""
def __init__(self, filename):
super(ConfigParser, self).__init__(filename, raise_errors=True,
file_error=True)
def dummy(self, section, key):
"""Dummy function to return the same key, used in walk"""
return section[key]

View File

@ -0,0 +1,44 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2012 Red Hat, Inc.
#
# 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.
from quantum.openstack.common import cfg
database_opts = [
cfg.StrOpt('sql_connection', default='sqlite://'),
cfg.IntOpt('reconnect_interval', default=2),
]
ovs_opts = [
cfg.StrOpt('enable_tunneling', default='False'),
cfg.StrOpt('integration_bridge', default='br-int'),
cfg.StrOpt('tunnel_bridge', default='br-tun'),
cfg.StrOpt('local_ip', default='10.0.0.3'),
]
agent_opts = [
cfg.IntOpt('polling_interval', default=2),
cfg.StrOpt('root_helper', default='sudo'),
]
def parse(config_file):
conf = cfg.ConfigOpts(default_config_files=[config_file])
conf(args=[])
conf.register_opts(database_opts, "DATABASE")
conf.register_opts(ovs_opts, "OVS")
conf.register_opts(agent_opts, "AGENT")
return conf

View File

@ -18,7 +18,6 @@
# @author: Dan Wendlandt, Nicira Networks, Inc.
# @author: Dave Lapsley, Nicira Networks, Inc.
import ConfigParser
import logging
from optparse import OptionParser
import os
@ -29,9 +28,9 @@ from quantum.common import exceptions as q_exc
from quantum.common.config import find_config_file
import quantum.db.api as db
from quantum.plugins.openvswitch import ovs_db
from quantum.plugins.openvswitch.common import config
from quantum.quantum_plugin_base import QuantumPluginBase
LOG = logging.getLogger("ovs_quantum_plugin")
@ -89,7 +88,6 @@ class VlanMap(object):
class OVSQuantumPlugin(QuantumPluginBase):
def __init__(self, configfile=None):
config = ConfigParser.ConfigParser()
if configfile is None:
if os.path.exists(CONF_FILE):
configfile = CONF_FILE
@ -100,15 +98,9 @@ class OVSQuantumPlugin(QuantumPluginBase):
raise Exception("Configuration file \"%s\" doesn't exist" %
(configfile))
LOG.debug("Using configuration file: %s" % configfile)
config.read(configfile)
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
conf = config.parse(configfile)
options = {"sql_connection": conf.DATABASE.sql_connection}
reconnect_interval = conf.DATABASE.reconnect_interval
options.update({"reconnect_interval": reconnect_interval})
db.configure_db(options)