Enable Ceilometer to support mongodb replication set
At present, ceilometer does not support mongodb replication set. As a result, when the primary mongod node is down, ceilometer can not write or read meters. Use pymongo.Connection object's replicaSet param and allowing to connect with a host seed list will let the mongodb connection support replication set. Change-Id: I8404ca5b08b6e73366161c07b3815f75bed7e0eb Fixes: Bug 1188649
This commit is contained in:
parent
04bbab3971
commit
a2b6dc4ed2
@ -32,11 +32,12 @@ import bson.code
|
|||||||
import bson.objectid
|
import bson.objectid
|
||||||
import pymongo
|
import pymongo
|
||||||
|
|
||||||
|
from oslo.config import cfg
|
||||||
|
|
||||||
from ceilometer.openstack.common import log
|
from ceilometer.openstack.common import log
|
||||||
from ceilometer.storage import base
|
from ceilometer.storage import base
|
||||||
from ceilometer.storage import models
|
from ceilometer.storage import models
|
||||||
|
|
||||||
|
|
||||||
LOG = log.getLogger(__name__)
|
LOG = log.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
@ -66,13 +67,26 @@ class MongoDBStorage(base.StorageEngine):
|
|||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
|
|
||||||
OPTIONS = []
|
OPTIONS = [
|
||||||
|
cfg.StrOpt('replica_set_name',
|
||||||
|
default='',
|
||||||
|
help='Used to identify the replication set name',
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
||||||
|
OPTION_GROUP = cfg.OptGroup(name='storage_mongodb',
|
||||||
|
title='Options for the mongodb storage')
|
||||||
|
|
||||||
def register_opts(self, conf):
|
def register_opts(self, conf):
|
||||||
"""Register any configuration options used by this engine.
|
"""Register any configuration options used by this engine.
|
||||||
"""
|
"""
|
||||||
conf.register_opts(self.OPTIONS)
|
conf.register_group(self.OPTION_GROUP)
|
||||||
|
conf.register_opts(self.OPTIONS, self.OPTION_GROUP)
|
||||||
|
|
||||||
|
# FIXME(xingzhou): ceilometer-api will create a Connection object for
|
||||||
|
# each request. As pymongo.Connection has already maintained a db
|
||||||
|
# connection pool for client, it is better to use a cached Connection
|
||||||
|
# object to connect to mongodb.
|
||||||
def get_connection(self, conf):
|
def get_connection(self, conf):
|
||||||
"""Return a Connection instance based on the configuration settings.
|
"""Return a Connection instance based on the configuration settings.
|
||||||
"""
|
"""
|
||||||
@ -197,15 +211,15 @@ class Connection(base.Connection):
|
|||||||
|
|
||||||
def __init__(self, conf):
|
def __init__(self, conf):
|
||||||
opts = self._parse_connection_url(conf.database.connection)
|
opts = self._parse_connection_url(conf.database.connection)
|
||||||
LOG.info('connecting to MongoDB on %s:%s', opts['host'], opts['port'])
|
LOG.info('connecting to MongoDB replicaset "%s" on %s',
|
||||||
|
conf.storage_mongodb.replica_set_name,
|
||||||
|
opts['netloc'])
|
||||||
|
|
||||||
if opts['host'] == '__test__':
|
if opts['netloc'] == '__test__':
|
||||||
url = os.environ.get('CEILOMETER_TEST_MONGODB_URL')
|
url = os.environ.get('CEILOMETER_TEST_MONGODB_URL')
|
||||||
if url:
|
if url:
|
||||||
opts = self._parse_connection_url(url)
|
opts = self._parse_connection_url(url)
|
||||||
self.conn = pymongo.Connection(opts['host'],
|
self.conn = pymongo.Connection(opts['netloc'], safe=True)
|
||||||
opts['port'],
|
|
||||||
safe=True)
|
|
||||||
else:
|
else:
|
||||||
# MIM will die if we have too many connections, so use a
|
# MIM will die if we have too many connections, so use a
|
||||||
# Singleton
|
# Singleton
|
||||||
@ -220,9 +234,10 @@ class Connection(base.Connection):
|
|||||||
self.conn = Connection._mim_instance
|
self.conn = Connection._mim_instance
|
||||||
LOG.debug('Using MIM for test connection')
|
LOG.debug('Using MIM for test connection')
|
||||||
else:
|
else:
|
||||||
self.conn = pymongo.Connection(opts['host'],
|
self.conn = pymongo.Connection(
|
||||||
opts['port'],
|
opts['netloc'],
|
||||||
safe=True)
|
replicaSet=conf.storage_mongodb.replica_set_name,
|
||||||
|
safe=True)
|
||||||
|
|
||||||
self.db = getattr(self.conn, opts['dbname'])
|
self.db = getattr(self.conn, opts['dbname'])
|
||||||
if 'username' in opts:
|
if 'username' in opts:
|
||||||
@ -269,15 +284,9 @@ class Connection(base.Connection):
|
|||||||
opts['dbname'] = result.path.replace('/', '')
|
opts['dbname'] = result.path.replace('/', '')
|
||||||
netloc_match = re.match(r'(?:(\w+:\w+)@)?(.*)', result.netloc)
|
netloc_match = re.match(r'(?:(\w+:\w+)@)?(.*)', result.netloc)
|
||||||
auth = netloc_match.group(1)
|
auth = netloc_match.group(1)
|
||||||
netloc = netloc_match.group(2)
|
opts['netloc'] = netloc_match.group(2)
|
||||||
if auth:
|
if auth:
|
||||||
opts['username'], opts['password'] = auth.split(':')
|
opts['username'], opts['password'] = auth.split(':')
|
||||||
if ':' in netloc:
|
|
||||||
opts['host'], port = netloc.split(':')
|
|
||||||
else:
|
|
||||||
opts['host'] = netloc
|
|
||||||
port = 27017
|
|
||||||
opts['port'] = port and int(port) or 27017
|
|
||||||
return opts
|
return opts
|
||||||
|
|
||||||
def record_metering_data(self, data):
|
def record_metering_data(self, data):
|
||||||
|
Loading…
Reference in New Issue
Block a user