cinder/tools/config/generate_cinder_opts.py
Eric Harney d3abafdee4 Move config-generator to tools
Moving this out of cinder/ separates it from the
actual run-time Cinder code.

Change-Id: I056f40120fdef60a0dc1a5926729748fd2835938
2017-08-16 16:18:48 -04:00

249 lines
8.9 KiB
Python

#!/usr/bin/env python
# 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 collections
import os
import subprocess
import textwrap
from cinder.volume import configuration
OrderedDict = collections.OrderedDict
BASEDIR = os.path.split(os.path.realpath(__file__))[0] + "/../../"
if __name__ == "__main__":
os.chdir(BASEDIR)
opt_file = open("cinder/opts.py", 'w')
opt_dict = OrderedDict()
dir_trees_list = []
REGISTER_OPTS_STR = "CONF.register_opts("
REGISTER_OPT_STR = "CONF.register_opt("
license_str = textwrap.dedent(
"""
# 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.\n
""")
opt_file.write(license_str)
edit_header = textwrap.dedent(
"""
###################################################################
# WARNING!
#
# Do not edit this file directly. This file should be generated by
# running the command "tox -e genopts" any time a config option
# has been added, changed, or removed.
###################################################################\n
""")
opt_file.write(edit_header)
opt_file.write("import itertools\n\n")
# NOTE(geguileo): We need to register all OVOs before importing any other
# cinder files, otherwise any decorator that uses cinder.objects.YYY will
# fail with exception AttributeError: 'module' object has no attribute
# 'YYY' when running tox -egenconfig
opt_file.write("from cinder import objects\nobjects.register_all()\n\n")
targetdir = 'cinder'
common_string = ('find ' + targetdir + ' -type f -name "*.py" ! '
'-path "*/tests/*" -exec grep -l "%s" {} '
'+ | sed -e "s|^' + BASEDIR +
'|/|g" | sort -u')
cmd_opts = common_string % REGISTER_OPTS_STR
output_opts = subprocess.check_output( # nosec : command is hardcoded
'{}'.format(cmd_opts), shell=True,
universal_newlines=True)
dir_trees_list = output_opts.split()
cmd_opt = common_string % REGISTER_OPT_STR
output_opt = subprocess.check_output( # nosec : command is hardcoded
'{}'.format(cmd_opt), shell=True,
universal_newlines=True)
temp_list = output_opt.split()
for item in temp_list:
dir_trees_list.append(item)
dir_trees_list.sort()
flag = False
def _check_import(aline):
if len(aline) > 79:
new_lines = aline.partition(' as ')
return new_lines
else:
return [aline]
for atree in dir_trees_list:
if atree in ["cinder/config/generate_cinder_opts.py",
"cinder/hacking/checks.py",
"cinder/volume/configuration.py",
"cinder/test.py"]:
continue
dirs_list = atree.split('/')
import_module = "from "
init_import_module = ""
import_name = ""
for dir in dirs_list:
if dir.find(".py") == -1:
import_module += dir + "."
init_import_module += dir + "."
import_name += dir + "_"
else:
if dir[:-3] != "__init__":
import_name += dir[:-3].replace("_", "")
import_module = (import_module[:-1] + " import " +
dir[:-3] + " as " + import_name)
lines = _check_import(import_module)
if len(lines) > 1:
opt_file.write(lines[0] + lines[1] + "\\\n")
opt_file.write(" " + lines[2] + "\n")
else:
opt_file.write(lines[0] + "\n")
else:
import_name = import_name[:-1].replace('/', '.')
init_import = atree[:-12].replace('/', '.')
opt_file.write("import " + init_import + "\n")
flag = True
if flag is False:
opt_dict[import_name] = atree
else:
opt_dict[init_import_module.strip(".")] = atree
flag = False
registered_opts_dict = OrderedDict([('DEFAULT', [])])
def _write_item(opts):
list_name = opts[-3:]
if list_name.lower() == "opt":
line_to_write = " [" + opts.strip("\n") + "],\n"
opt_line = _check_line_length(line_to_write)
if len(opt_line) > 1:
opt_file.write(opt_line[0] + opt_line[1] + "\n")
opt_file.write(" " + opt_line[2])
else:
opt_file.write(opt_line[0])
else:
line_to_write = " " + opts.strip("\n") + ",\n"
opt_line = _check_line_length(line_to_write)
if len(opt_line) > 1:
opt_file.write(opt_line[0] + opt_line[1] + "\n")
opt_file.write(" " + opt_line[2])
else:
opt_file.write(opt_line[0])
def _retrieve_name(aline):
if REGISTER_OPT_STR in aline:
str_to_replace = REGISTER_OPT_STR
else:
str_to_replace = REGISTER_OPTS_STR
return aline.replace(str_to_replace, "")
def _check_line_length(aline):
if len(aline) > 79:
temp = aline.split(".")
lines_to_write = []
for section in temp:
lines_to_write.append(section)
lines_to_write.append('.')
return lines_to_write
else:
return [aline]
for key in opt_dict:
fd = os.open(opt_dict[key], os.O_RDONLY)
afile = os.fdopen(fd, "r")
for aline in afile:
exists = aline.find("CONF.register_opt")
if exists != -1:
# TODO(kjnelson) FIX THIS LATER. These are instances where
# CONF.register_opts is happening without actually registering
# real lists of opts
exists = aline.find('base_san_opts')
if (exists != -1) or (key == 'cinder_volume_configuration'):
continue
group_exists = aline.find(', group=')
formatted_opt = _retrieve_name(aline[: group_exists])
formatted_opt = formatted_opt.replace(')', '').strip()
if group_exists != -1:
group_name = aline[group_exists:-1].replace(
', group=\"\'', '').replace(
', group=', '').strip(
"\'\")").upper()
# NOTE(dulek): Hack to resolve constants manually.
if (group_name.endswith('SHARED_CONF_GROUP')
or group_name.lower() == 'backend_defaults'):
group_name = configuration.SHARED_CONF_GROUP
if group_name in registered_opts_dict:
line = key + "." + formatted_opt
registered_opts_dict[group_name].append(line)
else:
line = key + "." + formatted_opt
registered_opts_dict[group_name] = [line]
else:
line = key + "." + formatted_opt
registered_opts_dict['DEFAULT'].append(line)
setup_str = ("\n\n"
"def list_opts():\n"
" return [\n")
opt_file.write(setup_str)
registered_opts_dict = OrderedDict(sorted(registered_opts_dict.items(),
key = lambda x: x[0]))
for key in registered_opts_dict:
section_start_str = (" ('" + key + "',\n"
" itertools.chain(\n")
opt_file.write(section_start_str)
for item in registered_opts_dict[key]:
_write_item(item)
section_end_str = " )),\n"
opt_file.write(section_end_str)
closing_str = (" ]\n")
opt_file.write(closing_str)
opt_file.close()