Files
horizon/openstack_dashboard/management/commands/upgrade_check.py
Akihiro Motoki 57380fae71 Deprecate Django launch instance form
As discussed in the horizon meeting, we think that feature gaps
between the two implementations have been closed. Let's mark
the Django version as deprecated and gather more attentions
from operators.

Change-Id: I55379c0897bad46decfabb443afe9439a31a3164
2021-03-09 15:55:35 +09:00

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)