Merge "Migrate upgrade checks to oslo.upgradecheck"
This commit is contained in:
commit
2e9356374e
@ -89,6 +89,7 @@ oslo.reports==1.18.0
|
|||||||
oslo.rootwrap==5.8.0
|
oslo.rootwrap==5.8.0
|
||||||
oslo.serialization==2.18.0
|
oslo.serialization==2.18.0
|
||||||
oslo.service==1.33.0
|
oslo.service==1.33.0
|
||||||
|
oslo.upgradecheck==0.1.1
|
||||||
oslo.utils==3.37.0
|
oslo.utils==3.37.0
|
||||||
oslo.versionedobjects==1.33.3
|
oslo.versionedobjects==1.33.3
|
||||||
oslo.vmware==2.17.0
|
oslo.vmware==2.17.0
|
||||||
|
@ -19,18 +19,15 @@ CLI interface for nova status commands.
|
|||||||
from __future__ import print_function
|
from __future__ import print_function
|
||||||
|
|
||||||
import collections
|
import collections
|
||||||
# enum comes from the enum34 package if python < 3.4, else it's stdlib
|
|
||||||
import enum
|
|
||||||
import functools
|
import functools
|
||||||
import sys
|
import sys
|
||||||
import textwrap
|
|
||||||
import traceback
|
import traceback
|
||||||
|
|
||||||
from keystoneauth1 import exceptions as ks_exc
|
from keystoneauth1 import exceptions as ks_exc
|
||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
from oslo_serialization import jsonutils
|
from oslo_serialization import jsonutils
|
||||||
|
from oslo_upgradecheck import upgradecheck
|
||||||
import pkg_resources
|
import pkg_resources
|
||||||
import prettytable
|
|
||||||
from sqlalchemy import func as sqlfunc
|
from sqlalchemy import func as sqlfunc
|
||||||
from sqlalchemy import MetaData, Table, and_, select
|
from sqlalchemy import MetaData, Table, and_, select
|
||||||
from sqlalchemy.sql import false
|
from sqlalchemy.sql import false
|
||||||
@ -59,47 +56,7 @@ PLACEMENT_DOCS_LINK = 'https://docs.openstack.org/nova/latest' \
|
|||||||
MIN_PLACEMENT_MICROVERSION = "1.30"
|
MIN_PLACEMENT_MICROVERSION = "1.30"
|
||||||
|
|
||||||
|
|
||||||
class UpgradeCheckCode(enum.IntEnum):
|
class UpgradeCommands(upgradecheck.UpgradeCommands):
|
||||||
"""These are the status codes for the nova-status upgrade check command
|
|
||||||
and internal check commands.
|
|
||||||
"""
|
|
||||||
|
|
||||||
# All upgrade readiness checks passed successfully and there is
|
|
||||||
# nothing to do.
|
|
||||||
SUCCESS = 0
|
|
||||||
|
|
||||||
# At least one check encountered an issue and requires further
|
|
||||||
# investigation. This is considered a warning but the upgrade may be OK.
|
|
||||||
WARNING = 1
|
|
||||||
|
|
||||||
# There was an upgrade status check failure that needs to be
|
|
||||||
# investigated. This should be considered something that stops an upgrade.
|
|
||||||
FAILURE = 2
|
|
||||||
|
|
||||||
|
|
||||||
UPGRADE_CHECK_MSG_MAP = {
|
|
||||||
UpgradeCheckCode.SUCCESS: _('Success'),
|
|
||||||
UpgradeCheckCode.WARNING: _('Warning'),
|
|
||||||
UpgradeCheckCode.FAILURE: _('Failure'),
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class UpgradeCheckResult(object):
|
|
||||||
"""Class used for 'nova-status upgrade check' results.
|
|
||||||
|
|
||||||
The 'code' attribute is an UpgradeCheckCode enum.
|
|
||||||
The 'details' attribute is a translated message generally only used for
|
|
||||||
checks that result in a warning or failure code. The details should provide
|
|
||||||
information on what issue was discovered along with any remediation.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, code, details=None):
|
|
||||||
super(UpgradeCheckResult, self).__init__()
|
|
||||||
self.code = code
|
|
||||||
self.details = details
|
|
||||||
|
|
||||||
|
|
||||||
class UpgradeCommands(object):
|
|
||||||
"""Commands related to upgrades.
|
"""Commands related to upgrades.
|
||||||
|
|
||||||
The subcommands here must not rely on the nova object model since they
|
The subcommands here must not rely on the nova object model since they
|
||||||
@ -152,7 +109,7 @@ class UpgradeCommands(object):
|
|||||||
'cell0 and one for your first cell. Run command '
|
'cell0 and one for your first cell. Run command '
|
||||||
'\'nova-manage cell_v2 simple_cell_setup\' and then '
|
'\'nova-manage cell_v2 simple_cell_setup\' and then '
|
||||||
'retry.')
|
'retry.')
|
||||||
return UpgradeCheckResult(UpgradeCheckCode.FAILURE, msg)
|
return upgradecheck.Result(upgradecheck.Code.FAILURE, msg)
|
||||||
|
|
||||||
count = select([sqlfunc.count()]).select_from(cell_mappings).where(
|
count = select([sqlfunc.count()]).select_from(cell_mappings).where(
|
||||||
cell_mappings.c.uuid ==
|
cell_mappings.c.uuid ==
|
||||||
@ -161,7 +118,7 @@ class UpgradeCommands(object):
|
|||||||
msg = _('No cell0 mapping found. Run command '
|
msg = _('No cell0 mapping found. Run command '
|
||||||
'\'nova-manage cell_v2 simple_cell_setup\' and then '
|
'\'nova-manage cell_v2 simple_cell_setup\' and then '
|
||||||
'retry.')
|
'retry.')
|
||||||
return UpgradeCheckResult(UpgradeCheckCode.FAILURE, msg)
|
return upgradecheck.Result(upgradecheck.Code.FAILURE, msg)
|
||||||
|
|
||||||
host_mappings = Table('host_mappings', meta, autoload=True)
|
host_mappings = Table('host_mappings', meta, autoload=True)
|
||||||
count = select([sqlfunc.count()]).select_from(host_mappings).scalar()
|
count = select([sqlfunc.count()]).select_from(host_mappings).scalar()
|
||||||
@ -176,14 +133,14 @@ class UpgradeCommands(object):
|
|||||||
msg = _('No host mappings found but there are compute nodes. '
|
msg = _('No host mappings found but there are compute nodes. '
|
||||||
'Run command \'nova-manage cell_v2 '
|
'Run command \'nova-manage cell_v2 '
|
||||||
'simple_cell_setup\' and then retry.')
|
'simple_cell_setup\' and then retry.')
|
||||||
return UpgradeCheckResult(UpgradeCheckCode.FAILURE, msg)
|
return upgradecheck.Result(upgradecheck.Code.FAILURE, msg)
|
||||||
|
|
||||||
msg = _('No host mappings or compute nodes were found. Remember '
|
msg = _('No host mappings or compute nodes were found. Remember '
|
||||||
'to run command \'nova-manage cell_v2 discover_hosts\' '
|
'to run command \'nova-manage cell_v2 discover_hosts\' '
|
||||||
'when new compute hosts are deployed.')
|
'when new compute hosts are deployed.')
|
||||||
return UpgradeCheckResult(UpgradeCheckCode.SUCCESS, msg)
|
return upgradecheck.Result(upgradecheck.Code.SUCCESS, msg)
|
||||||
|
|
||||||
return UpgradeCheckResult(UpgradeCheckCode.SUCCESS)
|
return upgradecheck.Result(upgradecheck.Code.SUCCESS)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _placement_get(path):
|
def _placement_get(path):
|
||||||
@ -213,24 +170,24 @@ class UpgradeCommands(object):
|
|||||||
msg = (_('Placement API version %(needed)s needed, '
|
msg = (_('Placement API version %(needed)s needed, '
|
||||||
'you have %(current)s.') %
|
'you have %(current)s.') %
|
||||||
{'needed': needs_version, 'current': max_version})
|
{'needed': needs_version, 'current': max_version})
|
||||||
return UpgradeCheckResult(UpgradeCheckCode.FAILURE, msg)
|
return upgradecheck.Result(upgradecheck.Code.FAILURE, msg)
|
||||||
except ks_exc.MissingAuthPlugin:
|
except ks_exc.MissingAuthPlugin:
|
||||||
msg = _('No credentials specified for placement API in nova.conf.')
|
msg = _('No credentials specified for placement API in nova.conf.')
|
||||||
return UpgradeCheckResult(UpgradeCheckCode.FAILURE, msg)
|
return upgradecheck.Result(upgradecheck.Code.FAILURE, msg)
|
||||||
except ks_exc.Unauthorized:
|
except ks_exc.Unauthorized:
|
||||||
msg = _('Placement service credentials do not work.')
|
msg = _('Placement service credentials do not work.')
|
||||||
return UpgradeCheckResult(UpgradeCheckCode.FAILURE, msg)
|
return upgradecheck.Result(upgradecheck.Code.FAILURE, msg)
|
||||||
except ks_exc.EndpointNotFound:
|
except ks_exc.EndpointNotFound:
|
||||||
msg = _('Placement API endpoint not found.')
|
msg = _('Placement API endpoint not found.')
|
||||||
return UpgradeCheckResult(UpgradeCheckCode.FAILURE, msg)
|
return upgradecheck.Result(upgradecheck.Code.FAILURE, msg)
|
||||||
except ks_exc.DiscoveryFailure:
|
except ks_exc.DiscoveryFailure:
|
||||||
msg = _('Discovery for placement API URI failed.')
|
msg = _('Discovery for placement API URI failed.')
|
||||||
return UpgradeCheckResult(UpgradeCheckCode.FAILURE, msg)
|
return upgradecheck.Result(upgradecheck.Code.FAILURE, msg)
|
||||||
except ks_exc.NotFound:
|
except ks_exc.NotFound:
|
||||||
msg = _('Placement API does not seem to be running.')
|
msg = _('Placement API does not seem to be running.')
|
||||||
return UpgradeCheckResult(UpgradeCheckCode.FAILURE, msg)
|
return upgradecheck.Result(upgradecheck.Code.FAILURE, msg)
|
||||||
|
|
||||||
return UpgradeCheckResult(UpgradeCheckCode.SUCCESS)
|
return upgradecheck.Result(upgradecheck.Code.SUCCESS)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _count_compute_resource_providers():
|
def _count_compute_resource_providers():
|
||||||
@ -319,7 +276,7 @@ class UpgradeCommands(object):
|
|||||||
'%(placement_docs_link)s for more details.') %
|
'%(placement_docs_link)s for more details.') %
|
||||||
{'num_computes': num_computes,
|
{'num_computes': num_computes,
|
||||||
'placement_docs_link': PLACEMENT_DOCS_LINK})
|
'placement_docs_link': PLACEMENT_DOCS_LINK})
|
||||||
return UpgradeCheckResult(UpgradeCheckCode.WARNING, msg)
|
return upgradecheck.Result(upgradecheck.Code.WARNING, msg)
|
||||||
|
|
||||||
# There are no resource providers and no compute nodes so we
|
# There are no resource providers and no compute nodes so we
|
||||||
# assume this is a fresh install and move on. We should return a
|
# assume this is a fresh install and move on. We should return a
|
||||||
@ -330,7 +287,7 @@ class UpgradeCommands(object):
|
|||||||
'report into the Placement service. See '
|
'report into the Placement service. See '
|
||||||
'%(placement_docs_link)s for more details.') %
|
'%(placement_docs_link)s for more details.') %
|
||||||
{'placement_docs_link': PLACEMENT_DOCS_LINK})
|
{'placement_docs_link': PLACEMENT_DOCS_LINK})
|
||||||
return UpgradeCheckResult(UpgradeCheckCode.SUCCESS, msg)
|
return upgradecheck.Result(upgradecheck.Code.SUCCESS, msg)
|
||||||
|
|
||||||
elif num_rps < num_computes:
|
elif num_rps < num_computes:
|
||||||
# There are fewer resource providers than compute nodes, so return
|
# There are fewer resource providers than compute nodes, so return
|
||||||
@ -349,10 +306,10 @@ class UpgradeCommands(object):
|
|||||||
{'num_resource_providers': num_rps,
|
{'num_resource_providers': num_rps,
|
||||||
'num_compute_nodes': num_computes,
|
'num_compute_nodes': num_computes,
|
||||||
'placement_docs_link': PLACEMENT_DOCS_LINK})
|
'placement_docs_link': PLACEMENT_DOCS_LINK})
|
||||||
return UpgradeCheckResult(UpgradeCheckCode.WARNING, msg)
|
return upgradecheck.Result(upgradecheck.Code.WARNING, msg)
|
||||||
else:
|
else:
|
||||||
# We have RPs >= CNs which is what we want to see.
|
# We have RPs >= CNs which is what we want to see.
|
||||||
return UpgradeCheckResult(UpgradeCheckCode.SUCCESS)
|
return upgradecheck.Result(upgradecheck.Code.SUCCESS)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _is_ironic_instance_migrated(extras, inst):
|
def _is_ironic_instance_migrated(extras, inst):
|
||||||
@ -431,7 +388,7 @@ class UpgradeCommands(object):
|
|||||||
# on this.
|
# on this.
|
||||||
msg = (_('Unable to determine ironic flavor migration without '
|
msg = (_('Unable to determine ironic flavor migration without '
|
||||||
'cell mappings.'))
|
'cell mappings.'))
|
||||||
return UpgradeCheckResult(UpgradeCheckCode.WARNING, msg)
|
return upgradecheck.Result(upgradecheck.Code.WARNING, msg)
|
||||||
|
|
||||||
if unmigrated_instance_count_by_cell:
|
if unmigrated_instance_count_by_cell:
|
||||||
# There are unmigrated ironic instances, so we need to fail.
|
# There are unmigrated ironic instances, so we need to fail.
|
||||||
@ -442,11 +399,11 @@ class UpgradeCommands(object):
|
|||||||
cell_id, unmigrated_instance_count_by_cell[cell_id])
|
cell_id, unmigrated_instance_count_by_cell[cell_id])
|
||||||
for cell_id in
|
for cell_id in
|
||||||
sorted(unmigrated_instance_count_by_cell.keys())))
|
sorted(unmigrated_instance_count_by_cell.keys())))
|
||||||
return UpgradeCheckResult(UpgradeCheckCode.FAILURE, msg)
|
return upgradecheck.Result(upgradecheck.Code.FAILURE, msg)
|
||||||
|
|
||||||
# Either there were no ironic compute nodes or all instances for
|
# Either there were no ironic compute nodes or all instances for
|
||||||
# those nodes are already migrated, so there is nothing to do.
|
# those nodes are already migrated, so there is nothing to do.
|
||||||
return UpgradeCheckResult(UpgradeCheckCode.SUCCESS)
|
return upgradecheck.Result(upgradecheck.Code.SUCCESS)
|
||||||
|
|
||||||
def _get_min_service_version(self, context, binary):
|
def _get_min_service_version(self, context, binary):
|
||||||
meta = MetaData(bind=db_session.get_engine(context=context))
|
meta = MetaData(bind=db_session.get_engine(context=context))
|
||||||
@ -475,7 +432,7 @@ class UpgradeCommands(object):
|
|||||||
"""
|
"""
|
||||||
# If we're using cells v1 then we don't care about this.
|
# If we're using cells v1 then we don't care about this.
|
||||||
if CONF.cells.enable:
|
if CONF.cells.enable:
|
||||||
return UpgradeCheckResult(UpgradeCheckCode.SUCCESS)
|
return upgradecheck.Result(upgradecheck.Code.SUCCESS)
|
||||||
|
|
||||||
meta = MetaData(bind=db_session.get_api_engine())
|
meta = MetaData(bind=db_session.get_api_engine())
|
||||||
cell_mappings = Table('cell_mappings', meta, autoload=True)
|
cell_mappings = Table('cell_mappings', meta, autoload=True)
|
||||||
@ -487,7 +444,7 @@ class UpgradeCommands(object):
|
|||||||
# on this.
|
# on this.
|
||||||
msg = (_('Unable to determine API service versions without '
|
msg = (_('Unable to determine API service versions without '
|
||||||
'cell mappings.'))
|
'cell mappings.'))
|
||||||
return UpgradeCheckResult(UpgradeCheckCode.WARNING, msg)
|
return upgradecheck.Result(upgradecheck.Code.WARNING, msg)
|
||||||
|
|
||||||
ctxt = nova_context.get_admin_context()
|
ctxt = nova_context.get_admin_context()
|
||||||
cells_with_old_api_services = []
|
cells_with_old_api_services = []
|
||||||
@ -513,8 +470,8 @@ class UpgradeCommands(object):
|
|||||||
"records. See "
|
"records. See "
|
||||||
"https://bugs.launchpad.net/nova/+bug/1759316 for "
|
"https://bugs.launchpad.net/nova/+bug/1759316 for "
|
||||||
"details.") % ', '.join(cells_with_old_api_services))
|
"details.") % ', '.join(cells_with_old_api_services))
|
||||||
return UpgradeCheckResult(UpgradeCheckCode.WARNING, msg)
|
return upgradecheck.Result(upgradecheck.Code.WARNING, msg)
|
||||||
return UpgradeCheckResult(UpgradeCheckCode.SUCCESS)
|
return upgradecheck.Result(upgradecheck.Code.SUCCESS)
|
||||||
|
|
||||||
def _check_request_spec_migration(self):
|
def _check_request_spec_migration(self):
|
||||||
"""Checks to make sure request spec migrations are complete.
|
"""Checks to make sure request spec migrations are complete.
|
||||||
@ -535,7 +492,7 @@ class UpgradeCommands(object):
|
|||||||
# on this.
|
# on this.
|
||||||
msg = (_('Unable to determine request spec migrations without '
|
msg = (_('Unable to determine request spec migrations without '
|
||||||
'cell mappings.'))
|
'cell mappings.'))
|
||||||
return UpgradeCheckResult(UpgradeCheckCode.WARNING, msg)
|
return upgradecheck.Result(upgradecheck.Code.WARNING, msg)
|
||||||
|
|
||||||
request_specs = Table('request_specs', meta, autoload=True)
|
request_specs = Table('request_specs', meta, autoload=True)
|
||||||
ctxt = nova_context.get_admin_context()
|
ctxt = nova_context.get_admin_context()
|
||||||
@ -573,8 +530,8 @@ class UpgradeCommands(object):
|
|||||||
"'nova-manage db online_data_migrations' on each cell "
|
"'nova-manage db online_data_migrations' on each cell "
|
||||||
"to create the missing request specs.") %
|
"to create the missing request specs.") %
|
||||||
', '.join(incomplete_cells))
|
', '.join(incomplete_cells))
|
||||||
return UpgradeCheckResult(UpgradeCheckCode.FAILURE, msg)
|
return upgradecheck.Result(upgradecheck.Code.FAILURE, msg)
|
||||||
return UpgradeCheckResult(UpgradeCheckCode.SUCCESS)
|
return upgradecheck.Result(upgradecheck.Code.SUCCESS)
|
||||||
|
|
||||||
def _check_console_auths(self):
|
def _check_console_auths(self):
|
||||||
"""Checks for console usage and warns with info for rolling upgrade.
|
"""Checks for console usage and warns with info for rolling upgrade.
|
||||||
@ -591,7 +548,7 @@ class UpgradeCommands(object):
|
|||||||
# If the operator has already enabled the workaround, we don't need
|
# If the operator has already enabled the workaround, we don't need
|
||||||
# to check anything.
|
# to check anything.
|
||||||
if CONF.cells.enable or CONF.workarounds.enable_consoleauth:
|
if CONF.cells.enable or CONF.workarounds.enable_consoleauth:
|
||||||
return UpgradeCheckResult(UpgradeCheckCode.SUCCESS)
|
return upgradecheck.Result(upgradecheck.Code.SUCCESS)
|
||||||
|
|
||||||
# We need to check cell0 for nova-consoleauth service records because
|
# We need to check cell0 for nova-consoleauth service records because
|
||||||
# it's possible a deployment could have services stored in the cell0
|
# it's possible a deployment could have services stored in the cell0
|
||||||
@ -606,7 +563,7 @@ class UpgradeCommands(object):
|
|||||||
# return a warning. The cellsv2 check would have already failed
|
# return a warning. The cellsv2 check would have already failed
|
||||||
# on this.
|
# on this.
|
||||||
msg = (_('Unable to check consoles without cell mappings.'))
|
msg = (_('Unable to check consoles without cell mappings.'))
|
||||||
return UpgradeCheckResult(UpgradeCheckCode.WARNING, msg)
|
return upgradecheck.Result(upgradecheck.Code.WARNING, msg)
|
||||||
|
|
||||||
ctxt = nova_context.get_admin_context()
|
ctxt = nova_context.get_admin_context()
|
||||||
# If we find a non-deleted, non-disabled nova-consoleauth service in
|
# If we find a non-deleted, non-disabled nova-consoleauth service in
|
||||||
@ -652,15 +609,15 @@ class UpgradeCommands(object):
|
|||||||
"console proxy host if you are performing a "
|
"console proxy host if you are performing a "
|
||||||
"rolling upgrade to enable consoles to "
|
"rolling upgrade to enable consoles to "
|
||||||
"function during a partial upgrade.")
|
"function during a partial upgrade.")
|
||||||
return UpgradeCheckResult(UpgradeCheckCode.WARNING,
|
return upgradecheck.Result(upgradecheck.Code.WARNING,
|
||||||
msg)
|
msg)
|
||||||
|
|
||||||
return UpgradeCheckResult(UpgradeCheckCode.SUCCESS)
|
return upgradecheck.Result(upgradecheck.Code.SUCCESS)
|
||||||
|
|
||||||
# The format of the check functions is to return an UpgradeCheckResult
|
# The format of the check functions is to return an upgradecheck.Result
|
||||||
# object with the appropriate UpgradeCheckCode and details set. If the
|
# object with the appropriate upgradecheck.Code and details set. If the
|
||||||
# check hits warnings or failures then those should be stored in the
|
# check hits warnings or failures then those should be stored in the
|
||||||
# returned UpgradeCheckResult's "details" attribute. The summary will
|
# returned upgradecheck.Result's "details" attribute. The summary will
|
||||||
# be rolled up at the end of the check() function. These functions are
|
# be rolled up at the end of the check() function. These functions are
|
||||||
# intended to be run in order and build on top of each other so order
|
# intended to be run in order and build on top of each other so order
|
||||||
# matters.
|
# matters.
|
||||||
@ -681,65 +638,6 @@ class UpgradeCommands(object):
|
|||||||
(_('Console Auths'), _check_console_auths),
|
(_('Console Auths'), _check_console_auths),
|
||||||
)
|
)
|
||||||
|
|
||||||
def _get_details(self, upgrade_check_result):
|
|
||||||
if upgrade_check_result.details is not None:
|
|
||||||
# wrap the text on the details to 60 characters
|
|
||||||
return '\n'.join(textwrap.wrap(upgrade_check_result.details, 60,
|
|
||||||
subsequent_indent=' '))
|
|
||||||
|
|
||||||
def check(self):
|
|
||||||
"""Performs checks to see if the deployment is ready for upgrade.
|
|
||||||
|
|
||||||
These checks are expected to be run BEFORE services are restarted with
|
|
||||||
new code. These checks also require access to potentially all of the
|
|
||||||
Nova databases (nova, nova_api, nova_api_cell0) and external services
|
|
||||||
such as the placement API service.
|
|
||||||
|
|
||||||
:returns: UpgradeCheckCode
|
|
||||||
"""
|
|
||||||
return_code = UpgradeCheckCode.SUCCESS
|
|
||||||
# This is a list if 2-item tuples for the check name and it's results.
|
|
||||||
check_results = []
|
|
||||||
for name, func in self._upgrade_checks:
|
|
||||||
result = func(self)
|
|
||||||
# store the result of the check for the summary table
|
|
||||||
check_results.append((name, result))
|
|
||||||
# we want to end up with the highest level code of all checks
|
|
||||||
if result.code > return_code:
|
|
||||||
return_code = result.code
|
|
||||||
|
|
||||||
# We're going to build a summary table that looks like:
|
|
||||||
# +----------------------------------------------------+
|
|
||||||
# | Upgrade Check Results |
|
|
||||||
# +----------------------------------------------------+
|
|
||||||
# | Check: Cells v2 |
|
|
||||||
# | Result: Success |
|
|
||||||
# | Details: None |
|
|
||||||
# +----------------------------------------------------+
|
|
||||||
# | Check: Placement API |
|
|
||||||
# | Result: Failure |
|
|
||||||
# | Details: There is no placement-api endpoint in the |
|
|
||||||
# | service catalog. |
|
|
||||||
# +----------------------------------------------------+
|
|
||||||
t = prettytable.PrettyTable([_('Upgrade Check Results')],
|
|
||||||
hrules=prettytable.ALL)
|
|
||||||
t.align = 'l'
|
|
||||||
for name, result in check_results:
|
|
||||||
cell = (
|
|
||||||
_('Check: %(name)s\n'
|
|
||||||
'Result: %(result)s\n'
|
|
||||||
'Details: %(details)s') %
|
|
||||||
{
|
|
||||||
'name': name,
|
|
||||||
'result': UPGRADE_CHECK_MSG_MAP[result.code],
|
|
||||||
'details': self._get_details(result),
|
|
||||||
}
|
|
||||||
)
|
|
||||||
t.add_row([cell])
|
|
||||||
print(t)
|
|
||||||
|
|
||||||
return return_code
|
|
||||||
|
|
||||||
|
|
||||||
CATEGORIES = {
|
CATEGORIES = {
|
||||||
'upgrade': UpgradeCommands,
|
'upgrade': UpgradeCommands,
|
||||||
|
@ -17,6 +17,7 @@ from six.moves import StringIO
|
|||||||
|
|
||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
from oslo_config import fixture as config_fixture
|
from oslo_config import fixture as config_fixture
|
||||||
|
from oslo_upgradecheck import upgradecheck
|
||||||
from oslo_utils.fixture import uuidsentinel as uuids
|
from oslo_utils.fixture import uuidsentinel as uuids
|
||||||
from oslo_utils import uuidutils
|
from oslo_utils import uuidutils
|
||||||
import placement.db_api
|
import placement.db_api
|
||||||
@ -97,7 +98,7 @@ class TestUpgradeCheckResourceProviders(test.NoDBTestCase):
|
|||||||
self.useFixture(nova_fixtures.Database())
|
self.useFixture(nova_fixtures.Database())
|
||||||
result = self.cmd._check_resource_providers()
|
result = self.cmd._check_resource_providers()
|
||||||
# this is assumed to be base install so it's OK but with details
|
# this is assumed to be base install so it's OK but with details
|
||||||
self.assertEqual(status.UpgradeCheckCode.SUCCESS, result.code)
|
self.assertEqual(upgradecheck.Code.SUCCESS, result.code)
|
||||||
self.assertIn('There are no compute resource providers in the '
|
self.assertIn('There are no compute resource providers in the '
|
||||||
'Placement service nor are there compute nodes in the '
|
'Placement service nor are there compute nodes in the '
|
||||||
'database',
|
'database',
|
||||||
@ -114,7 +115,7 @@ class TestUpgradeCheckResourceProviders(test.NoDBTestCase):
|
|||||||
# install and not a failure.
|
# install and not a failure.
|
||||||
result = self.cmd._check_resource_providers()
|
result = self.cmd._check_resource_providers()
|
||||||
# this is assumed to be base install so it's OK but with details
|
# this is assumed to be base install so it's OK but with details
|
||||||
self.assertEqual(status.UpgradeCheckCode.SUCCESS, result.code)
|
self.assertEqual(upgradecheck.Code.SUCCESS, result.code)
|
||||||
self.assertIn('There are no compute resource providers in the '
|
self.assertIn('There are no compute resource providers in the '
|
||||||
'Placement service nor are there compute nodes in the '
|
'Placement service nor are there compute nodes in the '
|
||||||
'database',
|
'database',
|
||||||
@ -141,7 +142,7 @@ class TestUpgradeCheckResourceProviders(test.NoDBTestCase):
|
|||||||
cpu_info='{"arch": "x86_64"}')
|
cpu_info='{"arch": "x86_64"}')
|
||||||
cn.create()
|
cn.create()
|
||||||
result = self.cmd._check_resource_providers()
|
result = self.cmd._check_resource_providers()
|
||||||
self.assertEqual(status.UpgradeCheckCode.WARNING, result.code)
|
self.assertEqual(upgradecheck.Code.WARNING, result.code)
|
||||||
self.assertIn('There are no compute resource providers in the '
|
self.assertIn('There are no compute resource providers in the '
|
||||||
'Placement service but there are 1 compute nodes in the '
|
'Placement service but there are 1 compute nodes in the '
|
||||||
'deployment.', result.details)
|
'deployment.', result.details)
|
||||||
@ -192,7 +193,7 @@ class TestUpgradeCheckResourceProviders(test.NoDBTestCase):
|
|||||||
self._create_resource_provider(FAKE_IP_POOL_INVENTORY)
|
self._create_resource_provider(FAKE_IP_POOL_INVENTORY)
|
||||||
|
|
||||||
result = self.cmd._check_resource_providers()
|
result = self.cmd._check_resource_providers()
|
||||||
self.assertEqual(status.UpgradeCheckCode.WARNING, result.code)
|
self.assertEqual(upgradecheck.Code.WARNING, result.code)
|
||||||
self.assertIn('There are no compute resource providers in the '
|
self.assertIn('There are no compute resource providers in the '
|
||||||
'Placement service but there are 1 compute nodes in the '
|
'Placement service but there are 1 compute nodes in the '
|
||||||
'deployment.', result.details)
|
'deployment.', result.details)
|
||||||
@ -225,7 +226,7 @@ class TestUpgradeCheckResourceProviders(test.NoDBTestCase):
|
|||||||
self._create_resource_provider(FAKE_VCPU_INVENTORY)
|
self._create_resource_provider(FAKE_VCPU_INVENTORY)
|
||||||
|
|
||||||
result = self.cmd._check_resource_providers()
|
result = self.cmd._check_resource_providers()
|
||||||
self.assertEqual(status.UpgradeCheckCode.WARNING, result.code)
|
self.assertEqual(upgradecheck.Code.WARNING, result.code)
|
||||||
self.assertIn('There are 1 compute resource providers and 2 compute '
|
self.assertIn('There are 1 compute resource providers and 2 compute '
|
||||||
'nodes in the deployment.', result.details)
|
'nodes in the deployment.', result.details)
|
||||||
|
|
||||||
@ -285,5 +286,5 @@ class TestUpgradeCheckResourceProviders(test.NoDBTestCase):
|
|||||||
stub_count_compute_nodes)
|
stub_count_compute_nodes)
|
||||||
|
|
||||||
result = self.cmd._check_resource_providers()
|
result = self.cmd._check_resource_providers()
|
||||||
self.assertEqual(status.UpgradeCheckCode.SUCCESS, result.code)
|
self.assertEqual(upgradecheck.Code.SUCCESS, result.code)
|
||||||
self.assertIsNone(result.details)
|
self.assertIsNone(result.details)
|
||||||
|
@ -27,6 +27,7 @@ from six.moves import StringIO
|
|||||||
from keystoneauth1 import exceptions as ks_exc
|
from keystoneauth1 import exceptions as ks_exc
|
||||||
from keystoneauth1 import loading as keystone
|
from keystoneauth1 import loading as keystone
|
||||||
from keystoneauth1 import session
|
from keystoneauth1 import session
|
||||||
|
from oslo_upgradecheck import upgradecheck
|
||||||
from oslo_utils.fixture import uuidsentinel as uuids
|
from oslo_utils.fixture import uuidsentinel as uuids
|
||||||
from oslo_utils import uuidutils
|
from oslo_utils import uuidutils
|
||||||
from requests import models
|
from requests import models
|
||||||
@ -124,7 +125,7 @@ class TestPlacementCheck(test.NoDBTestCase):
|
|||||||
"""
|
"""
|
||||||
auth.side_effect = ks_exc.MissingAuthPlugin()
|
auth.side_effect = ks_exc.MissingAuthPlugin()
|
||||||
res = self.cmd._check_placement()
|
res = self.cmd._check_placement()
|
||||||
self.assertEqual(status.UpgradeCheckCode.FAILURE, res.code)
|
self.assertEqual(upgradecheck.Code.FAILURE, res.code)
|
||||||
self.assertIn('No credentials specified', res.details)
|
self.assertIn('No credentials specified', res.details)
|
||||||
|
|
||||||
@mock.patch.object(keystone, "load_auth_from_conf_options")
|
@mock.patch.object(keystone, "load_auth_from_conf_options")
|
||||||
@ -166,7 +167,7 @@ class TestPlacementCheck(test.NoDBTestCase):
|
|||||||
"""
|
"""
|
||||||
get.side_effect = ks_exc.Unauthorized()
|
get.side_effect = ks_exc.Unauthorized()
|
||||||
res = self.cmd._check_placement()
|
res = self.cmd._check_placement()
|
||||||
self.assertEqual(status.UpgradeCheckCode.FAILURE, res.code)
|
self.assertEqual(upgradecheck.Code.FAILURE, res.code)
|
||||||
self.assertIn('Placement service credentials do not work', res.details)
|
self.assertIn('Placement service credentials do not work', res.details)
|
||||||
|
|
||||||
@mock.patch.object(status.UpgradeCommands, "_placement_get")
|
@mock.patch.object(status.UpgradeCommands, "_placement_get")
|
||||||
@ -179,7 +180,7 @@ class TestPlacementCheck(test.NoDBTestCase):
|
|||||||
"""
|
"""
|
||||||
get.side_effect = ks_exc.EndpointNotFound()
|
get.side_effect = ks_exc.EndpointNotFound()
|
||||||
res = self.cmd._check_placement()
|
res = self.cmd._check_placement()
|
||||||
self.assertEqual(status.UpgradeCheckCode.FAILURE, res.code)
|
self.assertEqual(upgradecheck.Code.FAILURE, res.code)
|
||||||
self.assertIn('Placement API endpoint not found', res.details)
|
self.assertIn('Placement API endpoint not found', res.details)
|
||||||
|
|
||||||
@mock.patch.object(status.UpgradeCommands, "_placement_get")
|
@mock.patch.object(status.UpgradeCommands, "_placement_get")
|
||||||
@ -192,7 +193,7 @@ class TestPlacementCheck(test.NoDBTestCase):
|
|||||||
"""
|
"""
|
||||||
get.side_effect = ks_exc.DiscoveryFailure()
|
get.side_effect = ks_exc.DiscoveryFailure()
|
||||||
res = self.cmd._check_placement()
|
res = self.cmd._check_placement()
|
||||||
self.assertEqual(status.UpgradeCheckCode.FAILURE, res.code)
|
self.assertEqual(upgradecheck.Code.FAILURE, res.code)
|
||||||
self.assertIn('Discovery for placement API URI failed.', res.details)
|
self.assertIn('Discovery for placement API URI failed.', res.details)
|
||||||
|
|
||||||
@mock.patch.object(status.UpgradeCommands, "_placement_get")
|
@mock.patch.object(status.UpgradeCommands, "_placement_get")
|
||||||
@ -204,7 +205,7 @@ class TestPlacementCheck(test.NoDBTestCase):
|
|||||||
"""
|
"""
|
||||||
get.side_effect = ks_exc.NotFound()
|
get.side_effect = ks_exc.NotFound()
|
||||||
res = self.cmd._check_placement()
|
res = self.cmd._check_placement()
|
||||||
self.assertEqual(status.UpgradeCheckCode.FAILURE, res.code)
|
self.assertEqual(upgradecheck.Code.FAILURE, res.code)
|
||||||
self.assertIn('Placement API does not seem to be running', res.details)
|
self.assertIn('Placement API does not seem to be running', res.details)
|
||||||
|
|
||||||
@mock.patch.object(status.UpgradeCommands, "_placement_get")
|
@mock.patch.object(status.UpgradeCommands, "_placement_get")
|
||||||
@ -219,7 +220,7 @@ class TestPlacementCheck(test.NoDBTestCase):
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
res = self.cmd._check_placement()
|
res = self.cmd._check_placement()
|
||||||
self.assertEqual(status.UpgradeCheckCode.SUCCESS, res.code)
|
self.assertEqual(upgradecheck.Code.SUCCESS, res.code)
|
||||||
|
|
||||||
@mock.patch.object(status.UpgradeCommands, "_placement_get")
|
@mock.patch.object(status.UpgradeCommands, "_placement_get")
|
||||||
def test_version_comparison_does_not_use_floats(self, get):
|
def test_version_comparison_does_not_use_floats(self, get):
|
||||||
@ -239,7 +240,7 @@ class TestPlacementCheck(test.NoDBTestCase):
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
res = self.cmd._check_placement()
|
res = self.cmd._check_placement()
|
||||||
self.assertEqual(status.UpgradeCheckCode.SUCCESS, res.code)
|
self.assertEqual(upgradecheck.Code.SUCCESS, res.code)
|
||||||
|
|
||||||
@mock.patch.object(status.UpgradeCommands, "_placement_get")
|
@mock.patch.object(status.UpgradeCommands, "_placement_get")
|
||||||
def test_invalid_version(self, get):
|
def test_invalid_version(self, get):
|
||||||
@ -253,109 +254,11 @@ class TestPlacementCheck(test.NoDBTestCase):
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
res = self.cmd._check_placement()
|
res = self.cmd._check_placement()
|
||||||
self.assertEqual(status.UpgradeCheckCode.FAILURE, res.code)
|
self.assertEqual(upgradecheck.Code.FAILURE, res.code)
|
||||||
self.assertIn('Placement API version %s needed, you have 0.9' %
|
self.assertIn('Placement API version %s needed, you have 0.9' %
|
||||||
status.MIN_PLACEMENT_MICROVERSION, res.details)
|
status.MIN_PLACEMENT_MICROVERSION, res.details)
|
||||||
|
|
||||||
|
|
||||||
class TestUpgradeCheckBasic(test.NoDBTestCase):
|
|
||||||
"""Tests for the nova-status upgrade check command.
|
|
||||||
|
|
||||||
The tests in this class should just test basic logic and use mock. Real
|
|
||||||
checks which require more elaborate fixtures or the database should be done
|
|
||||||
in separate test classes as they are more or less specific to a particular
|
|
||||||
release and may be removed in a later release after they are no longer
|
|
||||||
needed.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def setUp(self):
|
|
||||||
super(TestUpgradeCheckBasic, self).setUp()
|
|
||||||
self.output = StringIO()
|
|
||||||
self.useFixture(fixtures.MonkeyPatch('sys.stdout', self.output))
|
|
||||||
self.cmd = status.UpgradeCommands()
|
|
||||||
|
|
||||||
def test_check_success(self):
|
|
||||||
fake_checks = (
|
|
||||||
('good', mock.Mock(return_value=status.UpgradeCheckResult(
|
|
||||||
status.UpgradeCheckCode.SUCCESS
|
|
||||||
))),
|
|
||||||
)
|
|
||||||
with mock.patch.object(self.cmd, '_upgrade_checks', fake_checks):
|
|
||||||
self.assertEqual(status.UpgradeCheckCode.SUCCESS, self.cmd.check())
|
|
||||||
expected = """\
|
|
||||||
+-----------------------+
|
|
||||||
| Upgrade Check Results |
|
|
||||||
+-----------------------+
|
|
||||||
| Check: good |
|
|
||||||
| Result: Success |
|
|
||||||
| Details: None |
|
|
||||||
+-----------------------+
|
|
||||||
"""
|
|
||||||
self.assertEqual(expected, self.output.getvalue())
|
|
||||||
|
|
||||||
def test_check_warning(self):
|
|
||||||
fake_checks = (
|
|
||||||
('good', mock.Mock(return_value=status.UpgradeCheckResult(
|
|
||||||
status.UpgradeCheckCode.SUCCESS
|
|
||||||
))),
|
|
||||||
('warn', mock.Mock(return_value=status.UpgradeCheckResult(
|
|
||||||
status.UpgradeCheckCode.WARNING, 'there might be a problem'
|
|
||||||
))),
|
|
||||||
)
|
|
||||||
with mock.patch.object(self.cmd, '_upgrade_checks', fake_checks):
|
|
||||||
self.assertEqual(status.UpgradeCheckCode.WARNING, self.cmd.check())
|
|
||||||
expected = """\
|
|
||||||
+-----------------------------------+
|
|
||||||
| Upgrade Check Results |
|
|
||||||
+-----------------------------------+
|
|
||||||
| Check: good |
|
|
||||||
| Result: Success |
|
|
||||||
| Details: None |
|
|
||||||
+-----------------------------------+
|
|
||||||
| Check: warn |
|
|
||||||
| Result: Warning |
|
|
||||||
| Details: there might be a problem |
|
|
||||||
+-----------------------------------+
|
|
||||||
"""
|
|
||||||
self.assertEqual(expected, self.output.getvalue())
|
|
||||||
|
|
||||||
def test_check_failure(self):
|
|
||||||
# make the error details over 60 characters so we test the wrapping
|
|
||||||
error_details = 'go back to bed' + '!' * 60
|
|
||||||
fake_checks = (
|
|
||||||
('good', mock.Mock(return_value=status.UpgradeCheckResult(
|
|
||||||
status.UpgradeCheckCode.SUCCESS
|
|
||||||
))),
|
|
||||||
('warn', mock.Mock(return_value=status.UpgradeCheckResult(
|
|
||||||
status.UpgradeCheckCode.WARNING, 'there might be a problem'
|
|
||||||
))),
|
|
||||||
('fail', mock.Mock(return_value=status.UpgradeCheckResult(
|
|
||||||
status.UpgradeCheckCode.FAILURE, error_details
|
|
||||||
))),
|
|
||||||
)
|
|
||||||
with mock.patch.object(self.cmd, '_upgrade_checks', fake_checks):
|
|
||||||
self.assertEqual(status.UpgradeCheckCode.FAILURE, self.cmd.check())
|
|
||||||
expected = """\
|
|
||||||
+-----------------------------------------------------------------------+
|
|
||||||
| Upgrade Check Results |
|
|
||||||
+-----------------------------------------------------------------------+
|
|
||||||
| Check: good |
|
|
||||||
| Result: Success |
|
|
||||||
| Details: None |
|
|
||||||
+-----------------------------------------------------------------------+
|
|
||||||
| Check: warn |
|
|
||||||
| Result: Warning |
|
|
||||||
| Details: there might be a problem |
|
|
||||||
+-----------------------------------------------------------------------+
|
|
||||||
| Check: fail |
|
|
||||||
| Result: Failure |
|
|
||||||
| Details: go back to bed!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! |
|
|
||||||
| !!!!!!!!!!!!!! |
|
|
||||||
+-----------------------------------------------------------------------+
|
|
||||||
"""
|
|
||||||
self.assertEqual(expected, self.output.getvalue())
|
|
||||||
|
|
||||||
|
|
||||||
class TestUpgradeCheckCellsV2(test.NoDBTestCase):
|
class TestUpgradeCheckCellsV2(test.NoDBTestCase):
|
||||||
"""Tests for the nova-status upgrade cells v2 specific check."""
|
"""Tests for the nova-status upgrade cells v2 specific check."""
|
||||||
|
|
||||||
@ -374,7 +277,7 @@ class TestUpgradeCheckCellsV2(test.NoDBTestCase):
|
|||||||
"""The cells v2 check should fail because there are no cell mappings.
|
"""The cells v2 check should fail because there are no cell mappings.
|
||||||
"""
|
"""
|
||||||
result = self.cmd._check_cellsv2()
|
result = self.cmd._check_cellsv2()
|
||||||
self.assertEqual(status.UpgradeCheckCode.FAILURE, result.code)
|
self.assertEqual(upgradecheck.Code.FAILURE, result.code)
|
||||||
self.assertIn('There needs to be at least two cell mappings',
|
self.assertIn('There needs to be at least two cell mappings',
|
||||||
result.details)
|
result.details)
|
||||||
|
|
||||||
@ -395,7 +298,7 @@ class TestUpgradeCheckCellsV2(test.NoDBTestCase):
|
|||||||
self._create_cell_mapping(uuid)
|
self._create_cell_mapping(uuid)
|
||||||
|
|
||||||
result = self.cmd._check_cellsv2()
|
result = self.cmd._check_cellsv2()
|
||||||
self.assertEqual(status.UpgradeCheckCode.FAILURE, result.code)
|
self.assertEqual(upgradecheck.Code.FAILURE, result.code)
|
||||||
self.assertIn('No cell0 mapping found', result.details)
|
self.assertIn('No cell0 mapping found', result.details)
|
||||||
|
|
||||||
def test_check_no_host_mappings_with_computes(self):
|
def test_check_no_host_mappings_with_computes(self):
|
||||||
@ -418,7 +321,7 @@ class TestUpgradeCheckCellsV2(test.NoDBTestCase):
|
|||||||
cn.create()
|
cn.create()
|
||||||
|
|
||||||
result = self.cmd._check_cellsv2()
|
result = self.cmd._check_cellsv2()
|
||||||
self.assertEqual(status.UpgradeCheckCode.FAILURE, result.code)
|
self.assertEqual(upgradecheck.Code.FAILURE, result.code)
|
||||||
self.assertIn('No host mappings found but there are compute nodes',
|
self.assertIn('No host mappings found but there are compute nodes',
|
||||||
result.details)
|
result.details)
|
||||||
|
|
||||||
@ -429,7 +332,7 @@ class TestUpgradeCheckCellsV2(test.NoDBTestCase):
|
|||||||
self._setup_cells()
|
self._setup_cells()
|
||||||
|
|
||||||
result = self.cmd._check_cellsv2()
|
result = self.cmd._check_cellsv2()
|
||||||
self.assertEqual(status.UpgradeCheckCode.SUCCESS, result.code)
|
self.assertEqual(upgradecheck.Code.SUCCESS, result.code)
|
||||||
self.assertIn('No host mappings or compute nodes were found',
|
self.assertIn('No host mappings or compute nodes were found',
|
||||||
result.details)
|
result.details)
|
||||||
|
|
||||||
@ -446,7 +349,7 @@ class TestUpgradeCheckCellsV2(test.NoDBTestCase):
|
|||||||
hm.create()
|
hm.create()
|
||||||
|
|
||||||
result = self.cmd._check_cellsv2()
|
result = self.cmd._check_cellsv2()
|
||||||
self.assertEqual(status.UpgradeCheckCode.SUCCESS, result.code)
|
self.assertEqual(upgradecheck.Code.SUCCESS, result.code)
|
||||||
self.assertIsNone(result.details)
|
self.assertIsNone(result.details)
|
||||||
|
|
||||||
|
|
||||||
@ -522,7 +425,7 @@ class TestUpgradeCheckIronicFlavorMigration(test.NoDBTestCase):
|
|||||||
warning.
|
warning.
|
||||||
"""
|
"""
|
||||||
result = self.cmd._check_ironic_flavor_migration()
|
result = self.cmd._check_ironic_flavor_migration()
|
||||||
self.assertEqual(status.UpgradeCheckCode.WARNING, result.code)
|
self.assertEqual(upgradecheck.Code.WARNING, result.code)
|
||||||
self.assertIn('Unable to determine ironic flavor migration without '
|
self.assertIn('Unable to determine ironic flavor migration without '
|
||||||
'cell mappings', result.details)
|
'cell mappings', result.details)
|
||||||
|
|
||||||
@ -533,7 +436,7 @@ class TestUpgradeCheckIronicFlavorMigration(test.NoDBTestCase):
|
|||||||
"""
|
"""
|
||||||
self._setup_cells()
|
self._setup_cells()
|
||||||
result = self.cmd._check_ironic_flavor_migration()
|
result = self.cmd._check_ironic_flavor_migration()
|
||||||
self.assertEqual(status.UpgradeCheckCode.SUCCESS, result.code)
|
self.assertEqual(upgradecheck.Code.SUCCESS, result.code)
|
||||||
|
|
||||||
def test_mixed_computes_deleted_ironic_instance(self):
|
def test_mixed_computes_deleted_ironic_instance(self):
|
||||||
"""Tests the scenario where we have a kvm compute node in one cell
|
"""Tests the scenario where we have a kvm compute node in one cell
|
||||||
@ -557,7 +460,7 @@ class TestUpgradeCheckIronicFlavorMigration(test.NoDBTestCase):
|
|||||||
ctxt, self.cell_mappings['cell1'], ironic_node, is_deleted=True)
|
ctxt, self.cell_mappings['cell1'], ironic_node, is_deleted=True)
|
||||||
|
|
||||||
result = self.cmd._check_ironic_flavor_migration()
|
result = self.cmd._check_ironic_flavor_migration()
|
||||||
self.assertEqual(status.UpgradeCheckCode.SUCCESS, result.code)
|
self.assertEqual(upgradecheck.Code.SUCCESS, result.code)
|
||||||
|
|
||||||
def test_unmigrated_ironic_instances(self):
|
def test_unmigrated_ironic_instances(self):
|
||||||
"""Tests a scenario where we have two cells with only ironic compute
|
"""Tests a scenario where we have two cells with only ironic compute
|
||||||
@ -590,7 +493,7 @@ class TestUpgradeCheckIronicFlavorMigration(test.NoDBTestCase):
|
|||||||
ctxt, cell, ironic_node, flavor_migrated=False)
|
ctxt, cell, ironic_node, flavor_migrated=False)
|
||||||
|
|
||||||
result = self.cmd._check_ironic_flavor_migration()
|
result = self.cmd._check_ironic_flavor_migration()
|
||||||
self.assertEqual(status.UpgradeCheckCode.FAILURE, result.code)
|
self.assertEqual(upgradecheck.Code.FAILURE, result.code)
|
||||||
# Check the message - it should point out cell1 has one unmigrated
|
# Check the message - it should point out cell1 has one unmigrated
|
||||||
# instance and cell2 has two unmigrated instances.
|
# instance and cell2 has two unmigrated instances.
|
||||||
unmigrated_instance_count_by_cell = {
|
unmigrated_instance_count_by_cell = {
|
||||||
@ -629,12 +532,12 @@ class TestUpgradeCheckAPIServiceVersion(test.NoDBTestCase):
|
|||||||
"""
|
"""
|
||||||
self.flags(enable=True, group='cells')
|
self.flags(enable=True, group='cells')
|
||||||
result = self.cmd._check_api_service_version()
|
result = self.cmd._check_api_service_version()
|
||||||
self.assertEqual(status.UpgradeCheckCode.SUCCESS, result.code)
|
self.assertEqual(upgradecheck.Code.SUCCESS, result.code)
|
||||||
|
|
||||||
def test_check_no_cell_mappings_warning(self):
|
def test_check_no_cell_mappings_warning(self):
|
||||||
"""Warn when there are no cell mappings."""
|
"""Warn when there are no cell mappings."""
|
||||||
result = self.cmd._check_api_service_version()
|
result = self.cmd._check_api_service_version()
|
||||||
self.assertEqual(status.UpgradeCheckCode.WARNING, result.code)
|
self.assertEqual(upgradecheck.Code.WARNING, result.code)
|
||||||
self.assertEqual('Unable to determine API service versions without '
|
self.assertEqual('Unable to determine API service versions without '
|
||||||
'cell mappings.', result.details)
|
'cell mappings.', result.details)
|
||||||
|
|
||||||
@ -684,7 +587,7 @@ class TestUpgradeCheckAPIServiceVersion(test.NoDBTestCase):
|
|||||||
binary='nova-compute', version=14)
|
binary='nova-compute', version=14)
|
||||||
|
|
||||||
result = self.cmd._check_api_service_version()
|
result = self.cmd._check_api_service_version()
|
||||||
self.assertEqual(status.UpgradeCheckCode.WARNING, result.code)
|
self.assertEqual(upgradecheck.Code.WARNING, result.code)
|
||||||
# The only cell in the message should be cell0.
|
# The only cell in the message should be cell0.
|
||||||
self.assertIn(cell0.uuid, result.details)
|
self.assertIn(cell0.uuid, result.details)
|
||||||
self.assertNotIn(cell1.uuid, result.details)
|
self.assertNotIn(cell1.uuid, result.details)
|
||||||
@ -707,7 +610,7 @@ class TestUpgradeCheckAPIServiceVersion(test.NoDBTestCase):
|
|||||||
binary='nova-compute', version=15)
|
binary='nova-compute', version=15)
|
||||||
|
|
||||||
result = self.cmd._check_api_service_version()
|
result = self.cmd._check_api_service_version()
|
||||||
self.assertEqual(status.UpgradeCheckCode.SUCCESS, result.code)
|
self.assertEqual(upgradecheck.Code.SUCCESS, result.code)
|
||||||
|
|
||||||
|
|
||||||
class TestUpgradeCheckRequestSpecMigration(test.NoDBTestCase):
|
class TestUpgradeCheckRequestSpecMigration(test.NoDBTestCase):
|
||||||
@ -758,7 +661,7 @@ class TestUpgradeCheckRequestSpecMigration(test.NoDBTestCase):
|
|||||||
warning.
|
warning.
|
||||||
"""
|
"""
|
||||||
result = self.cmd._check_request_spec_migration()
|
result = self.cmd._check_request_spec_migration()
|
||||||
self.assertEqual(status.UpgradeCheckCode.WARNING, result.code)
|
self.assertEqual(upgradecheck.Code.WARNING, result.code)
|
||||||
self.assertIn('Unable to determine request spec migrations without '
|
self.assertIn('Unable to determine request spec migrations without '
|
||||||
'cell mappings.', result.details)
|
'cell mappings.', result.details)
|
||||||
|
|
||||||
@ -779,7 +682,7 @@ class TestUpgradeCheckRequestSpecMigration(test.NoDBTestCase):
|
|||||||
ctxt, self.cell_mappings['cell2'], create_request_spec=True)
|
ctxt, self.cell_mappings['cell2'], create_request_spec=True)
|
||||||
|
|
||||||
result = self.cmd._check_request_spec_migration()
|
result = self.cmd._check_request_spec_migration()
|
||||||
self.assertEqual(status.UpgradeCheckCode.SUCCESS, result.code)
|
self.assertEqual(upgradecheck.Code.SUCCESS, result.code)
|
||||||
|
|
||||||
def test_unmigrated_request_spec_instances(self):
|
def test_unmigrated_request_spec_instances(self):
|
||||||
"""Tests the scenario that we have a migrated instance in cell1 and
|
"""Tests the scenario that we have a migrated instance in cell1 and
|
||||||
@ -796,7 +699,7 @@ class TestUpgradeCheckRequestSpecMigration(test.NoDBTestCase):
|
|||||||
self._create_instance_in_cell(ctxt, self.cell_mappings['cell2'])
|
self._create_instance_in_cell(ctxt, self.cell_mappings['cell2'])
|
||||||
|
|
||||||
result = self.cmd._check_request_spec_migration()
|
result = self.cmd._check_request_spec_migration()
|
||||||
self.assertEqual(status.UpgradeCheckCode.FAILURE, result.code)
|
self.assertEqual(upgradecheck.Code.FAILURE, result.code)
|
||||||
self.assertIn("The following cells have instances which do not have "
|
self.assertIn("The following cells have instances which do not have "
|
||||||
"matching request_specs in the API database: %s Run "
|
"matching request_specs in the API database: %s Run "
|
||||||
"'nova-manage db online_data_migrations' on each cell "
|
"'nova-manage db online_data_migrations' on each cell "
|
||||||
@ -856,7 +759,7 @@ class TestUpgradeCheckConsoles(test.NoDBTestCase):
|
|||||||
"""
|
"""
|
||||||
self.flags(enable=True, group='cells')
|
self.flags(enable=True, group='cells')
|
||||||
result = self.cmd._check_console_auths()
|
result = self.cmd._check_console_auths()
|
||||||
self.assertEqual(status.UpgradeCheckCode.SUCCESS, result.code)
|
self.assertEqual(upgradecheck.Code.SUCCESS, result.code)
|
||||||
|
|
||||||
def test_check_workaround_enabled(self):
|
def test_check_workaround_enabled(self):
|
||||||
"""This is a 'success' case since the console auths check is
|
"""This is a 'success' case since the console auths check is
|
||||||
@ -864,7 +767,7 @@ class TestUpgradeCheckConsoles(test.NoDBTestCase):
|
|||||||
"""
|
"""
|
||||||
self.flags(enable_consoleauth=True, group='workarounds')
|
self.flags(enable_consoleauth=True, group='workarounds')
|
||||||
result = self.cmd._check_console_auths()
|
result = self.cmd._check_console_auths()
|
||||||
self.assertEqual(status.UpgradeCheckCode.SUCCESS, result.code)
|
self.assertEqual(upgradecheck.Code.SUCCESS, result.code)
|
||||||
|
|
||||||
def test_deleted_disabled_consoleauth(self):
|
def test_deleted_disabled_consoleauth(self):
|
||||||
"""Tests that services other than nova-consoleauth and deleted/disabled
|
"""Tests that services other than nova-consoleauth and deleted/disabled
|
||||||
@ -887,7 +790,7 @@ class TestUpgradeCheckConsoles(test.NoDBTestCase):
|
|||||||
'nova-consoleauth', disabled=True)
|
'nova-consoleauth', disabled=True)
|
||||||
|
|
||||||
result = self.cmd._check_console_auths()
|
result = self.cmd._check_console_auths()
|
||||||
self.assertEqual(status.UpgradeCheckCode.SUCCESS, result.code)
|
self.assertEqual(upgradecheck.Code.SUCCESS, result.code)
|
||||||
|
|
||||||
def test_consoleauth_with_upgrade_not_started(self):
|
def test_consoleauth_with_upgrade_not_started(self):
|
||||||
"""Tests the scenario where the deployment is using consoles but has no
|
"""Tests the scenario where the deployment is using consoles but has no
|
||||||
@ -908,7 +811,7 @@ class TestUpgradeCheckConsoles(test.NoDBTestCase):
|
|||||||
'nova-compute', version=30)
|
'nova-compute', version=30)
|
||||||
|
|
||||||
result = self.cmd._check_console_auths()
|
result = self.cmd._check_console_auths()
|
||||||
self.assertEqual(status.UpgradeCheckCode.WARNING, result.code)
|
self.assertEqual(upgradecheck.Code.WARNING, result.code)
|
||||||
|
|
||||||
def test_consoleauth_with_upgrade_complete(self):
|
def test_consoleauth_with_upgrade_complete(self):
|
||||||
"""Tests the scenario where the deployment is using consoles and has
|
"""Tests the scenario where the deployment is using consoles and has
|
||||||
@ -939,7 +842,7 @@ class TestUpgradeCheckConsoles(test.NoDBTestCase):
|
|||||||
'nova-compute', version=30)
|
'nova-compute', version=30)
|
||||||
|
|
||||||
result = self.cmd._check_console_auths()
|
result = self.cmd._check_console_auths()
|
||||||
self.assertEqual(status.UpgradeCheckCode.SUCCESS, result.code)
|
self.assertEqual(upgradecheck.Code.SUCCESS, result.code)
|
||||||
|
|
||||||
def test_consoleauth_with_upgrade_partial(self):
|
def test_consoleauth_with_upgrade_partial(self):
|
||||||
"""Tests the scenario where the deployment is using consoles and has
|
"""Tests the scenario where the deployment is using consoles and has
|
||||||
@ -968,7 +871,7 @@ class TestUpgradeCheckConsoles(test.NoDBTestCase):
|
|||||||
|
|
||||||
result = self.cmd._check_console_auths()
|
result = self.cmd._check_console_auths()
|
||||||
|
|
||||||
self.assertEqual(status.UpgradeCheckCode.WARNING, result.code)
|
self.assertEqual(upgradecheck.Code.WARNING, result.code)
|
||||||
self.assertIn("One or more cells were found which have nova-compute "
|
self.assertIn("One or more cells were found which have nova-compute "
|
||||||
"services older than Rocky. "
|
"services older than Rocky. "
|
||||||
"Please set the '[workarounds]enable_consoleauth' "
|
"Please set the '[workarounds]enable_consoleauth' "
|
||||||
|
@ -42,6 +42,7 @@ oslo.context>=2.19.2 # Apache-2.0
|
|||||||
oslo.log>=3.36.0 # Apache-2.0
|
oslo.log>=3.36.0 # Apache-2.0
|
||||||
oslo.reports>=1.18.0 # Apache-2.0
|
oslo.reports>=1.18.0 # Apache-2.0
|
||||||
oslo.serialization!=2.19.1,>=2.18.0 # Apache-2.0
|
oslo.serialization!=2.19.1,>=2.18.0 # Apache-2.0
|
||||||
|
oslo.upgradecheck>=0.1.1
|
||||||
oslo.utils>=3.37.0 # Apache-2.0
|
oslo.utils>=3.37.0 # Apache-2.0
|
||||||
oslo.db>=4.40.0 # Apache-2.0
|
oslo.db>=4.40.0 # Apache-2.0
|
||||||
oslo.rootwrap>=5.8.0 # Apache-2.0
|
oslo.rootwrap>=5.8.0 # Apache-2.0
|
||||||
|
Loading…
Reference in New Issue
Block a user