345 lines
11 KiB
Python
345 lines
11 KiB
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 json
|
|
import sys
|
|
|
|
from oslo_upgradecheck import upgradecheck
|
|
|
|
from django.conf import settings
|
|
from django.core.management.base import BaseCommand
|
|
from django.utils.translation import ugettext_lazy as _
|
|
|
|
from openstack_dashboard import defaults
|
|
|
|
|
|
CHECKS = []
|
|
|
|
|
|
def register_check(name):
|
|
def register(func):
|
|
CHECKS.append((name, func))
|
|
return register
|
|
|
|
|
|
@register_check(_("Unknown Settings"))
|
|
def check_invalid_settings(dummy=None):
|
|
# This list can be updated using the tools/find_settings.py script.
|
|
KNOWN_SETTINGS_NON_DASHBOARD = [
|
|
'ABSOLUTE_URL_OVERRIDES',
|
|
'ADD_INSTALLED_APPS',
|
|
'ADD_TEMPLATE_DIRS',
|
|
'ADD_TEMPLATE_LOADERS',
|
|
'ADMINS',
|
|
'ALLOWED_HOSTS',
|
|
'APPEND_SLASH',
|
|
'AUTHENTICATION_BACKENDS',
|
|
'AUTH_PASSWORD_VALIDATORS',
|
|
'AUTH_USER_MODEL',
|
|
'CACHED_TEMPLATE_LOADERS',
|
|
'CACHES',
|
|
'CACHE_MIDDLEWARE_ALIAS',
|
|
'CACHE_MIDDLEWARE_KEY_PREFIX',
|
|
'CACHE_MIDDLEWARE_SECONDS',
|
|
'COMPRESSORS',
|
|
'COMPRESS_CACHEABLE_PRECOMPILERS',
|
|
'COMPRESS_CACHE_BACKEND',
|
|
'COMPRESS_CACHE_KEY_FUNCTION',
|
|
'COMPRESS_CLEAN_CSS_ARGUMENTS',
|
|
'COMPRESS_CLEAN_CSS_BINARY',
|
|
'COMPRESS_CLOSURE_COMPILER_ARGUMENTS',
|
|
'COMPRESS_CLOSURE_COMPILER_BINARY',
|
|
'COMPRESS_CSS_COMPRESSOR',
|
|
'COMPRESS_CSS_FILTERS',
|
|
'COMPRESS_CSS_HASHING_METHOD',
|
|
'COMPRESS_DATA_URI_MAX_SIZE',
|
|
'COMPRESS_DEBUG_TOGGLE',
|
|
'COMPRESS_ENABLED',
|
|
'COMPRESS_FILTERS',
|
|
'COMPRESS_JINJA2_GET_ENVIRONMENT',
|
|
'COMPRESS_JS_COMPRESSOR',
|
|
'COMPRESS_JS_FILTERS',
|
|
'COMPRESS_MINT_DELAY',
|
|
'COMPRESS_MTIME_DELAY',
|
|
'COMPRESS_OFFLINE',
|
|
'COMPRESS_OFFLINE_CONTEXT',
|
|
'COMPRESS_OFFLINE_MANIFEST',
|
|
'COMPRESS_OFFLINE_TIMEOUT',
|
|
'COMPRESS_OUTPUT_DIR',
|
|
'COMPRESS_PARSER',
|
|
'COMPRESS_PRECOMPILERS',
|
|
'COMPRESS_REBUILD_TIMEOUT',
|
|
'COMPRESS_ROOT',
|
|
'COMPRESS_STORAGE',
|
|
'COMPRESS_TEMPLATE_FILTER_CONTEXT',
|
|
'COMPRESS_URL',
|
|
'COMPRESS_URL_PLACEHOLDER',
|
|
'COMPRESS_VERBOSE',
|
|
'COMPRESS_YUGLIFY_BINARY',
|
|
'COMPRESS_YUGLIFY_CSS_ARGUMENTS',
|
|
'COMPRESS_YUGLIFY_JS_ARGUMENTS',
|
|
'COMPRESS_YUI_BINARY',
|
|
'COMPRESS_YUI_CSS_ARGUMENTS',
|
|
'COMPRESS_YUI_JS_ARGUMENTS',
|
|
'CSRF_COOKIE_AGE',
|
|
'CSRF_COOKIE_DOMAIN',
|
|
'CSRF_COOKIE_HTTPONLY',
|
|
'CSRF_COOKIE_NAME',
|
|
'CSRF_COOKIE_PATH',
|
|
'CSRF_COOKIE_SAMESITE',
|
|
'CSRF_COOKIE_SECURE',
|
|
'CSRF_FAILURE_VIEW',
|
|
'CSRF_HEADER_NAME',
|
|
'CSRF_TRUSTED_ORIGINS',
|
|
'CSRF_USE_SESSIONS',
|
|
'DATABASES',
|
|
'DATABASE_ROUTERS',
|
|
'DATA_UPLOAD_MAX_MEMORY_SIZE',
|
|
'DATA_UPLOAD_MAX_NUMBER_FIELDS',
|
|
'DATEPICKER_LOCALES',
|
|
'DATETIME_FORMAT',
|
|
'DATETIME_INPUT_FORMATS',
|
|
'DATE_FORMAT',
|
|
'DATE_INPUT_FORMATS',
|
|
'DEBUG',
|
|
'DEBUG_PROPAGATE_EXCEPTIONS',
|
|
'DECIMAL_SEPARATOR',
|
|
'DEFAULT_CHARSET',
|
|
'DEFAULT_CONTENT_TYPE',
|
|
'DEFAULT_EXCEPTION_REPORTER_FILTER',
|
|
'DEFAULT_FILE_STORAGE',
|
|
'DEFAULT_FROM_EMAIL',
|
|
'DEFAULT_INDEX_TABLESPACE',
|
|
'DEFAULT_TABLESPACE',
|
|
'DISALLOWED_USER_AGENTS',
|
|
'EMAIL_BACKEND',
|
|
'EMAIL_HOST',
|
|
'EMAIL_HOST_PASSWORD',
|
|
'EMAIL_HOST_USER',
|
|
'EMAIL_PORT',
|
|
'EMAIL_SSL_CERTFILE',
|
|
'EMAIL_SSL_KEYFILE',
|
|
'EMAIL_SUBJECT_PREFIX',
|
|
'EMAIL_TIMEOUT',
|
|
'EMAIL_USE_LOCALTIME',
|
|
'EMAIL_USE_SSL',
|
|
'EMAIL_USE_TLS',
|
|
'FILE_CHARSET',
|
|
'FILE_UPLOAD_DIRECTORY_PERMISSIONS',
|
|
'FILE_UPLOAD_HANDLERS',
|
|
'FILE_UPLOAD_MAX_MEMORY_SIZE',
|
|
'FILE_UPLOAD_PERMISSIONS',
|
|
'FILE_UPLOAD_TEMP_DIR',
|
|
'FIRST_DAY_OF_WEEK',
|
|
'FIXTURE_DIRS',
|
|
'FORCE_SCRIPT_NAME',
|
|
'FORMAT_MODULE_PATH',
|
|
'FORM_RENDERER',
|
|
'HORIZON_CONFIG',
|
|
'IGNORABLE_404_URLS',
|
|
'IMAGE_RESERVED_CUSTOM_PROPERTIES',
|
|
'INSTALLED_APPS',
|
|
'INTERNAL_IPS',
|
|
'LANGUAGES',
|
|
'LANGUAGES_BIDI',
|
|
'LANGUAGE_CODE',
|
|
'LANGUAGE_COOKIE_AGE',
|
|
'LANGUAGE_COOKIE_DOMAIN',
|
|
'LANGUAGE_COOKIE_NAME',
|
|
'LANGUAGE_COOKIE_PATH',
|
|
'LOCALE_PATHS',
|
|
'LOCAL_PATH',
|
|
'LOCAL_SETTINGS_DIR_PATH',
|
|
'LOGGING',
|
|
'LOGGING_CONFIG',
|
|
'LOGOUT_REDIRECT_URL',
|
|
'MANAGERS',
|
|
'MESSAGE_STORAGE',
|
|
'MIDDLEWARE',
|
|
'MIDDLEWARE_CLASSES',
|
|
'MIGRATION_MODULES',
|
|
'MONTH_DAY_FORMAT',
|
|
'NUMBER_GROUPING',
|
|
'OPENSTACK_HEAT_STACK',
|
|
'OPENSTACK_HOST',
|
|
'OPENSTACK_IMAGE_FORMATS',
|
|
'PASSWORD_HASHERS',
|
|
'PASSWORD_RESET_TIMEOUT_DAYS',
|
|
'PREPEND_WWW',
|
|
'ROOT_PATH',
|
|
'ROOT_URLCONF',
|
|
'SECRET_KEY',
|
|
'SECURE_BROWSER_XSS_FILTER',
|
|
'SECURE_CONTENT_TYPE_NOSNIFF',
|
|
'SECURE_HSTS_INCLUDE_SUBDOMAINS',
|
|
'SECURE_HSTS_PRELOAD',
|
|
'SECURE_HSTS_SECONDS',
|
|
'SECURE_PROXY_SSL_HEADER',
|
|
'SECURE_REDIRECT_EXEMPT',
|
|
'SECURE_SSL_HOST',
|
|
'SECURE_SSL_REDIRECT',
|
|
'SERVER_EMAIL',
|
|
'SESSION_CACHE_ALIAS',
|
|
'SESSION_COOKIE_AGE',
|
|
'SESSION_COOKIE_DOMAIN',
|
|
'SESSION_COOKIE_HTTPONLY',
|
|
'SESSION_COOKIE_NAME',
|
|
'SESSION_COOKIE_PATH',
|
|
'SESSION_COOKIE_SAMESITE',
|
|
'SESSION_COOKIE_SECURE',
|
|
'SESSION_ENGINE',
|
|
'SESSION_EXPIRE_AT_BROWSER_CLOSE',
|
|
'SESSION_FILE_PATH',
|
|
'SESSION_SAVE_EVERY_REQUEST',
|
|
'SESSION_SERIALIZER',
|
|
'SETTINGS_MODULE',
|
|
'SHORT_DATETIME_FORMAT',
|
|
'SHORT_DATE_FORMAT',
|
|
'SIGNING_BACKEND',
|
|
'SILENCED_SYSTEM_CHECKS',
|
|
'STATICFILES_DIRS',
|
|
'STATICFILES_FINDERS',
|
|
'STATICFILES_STORAGE',
|
|
'TEMPLATES',
|
|
'TESTSERVER',
|
|
'TEST_GLOBAL_MOCKS_ON_PANELS',
|
|
'TEST_NON_SERIALIZED_APPS',
|
|
'TEST_RUNNER',
|
|
'THOUSAND_SEPARATOR',
|
|
'TIME_FORMAT',
|
|
'TIME_INPUT_FORMATS',
|
|
'USE_ETAGS',
|
|
'USE_I18N',
|
|
'USE_L10N',
|
|
'USE_THOUSAND_SEPARATOR',
|
|
'USE_TZ',
|
|
'USE_X_FORWARDED_HOST',
|
|
'USE_X_FORWARDED_PORT',
|
|
'WSGI_APPLICATION',
|
|
'XSTATIC_MODULES',
|
|
'X_FRAME_OPTIONS',
|
|
'YEAR_MONTH_FORMAT',
|
|
]
|
|
KNOWN_SETTINGS_DASHBOARD = dir(defaults)
|
|
KNOWN_SETTINGS = set(KNOWN_SETTINGS_DASHBOARD +
|
|
KNOWN_SETTINGS_NON_DASHBOARD)
|
|
invalid = []
|
|
for setting in dir(settings):
|
|
if not setting.isupper() or setting.startswith("_"):
|
|
continue
|
|
if setting not in KNOWN_SETTINGS:
|
|
invalid.append(setting)
|
|
if invalid:
|
|
return upgradecheck.Result(
|
|
upgradecheck.Code.WARNING,
|
|
_("Unknown settings: {}.").format(", ".join(invalid)),
|
|
)
|
|
return upgradecheck.Result(upgradecheck.Code.SUCCESS)
|
|
|
|
|
|
@register_check(_("Deprecated Settings"))
|
|
def check_deprecated_settings(dummy=None):
|
|
DEPRECATED_SETTINGS = set()
|
|
deprecated = []
|
|
for setting in dir(settings):
|
|
if not setting.isupper() or setting.startswith("_"):
|
|
continue
|
|
if setting in DEPRECATED_SETTINGS:
|
|
deprecated.append(setting)
|
|
if deprecated:
|
|
return upgradecheck.Result(
|
|
upgradecheck.Code.FAILURE,
|
|
_("Deprecated settings: {}.").format(", ".join(deprecated)),
|
|
)
|
|
return upgradecheck.Result(upgradecheck.Code.SUCCESS)
|
|
|
|
|
|
@register_check(_("Required Settings"))
|
|
def check_required_settings(dummy=None):
|
|
REQUIRED_SETTINGS = {
|
|
'ALLOWED_HOSTS',
|
|
'HORIZON_CONFIG',
|
|
'OPENSTACK_KEYSTONE_URL',
|
|
}
|
|
missing = []
|
|
all_settings = set(dir(settings))
|
|
for setting in REQUIRED_SETTINGS:
|
|
if setting not in all_settings:
|
|
missing.append(setting)
|
|
if missing:
|
|
return upgradecheck.Result(
|
|
upgradecheck.Code.FAILURE,
|
|
_("Missing required settings: {}.").format(", ".join(missing)),
|
|
)
|
|
return upgradecheck.Result(upgradecheck.Code.SUCCESS)
|
|
|
|
|
|
@register_check(_("Chinese locale rename"))
|
|
def check_chinese_locale_rename(dummy):
|
|
# LANGUAGES setting is defined in Django, so we can assume
|
|
# it always exists.
|
|
langs = [code for code, name in settings.LANGUAGES]
|
|
if 'zh-cn' in langs or 'zh-tw' in langs:
|
|
return upgradecheck.Result(
|
|
upgradecheck.Code.FAILURE,
|
|
_("Chinese locale 'zh-cn' and 'zh-tw' must be renamed to "
|
|
"'zh-hans' and 'zh-hant' respectively in 'LANGUAGES' setting. "
|
|
"If you define them in local_settings.py or local_settings.d "
|
|
"explicitly, ensure to rename them to the new locales.")
|
|
)
|
|
return upgradecheck.Result(upgradecheck.Code.SUCCESS)
|
|
|
|
|
|
@register_check(_("Django launch instance form"))
|
|
def check_django_launch_instance_form(dummy):
|
|
if settings.LAUNCH_INSTANCE_LEGACY_ENABLED:
|
|
return upgradecheck.Result(
|
|
upgradecheck.Code.WARNING,
|
|
_("The Django version of the launch instance form is deprecated "
|
|
"since Wallaby release. Switch to the AngularJS version of the "
|
|
"form by setting LAUNCH_INSTANCE_NG_ENABLED to True and "
|
|
"LAUNCH_INSTANCE_LEGACY_ENABLED to False.")
|
|
)
|
|
return upgradecheck.Result(upgradecheck.Code.SUCCESS)
|
|
|
|
|
|
class UpgradeCheckTable(upgradecheck.UpgradeCommands):
|
|
_upgrade_checks = CHECKS
|
|
|
|
|
|
class Command(BaseCommand):
|
|
help = "Perform a check to see if the application is ready for upgrade."
|
|
|
|
def add_arguments(self, parser):
|
|
parser.add_argument(
|
|
'-f', '--format', choices=['table', 'json'],
|
|
default='table', help=_("The output format")
|
|
)
|
|
|
|
def handle(self, *args, **options):
|
|
output_format = options.pop('format')
|
|
final_code = upgradecheck.Code.SUCCESS
|
|
if output_format == 'table':
|
|
final_code = UpgradeCheckTable().check()
|
|
elif output_format == 'json':
|
|
results = []
|
|
for check_name, check_func in CHECKS:
|
|
result = check_func()
|
|
final_code = max(final_code, int(result.code))
|
|
results.append({
|
|
'check': "{}".format(check_name),
|
|
'code': int(result.code),
|
|
'details': "{}".format(result.details),
|
|
})
|
|
print(json.dumps(results))
|
|
sys.exit(final_code)
|