Qcow2 conversion to raw can be done using 'image-conversion' filesystem

1. Conversion filesystem can be added before/after
   stx-openstack is applied
2. If conversion filesystem is added after stx-openstack
   is applied, changes to stx-openstack will only take effect
   once the application is re-applied

3. It is not allowed to delete image-conversion filesystem
   when stx-openstack is in applying/applied/removing state
4. Raise alarms for image-conversion

Change-Id: Ie205329b694525509b0820497186fcd9ec2e45c9
Closes-bug: 1819688
Depends-On: https://review.opendev.org/#/c/724270/
Depends-On: https://review.opendev.org/724288/
Signed-off-by: Elena Taivan <elena.taivan@windriver.com>
This commit is contained in:
Elena Taivan 2020-04-29 11:25:26 +00:00
parent bc9cde71a0
commit 491cca42ed
5 changed files with 146 additions and 2 deletions

View File

@ -472,8 +472,18 @@ def _delete(host_fs):
_check_host_fs(host_fs)
ihost = pecan.request.dbapi.ihost_get(host_fs['forihostid'])
if host_fs['name'] == constants.FILESYSTEM_NAME_IMAGE_CONVERSION:
try:
app = pecan.request.dbapi.kube_app_get(constants.HELM_APP_OPENSTACK)
if app.status != constants.APP_UPLOAD_SUCCESS:
raise wsme.exc.ClientSideError(_("Deleting filesystem %s is not allowed "
"when stx-openstack is in %s state" %
(host_fs['name'], app.status)))
except exception.KubeAppNotFound:
LOG.info("Application %s not found, deleting %s fs" %
constants.HELM_APP_OPENSTACK, host_fs['name'])
ihost = pecan.request.dbapi.ihost_get(host_fs['forihostid'])
try:
pecan.request.dbapi.host_fs_destroy(host_fs['id'])
except exception.HTTPNotFound:

View File

