diff --git a/tools/conf/create_conf.py b/tools/conf/create_conf.py deleted file mode 100644 index c1fc936673f..00000000000 --- a/tools/conf/create_conf.py +++ /dev/null @@ -1,159 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2012 SINA Corporation -# All Rights Reserved. -# Author: Zhongyue Luo -# -# 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. - -"""Generates a cinder.conf file.""" - -import os -import re -import sys - - -_PY_EXT = ".py" -_FLAGS = "FLAGS" - -_STROPT = "StrOpt" -_BOOLOPT = "BoolOpt" -_INTOPT = "IntOpt" -_FLOATOPT = "FloatOpt" -_LISTOPT = "ListOpt" -_MULTISTROPT = "MultiStrOpt" - -_OPTION_CACHE = list() -_OPTION_REGEX = re.compile(r"(%s)" % "|".join([_STROPT, _BOOLOPT, _INTOPT, - _FLOATOPT, _LISTOPT, - _MULTISTROPT])) - -_BASEDIR = os.path.abspath(os.path.dirname(__file__) + "../../") - - -def main(srcfiles): - - def mod_prefer(mod_str): - prefer = ["flags.py", "log.py", "utils.py", "service.py"] - return prefer.index(mod_str) if mod_str in prefer else ord(mod_str[0]) - - def pkg_prefer(pkg_str): - prefer = ["auth", "api", "vnc", "ipv6", "network", "compute", "virt", - "console", "consoleauth", "image"] - return prefer.index(pkg_str) if pkg_str in prefer else ord(pkg_str[0]) - - print '#' * 20 + '\n# cinder.conf sample #\n' + '#' * 20 - # NOTE(lzyeval): sort top level modules and packages - # to process modules first - print - print '[DEFAULT]' - print - mods_by_pkg = dict() - for filepath in srcfiles: - pkg_name = filepath.split(os.sep)[3] - mod_str = '.'.join(['.'.join(filepath.split(os.sep)[2:-1]), - os.path.basename(filepath).split('.')[0]]) - mods = mods_by_pkg.get(pkg_name, list()) - if not mods: - mods_by_pkg[pkg_name] = mods - mods.append(mod_str) - # NOTE(lzyeval): place top level modules before packages - pkg_names = filter(lambda x: x.endswith(_PY_EXT), mods_by_pkg.keys()) - pkg_names.sort(key=lambda x: mod_prefer(x)) - ext_names = filter(lambda x: x not in pkg_names, mods_by_pkg.keys()) - ext_names.sort(key=lambda x: pkg_prefer(x)) - pkg_names.extend(ext_names) - for pkg_name in pkg_names: - mods = mods_by_pkg.get(pkg_name) - mods.sort() - for mod_str in mods: - print_module(mod_str) - - -def print_module(mod_str): - opts = list() - flags = None - if mod_str.endswith('.__init__'): - mod_str = mod_str[:mod_str.rfind(".")] - try: - __import__(mod_str) - flags = getattr(sys.modules[mod_str], _FLAGS) - except (ValueError, AttributeError), err: - return - except ImportError, ie: - sys.stderr.write("%s\n" % str(ie)) - return - except Exception, e: - return - for opt_name in sorted(flags.keys()): - # check if option was processed - if opt_name in _OPTION_CACHE: - continue - opt_dict = flags._get_opt_info(opt_name) - opts.append(opt_dict['opt']) - _OPTION_CACHE.append(opt_name) - # return if flags has no unique options - if not opts: - return - # print out module info - print '######### defined in %s #########' % mod_str - print - for opt in opts: - print_opt(opt) - print - - -def convert_abspath(s): - """Set up a reasonably sensible default for pybasedir.""" - if not s.startswith(_BASEDIR): - return s - return s.replace(_BASEDIR, '/usr/lib/python/site-packages') - - -def print_opt(opt): - opt_type = None - try: - opt_type = _OPTION_REGEX.search(str(type(opt))).group(0) - except (ValueError, AttributeError), err: - sys.stderr.write("%s\n" % str(err)) - sys.exit(1) - # print out option info - print "######", "".join(["(", opt_type, ")"]), opt.help - - name, default = opt.name, opt.default - - if isinstance(default, basestring): - default = convert_abspath(default) - - if default is None: - print '# %s=' % name - else: - if opt_type == 'StrOpt': - print '# %s="%s"' % (name, default) - elif opt_type == 'ListOpt': - print '# %s="%s"' % (name, ','.join(default)) - elif opt_type == 'MultiStrOpt': - for default in default: - print '# %s="%s"' % (name, default) - elif opt_type == 'BoolOpt': - print '# %s=%s' % (name, str(default).lower()) - else: - print '# %s=%s' % (name, default) - - -if __name__ == '__main__': - if len(sys.argv) < 2: - print "usage: python %s [srcfile]...\n" % sys.argv[0] - sys.exit(0) - main(sys.argv[1:]) - print "#", "Total option count: %d" % len(_OPTION_CACHE) diff --git a/tools/conf/extract_opts.py b/tools/conf/extract_opts.py new file mode 100644 index 00000000000..ebdbe16c6d8 --- /dev/null +++ b/tools/conf/extract_opts.py @@ -0,0 +1,188 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2012 SINA Corporation +# All Rights Reserved. +# Author: Zhongyue Luo +# +# 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).""" + +import os +import re +import socket +import sys +import textwrap + +from cinder.openstack.common import cfg +from cinder.openstack.common import importutils + + +STROPT = "StrOpt" +BOOLOPT = "BoolOpt" +INTOPT = "IntOpt" +FLOATOPT = "FloatOpt" +LISTOPT = "ListOpt" +MULTISTROPT = "MultiStrOpt" + +OPTION_COUNT = 0 +OPTION_REGEX = re.compile(r"(%s)" % "|".join([STROPT, BOOLOPT, INTOPT, + FLOATOPT, LISTOPT, + MULTISTROPT])) +OPTION_HELP_INDENT = "####" + +PY_EXT = ".py" +BASEDIR = os.path.abspath(os.path.join(os.path.dirname(__file__), "../../")) +WORDWRAP_WIDTH = 60 + + +def main(srcfiles): + print '\n'.join(['#' * 20, '# cinder.conf sample #', '#' * 20, + '', '[DEFAULT]', '']) + _list_opts(cfg.CommonConfigOpts, + cfg.__name__ + ':' + cfg.CommonConfigOpts.__name__) + mods_by_pkg = dict() + for filepath in 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 = filter(lambda x: x.endswith(PY_EXT), mods_by_pkg.keys()) + pkg_names.sort() + ext_names = filter(lambda x: x not in pkg_names, mods_by_pkg.keys()) + ext_names.sort() + pkg_names.extend(ext_names) + for pkg_name in pkg_names: + mods = mods_by_pkg.get(pkg_name) + mods.sort() + for mod_str in mods: + _print_module(mod_str) + print "# Total option count: %d" % OPTION_COUNT + + +def _print_module(mod_str): + mod_obj = None + if mod_str.endswith('.__init__'): + mod_str = mod_str[:mod_str.rfind(".")] + try: + mod_obj = importutils.import_module(mod_str) + except (ValueError, AttributeError), err: + return + except ImportError, ie: + sys.stderr.write("%s\n" % str(ie)) + return + except Exception, e: + return + _list_opts(mod_obj, mod_str) + + +def _list_opts(obj, name): + opts = list() + for attr_str in dir(obj): + attr_obj = getattr(obj, attr_str) + if isinstance(attr_obj, cfg.Opt): + opts.append(attr_obj) + elif (isinstance(attr_obj, list) and + all(map(lambda x: isinstance(x, cfg.Opt), attr_obj))): + opts.extend(attr_obj) + if not opts: + return + global OPTION_COUNT + OPTION_COUNT += len(opts) + print '######## defined in %s ########\n' % name + 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 + + +MY_IP = _get_my_ip() +HOST = socket.gethostname() + + +def _sanitize_default(s): + """Set up a reasonably sensible default for pybasedir, my_ip and host.""" + if s.startswith(BASEDIR): + return s.replace(BASEDIR, '/usr/lib/python/site-packages') + elif s == MY_IP: + return '10.0.0.1' + elif s == HOST: + return 'cinder' + elif s.strip() != s: + return '"%s"' % s + return s + + +def _wrap(msg, indent): + padding = ' ' * indent + prefix = "\n%s %s " % (OPTION_HELP_INDENT, padding) + return prefix.join(textwrap.wrap(msg, WORDWRAP_WIDTH)) + + +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_type = None + try: + opt_type = OPTION_REGEX.search(str(type(opt))).group(0) + except (ValueError, AttributeError), err: + sys.stderr.write("%s\n" % str(err)) + sys.exit(1) + try: + if opt_default is None: + print '# %s=' % opt_name + elif opt_type == STROPT: + assert(isinstance(opt_default, basestring)) + print '# %s=%s' % (opt_name, _sanitize_default(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 == MULTISTROPT: + assert(isinstance(opt_default, list)) + for default in opt_default: + print '# %s=%s' % (opt_name, default) + except Exception: + sys.stderr.write('Error in option "%s"\n' % opt_name) + sys.exit(1) + opt_type_tag = "(%s)" % opt_type + print OPTION_HELP_INDENT, opt_type_tag, _wrap(opt_help, len(opt_type_tag)) + print + + +if __name__ == '__main__': + if len(sys.argv) < 2: + print "usage: python %s [srcfile]...\n" % sys.argv[0] + sys.exit(0) + main(sys.argv[1:]) diff --git a/tools/conf/generate_sample.sh b/tools/conf/generate_sample.sh index 7c2842d63d5..cdb86d25651 100755 --- a/tools/conf/generate_sample.sh +++ b/tools/conf/generate_sample.sh @@ -16,10 +16,9 @@ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. -pushd $(cd $(dirname "$0") && pwd) >/dev/null +FILES=$(find cinder -type f -name "*.py" ! -path "cinder/tests/*" -exec \ + grep -l "Opt(" {} \; | sort -u) -find ../../cinder -type f -name "*.py" ! -path "../../cinder/tests/*" -exec \ - grep -l "Opt(" {} \; | sort -u | xargs python create_conf.py > \ - ../../etc/cinder/cinder.conf.sample - -popd >/dev/null +PYTHONPATH=./:${PYTHONPATH} \ + python $(dirname "$0")/extract_opts.py ${FILES} > \ + etc/cinder/cinder.conf.sample