Make swift-bench not depending on swift.
Remove the dependence on swift, import the only needed functions from swift.common.utils to swiftbench.utils Add tests for utils using mock instead. Change-Id: I1b69dce750b55f3ee0e999fb5a7100cf811f7ebe
This commit is contained in:

committed by
Chmouel Boudjnah

parent
64b976e139
commit
b207aaca07
@@ -3,6 +3,6 @@ set -e
|
|||||||
|
|
||||||
python setup.py testr --coverage
|
python setup.py testr --coverage
|
||||||
RET=$?
|
RET=$?
|
||||||
coverage report -m
|
coverage report -mswiftbench
|
||||||
rm -f .coverage
|
rm -f .coverage
|
||||||
exit $RET
|
exit $RET
|
||||||
|
@@ -23,7 +23,7 @@ from optparse import OptionParser
|
|||||||
|
|
||||||
from swiftbench.bench import (BenchController, DistributedBenchController,
|
from swiftbench.bench import (BenchController, DistributedBenchController,
|
||||||
create_containers, delete_containers)
|
create_containers, delete_containers)
|
||||||
from swiftbench.utils import readconf, LogAdapter, config_true_value
|
from swiftbench.utils import readconf, config_true_value
|
||||||
|
|
||||||
# The defaults should be sufficient to run swift-bench on a SAIO
|
# The defaults should be sufficient to run swift-bench on a SAIO
|
||||||
CONF_DEFAULTS = {
|
CONF_DEFAULTS = {
|
||||||
@@ -172,7 +172,6 @@ if __name__ == '__main__':
|
|||||||
options.log_level.lower(), logging.INFO))
|
options.log_level.lower(), logging.INFO))
|
||||||
loghandler = logging.StreamHandler()
|
loghandler = logging.StreamHandler()
|
||||||
logger.addHandler(loghandler)
|
logger.addHandler(loghandler)
|
||||||
logger = LogAdapter(logger, 'swift-bench')
|
|
||||||
logformat = logging.Formatter('%(server)s %(asctime)s %(levelname)s '
|
logformat = logging.Formatter('%(server)s %(asctime)s %(levelname)s '
|
||||||
'%(message)s')
|
'%(message)s')
|
||||||
loghandler.setFormatter(logformat)
|
loghandler.setFormatter(logformat)
|
||||||
|
@@ -19,8 +19,7 @@ import sys
|
|||||||
import signal
|
import signal
|
||||||
from optparse import OptionParser
|
from optparse import OptionParser
|
||||||
|
|
||||||
from swift.common.bench import BenchServer
|
from swiftbench.bench import BenchServer
|
||||||
from swift.common.utils import LogAdapter
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
usage = "usage: %prog <ip> <port>"
|
usage = "usage: %prog <ip> <port>"
|
||||||
@@ -45,7 +44,6 @@ if __name__ == '__main__':
|
|||||||
options.log_level.lower(), logging.INFO))
|
options.log_level.lower(), logging.INFO))
|
||||||
loghandler = logging.StreamHandler()
|
loghandler = logging.StreamHandler()
|
||||||
logger.addHandler(loghandler)
|
logger.addHandler(loghandler)
|
||||||
logger = LogAdapter(logger, 'swift-bench-client')
|
|
||||||
logformat = logging.Formatter('%(server)s %(asctime)s %(levelname)s '
|
logformat = logging.Formatter('%(server)s %(asctime)s %(levelname)s '
|
||||||
'%(message)s')
|
'%(message)s')
|
||||||
loghandler.setFormatter(logformat)
|
loghandler.setFormatter(logformat)
|
||||||
|
@@ -29,11 +29,21 @@ import eventlet
|
|||||||
import eventlet.pools
|
import eventlet.pools
|
||||||
from eventlet.green.httplib import CannotSendRequest
|
from eventlet.green.httplib import CannotSendRequest
|
||||||
|
|
||||||
from swift.common.utils import config_true_value, LogAdapter
|
|
||||||
import swiftclient as client
|
import swiftclient as client
|
||||||
from swift.common import direct_client
|
|
||||||
from swift.common.http import HTTP_CONFLICT
|
from swiftbench.utils import config_true_value
|
||||||
from swift.common.utils import json
|
|
||||||
|
try:
|
||||||
|
import simplejson as json
|
||||||
|
except ImportError:
|
||||||
|
import json
|
||||||
|
|
||||||
|
try:
|
||||||
|
from swift.common import direct_client
|
||||||
|
except ImportError:
|
||||||
|
direct_client = None
|
||||||
|
|
||||||
|
HTTP_CONFLICT = 409
|
||||||
|
|
||||||
|
|
||||||
def _func_on_containers(logger, conf, concurrency_key, func):
|
def _func_on_containers(logger, conf, concurrency_key, func):
|
||||||
@@ -152,7 +162,6 @@ class BenchServer(object):
|
|||||||
'%(server)s %(asctime)s %(levelname)s %(message)s')
|
'%(server)s %(asctime)s %(levelname)s %(message)s')
|
||||||
loghandler.setFormatter(logformat)
|
loghandler.setFormatter(logformat)
|
||||||
logger.addHandler(loghandler)
|
logger.addHandler(loghandler)
|
||||||
logger = LogAdapter(logger, 'swift-bench-server')
|
|
||||||
|
|
||||||
controller = BenchController(logger, conf)
|
controller = BenchController(logger, conf)
|
||||||
try:
|
try:
|
||||||
@@ -176,6 +185,10 @@ class Bench(object):
|
|||||||
self.key = conf.key
|
self.key = conf.key
|
||||||
self.auth_url = conf.auth
|
self.auth_url = conf.auth
|
||||||
self.use_proxy = config_true_value(conf.use_proxy)
|
self.use_proxy = config_true_value(conf.use_proxy)
|
||||||
|
if not self.use_proxy and direct_client is None:
|
||||||
|
self.logger.critical("You need to have swift installed if you are "
|
||||||
|
"not using the proxy")
|
||||||
|
sys.exit(1)
|
||||||
self.auth_version = conf.auth_version
|
self.auth_version = conf.auth_version
|
||||||
self.logger.info("Auth version: %s" % self.auth_version)
|
self.logger.info("Auth version: %s" % self.auth_version)
|
||||||
if self.use_proxy:
|
if self.use_proxy:
|
||||||
|
79
swiftbench/utils.py
Normal file
79
swiftbench/utils.py
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
# Copyright (c) 2010-2013 OpenStack Foundation
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
import sys
|
||||||
|
from ConfigParser import ConfigParser, RawConfigParser
|
||||||
|
|
||||||
|
# Used when reading config values
|
||||||
|
TRUE_VALUES = set(('true', '1', 'yes', 'on', 't', 'y'))
|
||||||
|
|
||||||
|
|
||||||
|
# NOTE(chmouel): Imported from swift without the modular directory feature.
|
||||||
|
def readconf(conf_path, section_name=None, log_name=None, defaults=None,
|
||||||
|
raw=False):
|
||||||
|
"""
|
||||||
|
Read config file(s) and return config items as a dict
|
||||||
|
|
||||||
|
:param conf_path: path to config file, or a file-like object
|
||||||
|
(hasattr readline)
|
||||||
|
:param section_name: config section to read (will return all sections if
|
||||||
|
not defined)
|
||||||
|
:param log_name: name to be used with logging (will use section_name if
|
||||||
|
not defined)
|
||||||
|
:param defaults: dict of default values to pre-populate the config with
|
||||||
|
:returns: dict of config items
|
||||||
|
"""
|
||||||
|
if defaults is None:
|
||||||
|
defaults = {}
|
||||||
|
if raw:
|
||||||
|
c = RawConfigParser(defaults)
|
||||||
|
else:
|
||||||
|
c = ConfigParser(defaults)
|
||||||
|
if hasattr(conf_path, 'readline'):
|
||||||
|
c.readfp(conf_path)
|
||||||
|
else:
|
||||||
|
success = c.read(conf_path)
|
||||||
|
if not success:
|
||||||
|
print "Unable to read config from %s" % conf_path
|
||||||
|
sys.exit(1)
|
||||||
|
if section_name:
|
||||||
|
if c.has_section(section_name):
|
||||||
|
conf = dict(c.items(section_name))
|
||||||
|
else:
|
||||||
|
print "Unable to find %s config section in %s" % \
|
||||||
|
(section_name, conf_path)
|
||||||
|
sys.exit(1)
|
||||||
|
if "log_name" not in conf:
|
||||||
|
if log_name is not None:
|
||||||
|
conf['log_name'] = log_name
|
||||||
|
else:
|
||||||
|
conf['log_name'] = section_name
|
||||||
|
else:
|
||||||
|
conf = {}
|
||||||
|
for s in c.sections():
|
||||||
|
conf.update({s: dict(c.items(s))})
|
||||||
|
if 'log_name' not in conf:
|
||||||
|
conf['log_name'] = log_name
|
||||||
|
conf['__file__'] = conf_path
|
||||||
|
return conf
|
||||||
|
|
||||||
|
|
||||||
|
def config_true_value(value):
|
||||||
|
"""
|
||||||
|
Returns True if the value is either True or a string in TRUE_VALUES.
|
||||||
|
Returns False otherwise.
|
||||||
|
"""
|
||||||
|
return value is True or \
|
||||||
|
(isinstance(value, basestring) and value.lower() in TRUE_VALUES)
|
@@ -1,4 +1,4 @@
|
|||||||
# Copyright (c) 2010-2012 OpenStack Foundation
|
# Copyright (c) 2010-2013 OpenStack Foundation
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
# you may not use this file except in compliance with the License.
|
# you may not use this file except in compliance with the License.
|
||||||
|
109
tests/test_utils.py
Normal file
109
tests/test_utils.py
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
# Copyright (c) 2010-2013 OpenStack Foundation
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
import mock
|
||||||
|
import os
|
||||||
|
import tempfile
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
from StringIO import StringIO
|
||||||
|
|
||||||
|
from swiftbench import utils
|
||||||
|
|
||||||
|
|
||||||
|
class TestUtils(unittest.TestCase):
|
||||||
|
|
||||||
|
@mock.patch.object(utils, "TRUE_VALUES")
|
||||||
|
def test_config_true_value(self, mocked):
|
||||||
|
utils.TRUE_VALUES = 'hello world'.split()
|
||||||
|
for val in 'hello world HELLO WORLD'.split():
|
||||||
|
self.assertTrue(utils.config_true_value(val) is True)
|
||||||
|
self.assertTrue(utils.config_true_value(True) is True)
|
||||||
|
self.assertTrue(utils.config_true_value('foo') is False)
|
||||||
|
self.assertTrue(utils.config_true_value(False) is False)
|
||||||
|
|
||||||
|
def test_readconf(self):
|
||||||
|
conf = '''[section1]
|
||||||
|
foo = bar
|
||||||
|
|
||||||
|
[section2]
|
||||||
|
log_name = yarr'''
|
||||||
|
# setup a real file
|
||||||
|
fd, temppath = tempfile.mkstemp(dir='/tmp')
|
||||||
|
with os.fdopen(fd, 'wb') as f:
|
||||||
|
f.write(conf)
|
||||||
|
make_filename = lambda: temppath
|
||||||
|
# setup a file stream
|
||||||
|
make_fp = lambda: StringIO(conf)
|
||||||
|
for conf_object_maker in (make_filename, make_fp):
|
||||||
|
conffile = conf_object_maker()
|
||||||
|
result = utils.readconf(conffile)
|
||||||
|
expected = {'__file__': conffile,
|
||||||
|
'log_name': None,
|
||||||
|
'section1': {'foo': 'bar'},
|
||||||
|
'section2': {'log_name': 'yarr'}}
|
||||||
|
self.assertEquals(result, expected)
|
||||||
|
conffile = conf_object_maker()
|
||||||
|
result = utils.readconf(conffile, 'section1')
|
||||||
|
expected = {'__file__': conffile, 'log_name': 'section1',
|
||||||
|
'foo': 'bar'}
|
||||||
|
self.assertEquals(result, expected)
|
||||||
|
conffile = conf_object_maker()
|
||||||
|
result = utils.readconf(conffile,
|
||||||
|
'section2').get('log_name')
|
||||||
|
expected = 'yarr'
|
||||||
|
self.assertEquals(result, expected)
|
||||||
|
conffile = conf_object_maker()
|
||||||
|
result = utils.readconf(conffile, 'section1',
|
||||||
|
log_name='foo').get('log_name')
|
||||||
|
expected = 'foo'
|
||||||
|
self.assertEquals(result, expected)
|
||||||
|
conffile = conf_object_maker()
|
||||||
|
result = utils.readconf(conffile, 'section1',
|
||||||
|
defaults={'bar': 'baz'})
|
||||||
|
expected = {'__file__': conffile, 'log_name': 'section1',
|
||||||
|
'foo': 'bar', 'bar': 'baz'}
|
||||||
|
self.assertEquals(result, expected)
|
||||||
|
self.assertRaises(SystemExit, utils.readconf, temppath, 'section3')
|
||||||
|
os.unlink(temppath)
|
||||||
|
self.assertRaises(SystemExit, utils.readconf, temppath)
|
||||||
|
|
||||||
|
def test_readconf_raw(self):
|
||||||
|
conf = '''[section1]
|
||||||
|
foo = bar
|
||||||
|
|
||||||
|
[section2]
|
||||||
|
log_name = %(yarr)s'''
|
||||||
|
# setup a real file
|
||||||
|
fd, temppath = tempfile.mkstemp(dir='/tmp')
|
||||||
|
with os.fdopen(fd, 'wb') as f:
|
||||||
|
f.write(conf)
|
||||||
|
make_filename = lambda: temppath
|
||||||
|
# setup a file stream
|
||||||
|
make_fp = lambda: StringIO(conf)
|
||||||
|
for conf_object_maker in (make_filename, make_fp):
|
||||||
|
conffile = conf_object_maker()
|
||||||
|
result = utils.readconf(conffile, raw=True)
|
||||||
|
expected = {'__file__': conffile,
|
||||||
|
'log_name': None,
|
||||||
|
'section1': {'foo': 'bar'},
|
||||||
|
'section2': {'log_name': '%(yarr)s'}}
|
||||||
|
self.assertEquals(result, expected)
|
||||||
|
os.unlink(temppath)
|
||||||
|
self.assertRaises(SystemExit, utils.readconf, temppath)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
Reference in New Issue
Block a user