@ -4946,6 +4946,9 @@ class ConductorManager(service.PeriodicService):
# Audit kubernetes node labels
self._audit_kubernetes_labels(hosts)
# Audit image conversion
self._audit_image_conversion(hosts)
for host in hosts:
# only audit configured hosts
if not host.personality:
@ -5015,6 +5018,49 @@ class ConductorManager(service.PeriodicService):
elif bk.backend in self._stor_bck_op_timeouts:
del self._stor_bck_op_timeouts[bk.backend]
def _audit_image_conversion(self, hosts):
"""
Raise alarm if:
- image-conversion is not added on both controllers;
- the size of the filesystem is not the same
on both controllers
"""
chosts = [h for h in hosts if h.personality == constants.CONTROLLER]
if len(chosts) <= 1:
# No alarm is raised if setup has only one controller
return
conversion_list = []
for host in chosts:
hostfs_list = self.dbapi.host_fs_get_by_ihost(host.uuid)
for host_fs in hostfs_list:
if host_fs['name'] == constants.FILESYSTEM_NAME_IMAGE_CONVERSION:
conversion_list.append(host_fs['size'])
reason_text = "image-conversion must be added on both controllers"
if not conversion_list:
# If no conversion filesystem is present on any host
# any alarm present is cleared
self._update_image_conversion_alarm(fm_constants.FM_ALARM_STATE_CLEAR,
constants.FILESYSTEM_NAME_IMAGE_CONVERSION)
elif (len(conversion_list) == 1):
self._update_image_conversion_alarm(fm_constants.FM_ALARM_STATE_SET,
constants.FILESYSTEM_NAME_IMAGE_CONVERSION,
reason_text)
else:
# If conversion filesystem is present on both controllers
# with different sizes
self._update_image_conversion_alarm(fm_constants.FM_ALARM_STATE_CLEAR,
constants.FILESYSTEM_NAME_IMAGE_CONVERSION)
if (conversion_list[0] != conversion_list[1]):
reason_text = "image-conversion size must be the same on both controllers"
self._update_image_conversion_alarm(fm_constants.FM_ALARM_STATE_SET,
constants.FILESYSTEM_NAME_IMAGE_CONVERSION,
reason_text)
elif conversion_list[0] == conversion_list[1]:
self._update_image_conversion_alarm(fm_constants.FM_ALARM_STATE_CLEAR,
constants.FILESYSTEM_NAME_IMAGE_CONVERSION)
def _auto_upload_managed_app(self, context, app_name):
if self._patching_operation_is_occurring():
return
@ -6430,6 +6476,31 @@ class ConductorManager(service.PeriodicService):
'task': None}
self.dbapi.storage_ceph_external_update(sb_uuid, values)
def _update_image_conversion_alarm(self, alarm_state, fs_name, reason_text=None):
""" Raise conversion configuration alarm"""
entity_instance_id = "%s=%s" % (fm_constants.FM_ENTITY_TYPE_IMAGE_CONVERSION,
fs_name)
if alarm_state == fm_constants.FM_ALARM_STATE_SET:
fault = fm_api.Fault(
alarm_id=fm_constants.FM_ALARM_ID_IMAGE_CONVERSION,
alarm_state=alarm_state,
entity_type_id=fm_constants.FM_ENTITY_TYPE_IMAGE_CONVERSION,
entity_instance_id=entity_instance_id,
severity=fm_constants.FM_ALARM_SEVERITY_CRITICAL,
reason_text=reason_text,
alarm_type=fm_constants.FM_ALARM_TYPE_4,
probable_cause=fm_constants.ALARM_PROBABLE_CAUSE_7,
proposed_repair_action=_("Add image-conversion filesystem on both controllers."
"Consult the System Administration Manual "
"for more details. If problem persists, "
"contact next level of support."),
service_affecting=True)
self.fm_api.set_fault(fault)
else:
self.fm_api.clear_fault(fm_constants.FM_ALARM_ID_IMAGE_CONVERSION,
entity_instance_id)
def _update_storage_backend_alarm(self, alarm_state, backend, reason_text=None):
""" Update storage backend configuration alarm"""
entity_instance_id = "%s=%s" % (fm_constants.FM_ENTITY_TYPE_STORAGE_BACKEND,

View File

@ -1,9 +1,10 @@
#
# Copyright (c) 2018-2019 Wind River Systems, Inc.
# Copyright (c) 2018-2020 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
import tsconfig.tsconfig as tsc
from sysinv.common import constants
from sysinv.common import exception
from sysinv.common.storage_backend_conf import StorageBackendConfig
@ -21,10 +22,30 @@ class CinderHelm(openstack.OpenstackBaseHelm):
SERVICE_TYPE = 'volume'
AUTH_USERS = ['cinder']
def _get_mount_overrides(self):
overrides = {
'volumes': [],
'volumeMounts': []
}
overrides['volumes'].append({
'name': 'newvolume',
'hostPath': {'path': tsc.IMAGE_CONVERSION_PATH}
})
overrides['volumeMounts'].append({
'name': 'newvolume',
'mountPath': tsc.IMAGE_CONVERSION_PATH
})
return overrides
def get_overrides(self, namespace=None):
overrides = {
common.HELM_NS_OPENSTACK: {
'pod': {
'mounts': {
'cinder_volume': {
'cinder_volume': self._get_mount_overrides()
}
},
'replicas': {
'api': self._num_controllers(),
'volume': self._num_controllers(),
@ -99,6 +120,17 @@ class CinderHelm(openstack.OpenstackBaseHelm):
str(b.name.encode('utf8', 'strict').decode('utf-8')) for b in backends)
},
}
current_host_fs_list = self.dbapi.host_fs_get_list()
chosts = self.dbapi.ihost_get_by_personality(constants.CONTROLLER)
chosts_fs = [fs for fs in current_host_fs_list
if fs['name'] == constants.FILESYSTEM_NAME_IMAGE_CONVERSION]
# conversion overrides should be generated only if each controller node
# configured has the conversion partition added
if len(chosts) == len(chosts_fs):
conf_cinder['DEFAULT']['image_conversion_dir'] = \
tsc.IMAGE_CONVERSION_PATH
# Always set the default_volume_type to the volume type associated with the
# primary Ceph backend/tier which is available on all StarlingX platform

View File

@ -0,0 +1,30 @@
import tsconfig.tsconfig as tsc
from sysinv.helm import common
from sysinv.tests.db import base as dbbase
from sysinv.tests.db import utils as dbutils
from sysinv.tests.helm import base
from sysinv.tests.helm import test_helm
class CinderConversionTestCase(test_helm.StxOpenstackAppMixin,
base.HelmTestCaseMixin):
def setUp(self):
super(CinderConversionTestCase, self).setUp()
self.app = dbutils.create_test_app(name=self.app_name)
class CinderGetOverrideTest(CinderConversionTestCase,
dbbase.ControllerHostTestCase):
def test_cinder_overrides(self):
dbutils.create_test_host_fs(name='image-conversion',
forihostid=self.host.id)
overrides = self.operator.get_helm_chart_overrides(
common.HELM_CHART_CINDER,
cnamespace=common.HELM_NS_OPENSTACK)
self.assertOverridesParameters(overrides, {
'conf': {
'cinder': {
'DEFAULT': {
'image_conversion_dir': tsc.IMAGE_CONVERSION_PATH}}}
})

View File

@ -173,6 +173,7 @@ KEYRING_PATH = PLATFORM_PATH + "/.keyring/" + SW_VERSION
DEPLOY_PATH = PLATFORM_PATH + "/deploy/" + SW_VERSION
ETCD_PATH = "/opt/etcd"
EXTENSION_PATH = "/opt/extension"
IMAGE_CONVERSION_PATH = "/opt/conversion"
PLATFORM_CEPH_CONF_PATH = CONFIG_PATH + 'ceph-config'
PLATFORM_BACKUP_PATH = '/opt/platform-backup'