Add validation to AIO-SX to AIO-DX migration command

In an SX with ceph backend configured and platform-integ-apps not
applied, an unhandled error shows when the command "system
modify --system_mode=duplex" is executed. After this error, the
system_mode in sysinv db is changed to "duplex" and cannot change
back to simplex, blocking further system CLI operation.

It is necessary for an SX with the ceph backend configured to have
platform-integ-apps applied to migrate to DX. With the fix, there
is a validation checking that the system storage backend is able
for a migration, raising a proper error if not. In addition, if
the system is not ready, there are no changes in the sysinv db.

Test-Plan:
  PASS: AIO-SX fresh install with ceph backend
  PASS: Use system modify --system_mode=duplex with
        platform-integ-apps not applied (uploaded or not)
  PASS: Verify the error message "Cannot modify system mode..."
        is printed on CLI
  PASS: Verify system_mode is still 'simplex' in the sysinv db
  PASS: Apply platform-integ-apps, use the same command, proceed
        with the migration and validate that it was successful
  PASS: AIO-SX fresh install without Ceph backend + successful
        migration to DX

Closes-Bug: 2013069
Signed-off-by: Gabriel de Araújo Cabral <gabriel.cabral@windriver.com>
Change-Id: Ib05c675b54c2b9fcfa3e7f92affec9ca37245df2
This commit is contained in:
Gabriel de Araújo Cabral 2023-03-27 14:57:31 -04:00
parent 86379201b4
commit 8f8c7d3abb
2 changed files with 61 additions and 0 deletions

View File

@ -334,6 +334,20 @@ class SystemController(rest.RestController):
"locked." % controller.hostname)
raise wsme.exc.ClientSideError(msg)
def _check_storage_backend_ready_for_migration(self):
ceph_backend = pecan.request.dbapi.storage_backend_get_list_by_type(
backend_type=constants.SB_TYPE_CEPH)
if ceph_backend:
msg = _("Cannot modify system mode to %s, %s must be "
"applied when ceph storage is configured as backend." %
(constants.SYSTEM_MODE_DUPLEX, constants.HELM_APP_PLATFORM))
try:
helm_app = pecan.request.dbapi.kube_app_get(constants.HELM_APP_PLATFORM)
if helm_app.status != constants.APP_APPLY_SUCCESS:
raise wsme.exc.ClientSideError(msg)
except exception.KubeAppNotFound:
raise wsme.exc.ClientSideError(msg)
def _get_isystem_collection(self, marker, limit, sort_key, sort_dir,
expand=False, resource_url=None):
limit = api_utils.validate_limit(limit)
@ -461,6 +475,9 @@ class SystemController(rest.RestController):
self._check_controller_locked()
if new_system_mode != constants.SYSTEM_MODE_SIMPLEX:
self._check_interfaces(new_system_mode)
if rpc_isystem.system_mode == constants.SYSTEM_MODE_SIMPLEX and \
new_system_mode == constants.SYSTEM_MODE_DUPLEX:
self._check_storage_backend_ready_for_migration()
if p['path'] == '/timezone':
timezone = p['value']

View File

@ -233,6 +233,20 @@ class TestNetworkSetup(object):
network_id=self.admin_network.id)
class TestStorageBackend(object):
def __init__(self, system, dbapi):
self.system = system
self.dbapi = dbapi
def _create_ceph_storage_backend(self, backend_type=constants.SB_TYPE_CEPH):
backend = dbutils.get_test_ceph_storage_backend(backend=backend_type)
self.dbapi.storage_ceph_create(backend)
def _create_helm_app(self, app_status, app_name=constants.HELM_APP_PLATFORM):
self.helm_app = dbutils.create_test_app(name=app_name,
status=app_status)
@mock.patch('socket.gethostname', return_value='controller-0')
class TestSystemUpdateModeFromSimplex(TestSystem):
@ -243,6 +257,7 @@ class TestSystemUpdateModeFromSimplex(TestSystem):
system_mode=constants.SYSTEM_MODE_SIMPLEX)
self.test_network = TestNetworkSetup(self.system,
controller_administrative_status=constants.ADMIN_LOCKED)
self.test_storage_backend = TestStorageBackend(self.system, self.dbapi)
@mock.patch('sysinv.common.utils.is_initial_config_complete',
return_value=True)
@ -254,6 +269,35 @@ class TestSystemUpdateModeFromSimplex(TestSystem):
self._patch_and_check(self._get_path(self.system.uuid),
update)
@mock.patch('sysinv.common.utils.is_initial_config_complete',
return_value=True)
def test_update_system_mode_simplex_to_duplex_with_ceph_and_helm_app_applied(self,
mock_init_config,
mock_controller):
self.test_network._create_mgmt_interface_network()
self.test_network._create_cluster_host_interface_network()
self.test_storage_backend._create_ceph_storage_backend()
self.test_storage_backend._create_helm_app(app_status=constants.APP_APPLY_SUCCESS)
update = {"system_mode": constants.SYSTEM_MODE_DUPLEX}
self._patch_and_check(self._get_path(self.system.uuid),
update)
@mock.patch('sysinv.common.utils.is_initial_config_complete',
return_value=True)
def test_update_system_mode_simplex_to_duplex_with_ceph_and_no_helm_app_applied(self,
mock_init_config,
mock_controller):
self.test_network._create_mgmt_interface_network()
self.test_network._create_cluster_host_interface_network()
self.test_storage_backend._create_ceph_storage_backend()
update = {"system_mode": constants.SYSTEM_MODE_DUPLEX}
msg = ("Cannot modify system mode to %s, %s must be "
"applied when ceph storage is configured as backend." %
(constants.SYSTEM_MODE_DUPLEX, constants.HELM_APP_PLATFORM))
self._patch_and_check(self._get_path(self.system.uuid),
update, expect_errors=True,
expected_error_message=msg)
@mock.patch('sysinv.common.utils.is_initial_config_complete',
return_value=True)
def test_update_system_mode_simplex_to_duplex_mgmt_on_lo(self,