Add support for updating the config file
This commit adds a new flag to the verify_tempest_config.py script,
'-u' that will update the config file from values found during the
verification process.
Partially implements bp config-verification
Change-Id: I20b8bca7d3368b56da0a0496ed7aa3c1a6eacc9e
diff --git a/tools/verify_tempest_config.py b/tools/verify_tempest_config.py
index 1726beb..14dd0c2 100755
--- a/tools/verify_tempest_config.py
+++ b/tools/verify_tempest_config.py
@@ -14,11 +14,14 @@
# License for the specific language governing permissions and limitations
# under the License.
+import argparse
import json
+import os
import sys
import urlparse
import httplib2
+from six.moves import configparser
from tempest import clients
from tempest import config
@@ -26,18 +29,50 @@
CONF = config.CONF
RAW_HTTP = httplib2.Http()
+CONF_FILE = None
+OUTFILE = sys.stdout
-def verify_glance_api_versions(os):
+def _get_config_file():
+ default_config_dir = os.path.join(os.path.abspath(
+ os.path.dirname(os.path.dirname(__file__))), "etc")
+ default_config_file = "tempest.conf"
+
+ conf_dir = os.environ.get('TEMPEST_CONFIG_DIR', default_config_dir)
+ conf_file = os.environ.get('TEMPEST_CONFIG', default_config_file)
+ path = os.path.join(conf_dir, conf_file)
+ fd = open(path, 'rw')
+ return fd
+
+
+def change_option(option, group, value):
+ config_parse = configparser.SafeConfigParser()
+ config_parse.optionxform = str
+ config_parse.readfp(CONF_FILE)
+ if not config_parse.has_section(group):
+ config_parse.add_section(group)
+ config_parse.set(group, option, str(value))
+ global OUTFILE
+ config_parse.write(OUTFILE)
+
+
+def print_and_or_update(option, group, value, update):
+ print('Config option %s in group %s should be changed to: %s'
+ % (option, group, value))
+ if update:
+ change_option(option, group, value)
+
+
+def verify_glance_api_versions(os, update):
# Check glance api versions
__, versions = os.image_client.get_versions()
if CONF.image_feature_enabled.api_v1 != ('v1.1' in versions or 'v1.0' in
versions):
- print('Config option image api_v1 should be change to: %s' % (
- not CONF.image_feature_enabled.api_v1))
+ print_and_or_update('api_v1', 'image_feature_enabled',
+ not CONF.image_feature_enabled.api_v1, update)
if CONF.image_feature_enabled.api_v2 != ('v2.0' in versions):
- print('Config option image api_v2 should be change to: %s' % (
- not CONF.image_feature_enabled.api_v2))
+ print_and_or_update('api_v2', 'image_feature_enabled',
+ not CONF.image_feature_enabled.api_v2, update)
def _get_api_versions(os, service):
@@ -59,33 +94,33 @@
return versions
-def verify_keystone_api_versions(os):
+def verify_keystone_api_versions(os, update):
# Check keystone api versions
versions = _get_api_versions(os, 'keystone')
if CONF.identity_feature_enabled.api_v2 != ('v2.0' in versions):
- print('Config option identity api_v2 should be change to %s' % (
- not CONF.identity_feature_enabled.api_v2))
+ print_and_or_update('api_v2', 'identity_feature_enabled',
+ not CONF.identity_feature_enabled.api_v2, update)
if CONF.identity_feature_enabled.api_v3 != ('v3.0' in versions):
- print('Config option identity api_v3 should be change to %s' % (
- not CONF.identity_feature_enabled.api_v3))
+ print_and_or_update('api_v3', 'identity_feature_enabled',
+ not CONF.identity_feature_enabled.api_v3, update)
-def verify_nova_api_versions(os):
+def verify_nova_api_versions(os, update):
versions = _get_api_versions(os, 'nova')
if CONF.compute_feature_enabled.api_v3 != ('v3.0' in versions):
- print('Config option compute api_v3 should be change to: %s' % (
- not CONF.compute_feature_enabled.api_v3))
+ print_and_or_update('api_v3', 'compute_feature_enabled',
+ not CONF.compute_feature_enabled.api_v3, update)
-def verify_cinder_api_versions(os):
+def verify_cinder_api_versions(os, update):
# Check cinder api versions
versions = _get_api_versions(os, 'cinder')
if CONF.volume_feature_enabled.api_v1 != ('v1.0' in versions):
- print('Config option volume api_v2 should be change to: %s' % (
- not CONF.volume_feature_enabled.api_v1))
+ print_and_or_update('api_v1', 'volume_feature_enabled',
+ not CONF.volume_feature_enabled.api_v1, update)
if CONF.volume_feature_enabled.api_v2 != ('v2.0' in versions):
- print('Config option volume api_v2 should be change to: %s' % (
- not CONF.volume_feature_enabled.api_v2))
+ print_and_or_update('api_v2', 'volume_feature_enabled',
+ not CONF.volume_feature_enabled.api_v2, update)
def get_extension_client(os, service):
@@ -139,7 +174,7 @@
results[service] = {}
extensions_opt = get_enabled_extensions(service)
if extensions_opt[0] == 'all':
- results[service]['extensions'] = 'all'
+ results[service]['extensions'] = extensions
return results
# Verify that all configured extensions are actually enabled
for extension in extensions_opt:
@@ -152,24 +187,54 @@
return results
-def display_results(results):
+def display_results(results, update, replace):
+ update_dict = {
+ 'swift': 'object-storage-feature-enabled',
+ 'nova': 'compute-feature-enabled',
+ 'nova_v3': 'compute-feature-enabled',
+ 'cinder': 'volume-feature-enabled',
+ 'neutron': 'network-feature-enabled',
+ }
for service in results:
# If all extensions are specified as being enabled there is no way to
# verify this so we just assume this to be true
if results[service].get('extensions'):
- continue
- extension_list = get_enabled_extensions(service)
- for extension in results[service]:
- if not results[service][extension]:
- if extension in extension_list:
- print("%s extension: %s should not be included in the list"
- " of enabled extensions" % (service, extension))
+ if replace:
+ output_list = results[service].get('extensions')
+ else:
+ output_list = ['all']
+ else:
+ extension_list = get_enabled_extensions(service)
+ output_list = []
+ for extension in results[service]:
+ if not results[service][extension]:
+ if extension in extension_list:
+ print("%s extension: %s should not be included in the "
+ "list of enabled extensions" % (service,
+ extension))
+ else:
+ print("%s extension: %s should be included in the list"
+ " of enabled extensions" % (service, extension))
+ output_list.append(extension)
else:
- print("%s extension: %s should be included in the list of "
- "enabled extensions" % (service, extension))
+ output_list.append(extension)
+ if update:
+ # Sort List
+ output_list.sort()
+ # Convert list to a string
+ output_string = ', '.join(output_list)
+ if service == 'swift':
+ change_option('discoverable_apis', update_dict[service],
+ output_string)
+ elif service == 'nova_v3':
+ change_option('api_v3_extensions', update_dict[service],
+ output_string)
+ else:
+ change_option('api_extensions', update_dict[service],
+ output_string)
-def check_service_availability(os):
+def check_service_availability(os, update):
services = []
avail_services = []
codename_match = {
@@ -207,21 +272,59 @@
print('Endpoint type %s not found either disable service '
'%s or fix the catalog_type in the config file' % (
catalog_type, codename_match[cfgname]))
+ if update:
+ change_option(codename_match[cfgname],
+ 'service_available', False)
else:
if not getattr(CONF.service_available,
codename_match[cfgname]):
print('Endpoint type %s is available, service %s should be'
' set as available in the config file.' % (
catalog_type, codename_match[cfgname]))
+ if update:
+ change_option(codename_match[cfgname],
+ 'service_available', True)
else:
avail_services.append(codename_match[cfgname])
return avail_services
+def parse_args():
+ parser = argparse.ArgumentParser()
+ parser.add_argument('-u', '--update', action='store_true',
+ help='Update the config file with results from api '
+ 'queries. This assumes whatever is set in the '
+ 'config file is incorrect. In the case of '
+ 'endpoint checks where it could either be the '
+ 'incorrect catalog type or the service available '
+ 'option the service available option is assumed '
+ 'to be incorrect and is thus changed')
+ parser.add_argument('-o', '--output',
+ help="Output file to write an updated config file to. "
+ "This has to be a separate file from the "
+ "original config file. If one isn't specified "
+ "with -u the new config file will be printed to "
+ "STDOUT")
+ parser.add_argument('-r', '--replace-ext', action='store_true',
+ help="If specified the all option will be replaced "
+ "with a full list of extensions")
+ args = parser.parse_args()
+ return args
+
+
def main(argv):
print('Running config verification...')
+ opts = parse_args()
+ update = opts.update
+ replace = opts.replace_ext
+ global CONF_FILE
+ global OUTFILE
+ if update:
+ CONF_FILE = _get_config_file()
+ if opts.output:
+ OUTFILE = open(opts.output, 'w+')
os = clients.ComputeAdminManager(interface='json')
- services = check_service_availability(os)
+ services = check_service_availability(os, update)
results = {}
for service in ['nova', 'nova_v3', 'cinder', 'neutron', 'swift']:
if service == 'nova_v3' and 'nova' not in services:
@@ -229,11 +332,14 @@
elif service not in services:
continue
results = verify_extensions(os, service, results)
- verify_keystone_api_versions(os)
- verify_glance_api_versions(os)
- verify_nova_api_versions(os)
- verify_cinder_api_versions(os)
- display_results(results)
+ verify_keystone_api_versions(os, update)
+ verify_glance_api_versions(os, update)
+ verify_nova_api_versions(os, update)
+ verify_cinder_api_versions(os, update)
+ display_results(results, update, replace)
+ if CONF_FILE:
+ CONF_FILE.close()
+ OUTFILE.close()
if __name__ == "__main__":