diff --git a/etc/oslo-config-generator/manila.conf b/etc/oslo-config-generator/manila.conf new file mode 100644 index 00000000..858b75df --- /dev/null +++ b/etc/oslo-config-generator/manila.conf @@ -0,0 +1,6 @@ +[DEFAULT] +output_file = etc/manila/manila.conf.sample +namespace = manila +namespace = oslo.messaging +namespace = oslo.db +namespace = oslo.db.concurrency diff --git a/manila/openstack/common/config/__init__.py b/manila/openstack/common/config/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/manila/openstack/common/config/generator.py b/manila/openstack/common/config/generator.py deleted file mode 100644 index cb02bf38..00000000 --- a/manila/openstack/common/config/generator.py +++ /dev/null @@ -1,313 +0,0 @@ -# Copyright 2012 SINA Corporation -# Copyright 2014 Cisco Systems, Inc. -# 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. -# - -"""Extracts OpenStack config option info from module(s).""" - -from __future__ import print_function - -import argparse -import imp -import os -import re -import socket -import sys -import textwrap - -from oslo.config import cfg -import six -import stevedore.named - -from manila.openstack.common import gettextutils -from manila.openstack.common import importutils - -gettextutils.install('manila') - -STROPT = "StrOpt" -BOOLOPT = "BoolOpt" -INTOPT = "IntOpt" -FLOATOPT = "FloatOpt" -LISTOPT = "ListOpt" -DICTOPT = "DictOpt" -MULTISTROPT = "MultiStrOpt" - -OPT_TYPES = { - STROPT: 'string value', - BOOLOPT: 'boolean value', - INTOPT: 'integer value', - FLOATOPT: 'floating point value', - LISTOPT: 'list value', - DICTOPT: 'dict value', - MULTISTROPT: 'multi valued', -} - -OPTION_REGEX = re.compile(r"(%s)" % "|".join([STROPT, BOOLOPT, INTOPT, - FLOATOPT, LISTOPT, DICTOPT, - MULTISTROPT])) - -PY_EXT = ".py" -BASEDIR = os.path.abspath(os.path.join(os.path.dirname(__file__), - "../../../../")) -WORDWRAP_WIDTH = 60 - - -def raise_extension_exception(extmanager, ep, err): - raise - - -def generate(argv): - parser = argparse.ArgumentParser( - description='generate sample configuration file', - ) - parser.add_argument('-m', dest='modules', action='append') - parser.add_argument('-l', dest='libraries', action='append') - parser.add_argument('srcfiles', nargs='*') - parsed_args = parser.parse_args(argv) - - mods_by_pkg = dict() - for filepath in parsed_args.srcfiles: - pkg_name = filepath.split(os.sep)[1] - mod_str = '.'.join(['.'.join(filepath.split(os.sep)[:-1]), - os.path.basename(filepath).split('.')[0]]) - mods_by_pkg.setdefault(pkg_name, list()).append(mod_str) - # NOTE(lzyeval): place top level modules before packages - pkg_names = sorted(pkg for pkg in mods_by_pkg if pkg.endswith(PY_EXT)) - ext_names = sorted(pkg for pkg in mods_by_pkg if pkg not in pkg_names) - pkg_names.extend(ext_names) - - # opts_by_group is a mapping of group name to an options list - # The options list is a list of (module, options) tuples - opts_by_group = {'DEFAULT': []} - - if parsed_args.modules: - for module_name in parsed_args.modules: - module = _import_module(module_name) - if module: - for group, opts in _list_opts(module): - opts_by_group.setdefault(group, []).append((module_name, - opts)) - - # Look for entry points defined in libraries (or applications) for - # option discovery, and include their return values in the output. - # - # Each entry point should be a function returning an iterable - # of pairs with the group name (or None for the default group) - # and the list of Opt instances for that group. - if parsed_args.libraries: - loader = stevedore.named.NamedExtensionManager( - 'oslo.config.opts', - names=list(set(parsed_args.libraries)), - invoke_on_load=False, - on_load_failure_callback=raise_extension_exception - ) - for ext in loader: - for group, opts in ext.plugin(): - opt_list = opts_by_group.setdefault(group or 'DEFAULT', []) - opt_list.append((ext.name, opts)) - - for pkg_name in pkg_names: - mods = mods_by_pkg.get(pkg_name) - mods.sort() - for mod_str in mods: - if mod_str.endswith('.__init__'): - mod_str = mod_str[:mod_str.rfind(".")] - - mod_obj = _import_module(mod_str) - if not mod_obj: - raise RuntimeError("Unable to import module %s" % mod_str) - - for group, opts in _list_opts(mod_obj): - opts_by_group.setdefault(group, []).append((mod_str, opts)) - - print_group_opts('DEFAULT', opts_by_group.pop('DEFAULT', [])) - for group in sorted(opts_by_group.keys()): - print_group_opts(group, opts_by_group[group]) - - -def _import_module(mod_str): - try: - if mod_str.startswith('bin.'): - imp.load_source(mod_str[4:], os.path.join('bin', mod_str[4:])) - return sys.modules[mod_str[4:]] - else: - return importutils.import_module(mod_str) - except Exception as e: - sys.stderr.write("Error importing module %s: %s\n" % (mod_str, str(e))) - return None - - -def _is_in_group(opt, group): - """Check if opt is in group.""" - for value in group._opts.values(): - # NOTE(llu): Temporary workaround for bug #1262148, wait until - # newly released oslo.config support '==' operator. - if not(value['opt'] != opt): - return True - return False - - -def _guess_groups(opt): - # is it in the DEFAULT group? - if _is_in_group(opt, cfg.CONF): - return 'DEFAULT' - - # what other groups is it in? - for value in cfg.CONF.values(): - if isinstance(value, cfg.CONF.GroupAttr): - if _is_in_group(opt, value._group): - return value._group.name - - raise RuntimeError( - "Unable to find group for option %s, " - "maybe it's defined twice in the same group?" - % opt.name - ) - - -def _list_opts(obj): - def is_opt(o): - return (isinstance(o, cfg.Opt) and - not isinstance(o, cfg.SubCommandOpt)) - - opts = list() - for attr_str in dir(obj): - attr_obj = getattr(obj, attr_str) - if is_opt(attr_obj): - opts.append(attr_obj) - elif (isinstance(attr_obj, list) and - all(map(lambda x: is_opt(x), attr_obj))): - opts.extend(attr_obj) - - ret = {} - for opt in opts: - ret.setdefault(_guess_groups(opt), []).append(opt) - return ret.items() - - -def print_group_opts(group, opts_by_module): - print("[%s]" % group) - print('') - for mod, opts in opts_by_module: - print('#') - print('# Options defined in %s' % mod) - print('#') - print('') - for opt in opts: - _print_opt(opt) - print('') - - -def _get_my_ip(): - try: - csock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - csock.connect(('8.8.8.8', 80)) - (addr, port) = csock.getsockname() - csock.close() - return addr - except socket.error: - return None - - -def _sanitize_default(name, value): - """Set up a reasonably sensible default for pybasedir, my_ip and host.""" - hostname = socket.gethostname() - fqdn = socket.getfqdn() - if value.startswith(sys.prefix): - # NOTE(jd) Don't use os.path.join, because it is likely to think the - # second part is an absolute pathname and therefore drop the first - # part. - value = os.path.normpath("/usr/" + value[len(sys.prefix):]) - elif value.startswith(BASEDIR): - return value.replace(BASEDIR, '/usr/lib/python/site-packages') - elif BASEDIR in value: - return value.replace(BASEDIR, '') - elif value == _get_my_ip(): - return '10.0.0.1' - elif value in (hostname, fqdn): - if 'host' in name: - return 'manila' - elif value.endswith(hostname): - return value.replace(hostname, 'manila') - elif value.endswith(fqdn): - return value.replace(fqdn, 'manila') - elif value.strip() != value: - return '"%s"' % value - return value - - -def _print_opt(opt): - opt_name, opt_default, opt_help = opt.dest, opt.default, opt.help - if not opt_help: - sys.stderr.write('WARNING: "%s" is missing help string.\n' % opt_name) - opt_help = "" - try: - opt_type = OPTION_REGEX.search(str(type(opt))).group(0) - except (ValueError, AttributeError) as err: - sys.stderr.write("%s\n" % str(err)) - sys.exit(1) - opt_help = u'%s (%s)' % (opt_help, - OPT_TYPES[opt_type]) - print('#', "\n# ".join(textwrap.wrap(opt_help, WORDWRAP_WIDTH))) - if opt.deprecated_opts: - for deprecated_opt in opt.deprecated_opts: - if deprecated_opt.name: - deprecated_group = (deprecated_opt.group if - deprecated_opt.group else "DEFAULT") - print('# Deprecated group/name - [%s]/%s' % - (deprecated_group, - deprecated_opt.name)) - try: - if opt_default is None: - print('#%s=' % opt_name) - elif opt_type == STROPT: - assert(isinstance(opt_default, six.string_types)) - print('#%s=%s' % (opt_name, _sanitize_default(opt_name, - opt_default))) - elif opt_type == BOOLOPT: - assert(isinstance(opt_default, bool)) - print('#%s=%s' % (opt_name, str(opt_default).lower())) - elif opt_type == INTOPT: - assert(isinstance(opt_default, int) and - not isinstance(opt_default, bool)) - print('#%s=%s' % (opt_name, opt_default)) - elif opt_type == FLOATOPT: - assert(isinstance(opt_default, float)) - print('#%s=%s' % (opt_name, opt_default)) - elif opt_type == LISTOPT: - assert(isinstance(opt_default, list)) - print('#%s=%s' % (opt_name, ','.join(opt_default))) - elif opt_type == DICTOPT: - assert(isinstance(opt_default, dict)) - opt_default_strlist = [str(key) + ':' + str(value) - for (key, value) in opt_default.items()] - print('#%s=%s' % (opt_name, ','.join(opt_default_strlist))) - elif opt_type == MULTISTROPT: - assert(isinstance(opt_default, list)) - if not opt_default: - opt_default = [''] - for default in opt_default: - print('#%s=%s' % (opt_name, default)) - print('') - except Exception: - sys.stderr.write('Error in option "%s"\n' % opt_name) - sys.exit(1) - - -def main(): - generate(sys.argv[1:]) - -if __name__ == '__main__': - main() diff --git a/manila/opts.py b/manila/opts.py new file mode 100644 index 00000000..619b5fc1 --- /dev/null +++ b/manila/opts.py @@ -0,0 +1,121 @@ +# Copyright (c) 2014 SUSE Linux Products GmbH. +# +# 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. + +__all__ = [ + 'list_opts' +] + + +import copy +import itertools + + +import manila.api.middleware.auth +import manila.api.middleware.sizelimit +import manila.common.config +import manila.compute +import manila.compute.nova +import manila.db.api +import manila.db.base +import manila.exception +import manila.network +import manila.network.linux.interface +import manila.network.neutron.api +import manila.openstack.common.eventlet_backdoor +import manila.openstack.common.lockutils +import manila.openstack.common.log +import manila.openstack.common.policy +import manila.openstack.common.sslutils +import manila.quota +import manila.scheduler.driver +import manila.scheduler.host_manager +import manila.scheduler.manager +import manila.scheduler.scheduler_options +import manila.scheduler.simple +import manila.scheduler.weights +import manila.scheduler.weights.capacity +import manila.service +import manila.share.api +import manila.share.driver +import manila.share.drivers.emc.driver +import manila.share.drivers.generic +import manila.share.drivers.glusterfs +import manila.share.drivers.glusterfs_native +import manila.share.drivers.netapp.cluster_mode +import manila.share.drivers.service_instance +import manila.share.manager +import manila.volume +import manila.volume.cinder +import manila.wsgi + +# List of *all* options in [DEFAULT] namespace of manila. +# Any new option list or option needs to be registered here. +_global_opt_lists = [ + # Keep list alphabetically sorted + [manila.api.middleware.auth.use_forwarded_for_opt], + [manila.api.middleware.sizelimit.max_request_body_size_opt], + manila.common.config.core_opts, + manila.common.config.debug_opts, + manila.common.config.global_opts, + manila.compute._compute_opts, + manila.compute.nova.nova_opts, + manila.db.api.db_opts, + [manila.db.base.db_driver_opt], + manila.exception.exc_log_opts, + manila.network.linux.interface.OPTS, + manila.network.network_opts, + manila.network.neutron.api.neutron_opts, + manila.openstack.common.eventlet_backdoor.eventlet_backdoor_opts, + manila.openstack.common.lockutils.util_opts, + manila.openstack.common.log.common_cli_opts, + manila.openstack.common.log.generic_log_opts, + manila.openstack.common.log.log_opts, + manila.openstack.common.log.logging_cli_opts, + manila.openstack.common.policy.policy_opts, + manila.quota.quota_opts, + manila.scheduler.driver.scheduler_driver_opts, + manila.scheduler.host_manager.host_manager_opts, + manila.scheduler.host_manager.host_manager_opts, + [manila.scheduler.manager.scheduler_driver_opt], + [manila.scheduler.scheduler_options.scheduler_json_config_location_opt], + manila.scheduler.simple.simple_scheduler_opts, + manila.scheduler.simple.simple_scheduler_opts, + manila.scheduler.weights.capacity.capacity_weight_opts, + manila.scheduler.weights.capacity.capacity_weight_opts, + manila.service.service_opts, + manila.share.api.share_api_opts, + manila.share.driver.share_opts, + manila.share.drivers.emc.driver.EMC_NAS_OPTS, + manila.share.drivers.generic.share_opts, + manila.share.drivers.glusterfs.GlusterfsManilaShare_opts, + manila.share.drivers.glusterfs_native.glusterfs_native_manila_share_opts, + manila.share.drivers.netapp.cluster_mode.NETAPP_NAS_OPTS, + manila.share.drivers.service_instance.server_opts, + manila.share.manager.share_manager_opts, + manila.volume._volume_opts, + manila.volume.cinder.cinder_opts, + manila.wsgi.eventlet_opts, + manila.wsgi.socket_opts, +] + +_opts = [ + (None, list(itertools.chain(*_global_opt_lists))), + # ssl namespace: + ("ssl", manila.openstack.common.sslutils.ssl_opts) +] + + +def list_opts(): + """Return a list of oslo.config options available in Manila.""" + return [(m, copy.deepcopy(o)) for m, o in _opts] diff --git a/openstack-common.conf b/openstack-common.conf index 9e32d20d..747fb32b 100644 --- a/openstack-common.conf +++ b/openstack-common.conf @@ -1,7 +1,6 @@ [DEFAULT] # The list of modules to copy from openstack-common -module=config module=context module=eventlet_backdoor # TODO(jaegerandi) remove excutils with next sync of oslo-incubator @@ -35,9 +34,6 @@ module=versionutils # The list of scripts to copy from oslo common code script = tools/colorizer.py -script = tools/config/README -script = tools/config/check_uptodate.sh -script = tools/config/generate_sample.sh script = tools/install_venv.py script = tools/install_venv_common.py script = tools/with_venv.sh diff --git a/setup.cfg b/setup.cfg index cf385586..d01b311d 100644 --- a/setup.cfg +++ b/setup.cfg @@ -50,6 +50,8 @@ oslo.messaging.notify.drivers = manila.openstack.common.notifier.rpc_notifier2 = oslo.messaging.notify._impl_messaging:MessagingV2Driver manila.openstack.common.notifier.rpc_notifier = oslo.messaging.notify._impl_messaging:MessagingDriver manila.openstack.common.notifier.test_notifier = oslo.messaging.notify._impl_test:TestDriver +oslo.config.opts = + manila = manila.opts:list_opts [build_sphinx] all_files = 1 diff --git a/tools/config/README b/tools/config/README deleted file mode 100644 index c6079dab..00000000 --- a/tools/config/README +++ /dev/null @@ -1,38 +0,0 @@ -This generate_sample.sh tool is used to generate sample config files -from OpenStack project source trees. - -Run it by passing the base directory and package name i.e. - - $> generate_sample.sh --base-dir /opt/stack/nova --package-name nova \ - --output-dir /opt/stack/nova/etc - $> generate_sample.sh -b /opt/stack/neutron -p nova -o /opt/stack/neutron/etc - -Optionally, include libraries that register entry points for option -discovery, such as oslo.messaging: - - $> generate_sample.sh -b /opt/stack/ceilometer -p ceilometer \ - -o /opt/stack/ceilometer/etc -l oslo.messaging - -Watch out for warnings about modules like libvirt, qpid and zmq not -being found - these warnings are significant because they result -in options not appearing in the generated config file. - - - -This check_uptodate.sh tool is used to ensure that the generated sample -config file in the OpenStack project source tree is continually kept up -to date with the code itself. - -This can be done by adding a hook to tox.ini. For example, if a project -already had flake8 enabled in a section like this: - - [testenv.pep8] - commands = - flake8 {posargs} - -This section would be changed to: - - [testenv.pep8] - commands = - flake8 {posargs} - {toxinidir}/tools/config/check_uptodate.sh diff --git a/tools/config/check_uptodate.sh b/tools/config/check_uptodate.sh deleted file mode 100755 index ac42fd2a..00000000 --- a/tools/config/check_uptodate.sh +++ /dev/null @@ -1,29 +0,0 @@ -#!/usr/bin/env bash - -PROJECT_NAME=${PROJECT_NAME:-manila} -CFGFILE_NAME=${PROJECT_NAME}.conf.sample - -if [ -e etc/${PROJECT_NAME}/${CFGFILE_NAME} ]; then - CFGFILE=etc/${PROJECT_NAME}/${CFGFILE_NAME} -elif [ -e etc/${CFGFILE_NAME} ]; then - CFGFILE=etc/${CFGFILE_NAME} -else - echo "${0##*/}: can not find config file" - exit 1 -fi - -TEMPDIR=`mktemp -d /tmp/${PROJECT_NAME}.XXXXXX` -trap "rm -rf $TEMPDIR" EXIT - -tools/config/generate_sample.sh -b ./ -p ${PROJECT_NAME} -o ${TEMPDIR} -if [ $? != 0 ] -then - exit 1 -fi - -if ! diff -u ${TEMPDIR}/${CFGFILE_NAME} ${CFGFILE} -then - echo "${0##*/}: ${PROJECT_NAME}.conf.sample is not up to date." - echo "${0##*/}: Please run ${0%%${0##*/}}generate_sample.sh." - exit 1 -fi diff --git a/tools/config/generate_sample.sh b/tools/config/generate_sample.sh deleted file mode 100755 index a8cb9495..00000000 --- a/tools/config/generate_sample.sh +++ /dev/null @@ -1,138 +0,0 @@ -#!/usr/bin/env bash - -# Generate sample configuration for your project. -# -# Aside from the command line flags, it also respects a config file which -# should be named oslo.config.generator.rc and be placed in the same directory. -# -# You can then export the following variables: -# MANILA_CONFIG_GENERATOR_EXTRA_MODULES: list of modules to interrogate for options. -# MANILA_CONFIG_GENERATOR_EXTRA_LIBRARIES: list of libraries to discover. -# MANILA_CONFIG_GENERATOR_EXCLUDED_FILES: list of files to remove from automatic listing. - -print_hint() { - echo "Try \`${0##*/} --help' for more information." >&2 -} - -PARSED_OPTIONS=$(getopt -n "${0##*/}" -o hb:p:m:l:o: \ - --long help,base-dir:,package-name:,output-dir:,module:,library: -- "$@") - -if [ $? != 0 ] ; then print_hint ; exit 1 ; fi - -eval set -- "$PARSED_OPTIONS" - -while true; do - case "$1" in - -h|--help) - echo "${0##*/} [options]" - echo "" - echo "options:" - echo "-h, --help show brief help" - echo "-b, --base-dir=DIR project base directory" - echo "-p, --package-name=NAME project package name" - echo "-o, --output-dir=DIR file output directory" - echo "-m, --module=MOD extra python module to interrogate for options" - echo "-l, --library=LIB extra library that registers options for discovery" - exit 0 - ;; - -b|--base-dir) - shift - BASEDIR=`echo $1 | sed -e 's/\/*$//g'` - shift - ;; - -p|--package-name) - shift - PACKAGENAME=`echo $1` - shift - ;; - -o|--output-dir) - shift - OUTPUTDIR=`echo $1 | sed -e 's/\/*$//g'` - shift - ;; - -m|--module) - shift - MODULES="$MODULES -m $1" - shift - ;; - -l|--library) - shift - LIBRARIES="$LIBRARIES -l $1" - shift - ;; - --) - break - ;; - esac -done - -BASEDIR=${BASEDIR:-`pwd`} -if ! [ -d $BASEDIR ] -then - echo "${0##*/}: missing project base directory" >&2 ; print_hint ; exit 1 -elif [[ $BASEDIR != /* ]] -then - BASEDIR=$(cd "$BASEDIR" && pwd) -fi - -PACKAGENAME=${PACKAGENAME:-$(python setup.py --name)} -TARGETDIR=$BASEDIR/$PACKAGENAME -if ! [ -d $TARGETDIR ] -then - echo "${0##*/}: invalid project package name" >&2 ; print_hint ; exit 1 -fi - -OUTPUTDIR=${OUTPUTDIR:-$BASEDIR/etc} -# NOTE(bnemec): Some projects put their sample config in etc/, -# some in etc/$PACKAGENAME/ -if [ -d $OUTPUTDIR/$PACKAGENAME ] -then - OUTPUTDIR=$OUTPUTDIR/$PACKAGENAME -elif ! [ -d $OUTPUTDIR ] -then - echo "${0##*/}: cannot access \`$OUTPUTDIR': No such file or directory" >&2 - exit 1 -fi - -BASEDIRESC=`echo $BASEDIR | sed -e 's/\//\\\\\//g'` -find $TARGETDIR -type f -name "*.pyc" -delete -FILES=$(find $TARGETDIR -type f -name "*.py" ! -path "*/tests/*" \ - -exec grep -l "Opt(" {} + | sed -e "s/^$BASEDIRESC\///g" | sort -u) - -RC_FILE="`dirname $0`/oslo.config.generator.rc" -if test -r "$RC_FILE" -then - source "$RC_FILE" -fi - -for filename in ${MANILA_CONFIG_GENERATOR_EXCLUDED_FILES}; do - FILES="${FILES[@]/$filename/}" -done - -for mod in ${MANILA_CONFIG_GENERATOR_EXTRA_MODULES}; do - MODULES="$MODULES -m $mod" -done - -for lib in ${MANILA_CONFIG_GENERATOR_EXTRA_LIBRARIES}; do - LIBRARIES="$LIBRARIES -l $lib" -done - -export EVENTLET_NO_GREENDNS=yes - -OS_VARS=$(set | sed -n '/^OS_/s/=[^=]*$//gp' | xargs) -[ "$OS_VARS" ] && eval "unset \$OS_VARS" -DEFAULT_MODULEPATH=manila.openstack.common.config.generator -MODULEPATH=${MODULEPATH:-$DEFAULT_MODULEPATH} -OUTPUTFILE=$OUTPUTDIR/$PACKAGENAME.conf.sample -python -m $MODULEPATH $MODULES $LIBRARIES $FILES > $OUTPUTFILE -if [ $? != 0 ] -then - echo "Can not generate $OUTPUTFILE" - exit 1 -fi - -# Hook to allow projects to append custom config file snippets -CONCAT_FILES=$(ls $BASEDIR/tools/config/*.conf.sample 2>/dev/null) -for CONCAT_FILE in $CONCAT_FILES; do - cat $CONCAT_FILE >> $OUTPUTFILE -done diff --git a/tools/config/oslo.config.generator.rc b/tools/config/oslo.config.generator.rc deleted file mode 100644 index f6bdecde..00000000 --- a/tools/config/oslo.config.generator.rc +++ /dev/null @@ -1 +0,0 @@ -export MANILA_CONFIG_GENERATOR_EXTRA_LIBRARIES="oslo.messaging oslo.db oslo.db.concurrency" diff --git a/tox.ini b/tox.ini index e55ef039..66a3f6ac 100644 --- a/tox.ini +++ b/tox.ini @@ -21,7 +21,7 @@ commands = [testenv:genconfig] commands = - bash tools/config/generate_sample.sh -o etc/manila + oslo-config-generator --config-file etc/oslo-config-generator/manila.conf [testenv:venv] commands = {posargs}