Bring up openstack services in stages during restore
During restore we need to bring up openstack services in stages. First we bring up MariaDB to populate the database. Then we bring up Glance and Cinder to restore images and volumes. Finally Nova and other services will be brought up. This is achieved by adding a "mode" option to sysinv application-apply API. For the stx-openstack application the possible values are "restore_db", "restore_storage" and "normal". The chartgroup list in the armada manifest will be modified by the generated meta-overrides based on the "mode". Story: 2004761 Task: 30522 Change-Id: I2bdb8b3a9e1fe34ee6f5f6e376279a5dc14f7cc4 Signed-off-by: Wei Zhou <wei.zhou@windriver.com>
This commit is contained in:
parent
7f17d2672c
commit
cbc5151cf2
|
@ -43,13 +43,14 @@ class AppManager(base.Manager):
|
|||
"""
|
||||
return self._create(self._path(), data)
|
||||
|
||||
def apply(self, app_name):
|
||||
def apply(self, app_name, data):
|
||||
"""Install/upgrade the specified application.
|
||||
|
||||
:param app_name: name of the application
|
||||
:param data: extra arguments
|
||||
"""
|
||||
return self._update(self._path(app_name) + '?directive=apply',
|
||||
{'values': {}})
|
||||
{'values': data})
|
||||
|
||||
def remove(self, app_name):
|
||||
"""Uninstall the specified application
|
||||
|
|
|
@ -98,10 +98,20 @@ def do_application_upload(cc, args):
|
|||
|
||||
@utils.arg('name', metavar='<app name>',
|
||||
help='Name of the application')
|
||||
@utils.arg('-m', '--mode',
|
||||
metavar='<mode>',
|
||||
default=None,
|
||||
help=('The mode is application specific. It controls how applicaton'
|
||||
' manifest is applied.'))
|
||||
def do_application_apply(cc, args):
|
||||
"""Apply/reapply the application manifest"""
|
||||
try:
|
||||
response = cc.app.apply(args.name)
|
||||
fields = ['mode']
|
||||
|
||||
data = dict((k, v) for (k, v) in vars(args).items()
|
||||
if k in fields and not (v is None))
|
||||
|
||||
response = cc.app.apply(args.name, data)
|
||||
_print_application_show(response)
|
||||
_print_reminder_msg(args.name)
|
||||
except exc.HTTPNotFound:
|
||||
|
|
|
@ -253,6 +253,22 @@ class KubeAppController(rest.RestController):
|
|||
"Application-{} rejected: application not found.".format(directive)))
|
||||
|
||||
if directive == 'apply':
|
||||
if not values:
|
||||
mode = None
|
||||
elif name not in constants.HELM_APP_APPLY_MODES.keys():
|
||||
raise wsme.exc.ClientSideError(_(
|
||||
"Application-apply rejected: Mode is not supported "
|
||||
"for app {}.".format(name)))
|
||||
elif (values['mode'] and
|
||||
values['mode'] not in constants.HELM_APP_APPLY_MODES[name]):
|
||||
raise wsme.exc.ClientSideError(_(
|
||||
"Application-apply rejected: Mode {} for app {} is not "
|
||||
"valid. Valid modes are {}.".format(
|
||||
values['mode'], name,
|
||||
constants.HELM_APP_APPLY_MODES[name])))
|
||||
else:
|
||||
mode = values['mode']
|
||||
|
||||
if db_app.status == constants.APP_APPLY_IN_PROGRESS:
|
||||
raise wsme.exc.ClientSideError(_(
|
||||
"Application-apply rejected: install/update is already "
|
||||
|
@ -268,7 +284,8 @@ class KubeAppController(rest.RestController):
|
|||
db_app.progress = None
|
||||
db_app.save()
|
||||
pecan.request.rpcapi.perform_app_apply(pecan.request.context,
|
||||
db_app, app_not_already_applied)
|
||||
db_app, app_not_already_applied,
|
||||
mode=mode)
|
||||
return KubeApp.convert_with_links(db_app)
|
||||
else:
|
||||
if db_app.status not in [constants.APP_APPLY_SUCCESS,
|
||||
|
|
|
@ -1464,6 +1464,22 @@ SUPPORTED_HELM_APP_NAMES = [
|
|||
HELM_APP_OPENSTACK
|
||||
]
|
||||
|
||||
# Apply mode for openstack app
|
||||
OPENSTACK_RESTORE_DB = 'restore_db'
|
||||
OPENSTACK_RESTORE_STORAGE = 'restore_storage'
|
||||
OPENSTACK_NORMAL = 'normal'
|
||||
|
||||
OPENSTACK_APP_APPLY_MODES = [
|
||||
OPENSTACK_RESTORE_DB,
|
||||
OPENSTACK_RESTORE_STORAGE,
|
||||
OPENSTACK_NORMAL
|
||||
]
|
||||
|
||||
# Appliction Apply Modes
|
||||
HELM_APP_APPLY_MODES = {
|
||||
HELM_APP_OPENSTACK: OPENSTACK_APP_APPLY_MODES
|
||||
}
|
||||
|
||||
# RBD Provisioner Ceph backend capabilities fields
|
||||
K8S_RBD_PROV_STORAGECLASS_NAME = 'rbd_storageclass_name' # Customer
|
||||
K8S_RBD_PROV_NAMESPACES = 'rbd_provisioner_namespaces' # Customer
|
||||
|
|
|
@ -440,7 +440,7 @@ class AppOperator(object):
|
|||
if app.system_app:
|
||||
LOG.info("Generating application overrides...")
|
||||
self._helm.generate_helm_application_overrides(
|
||||
app.name, cnamespace=None, armada_format=True, combined=True)
|
||||
app.name, mode=None, cnamespace=None, armada_format=True, combined=True)
|
||||
app.charts = self._get_list_of_charts(app.armada_mfile_abs)
|
||||
self._save_images_list_by_charts(app)
|
||||
# Get the list of images from the updated images overrides
|
||||
|
@ -753,7 +753,7 @@ class AppOperator(object):
|
|||
pass
|
||||
return charts
|
||||
|
||||
def _get_overrides_files(self, charts):
|
||||
def _get_overrides_files(self, charts, app_name, mode):
|
||||
"""Returns list of override files or None, used in
|
||||
application-install and application-delete."""
|
||||
|
||||
|
@ -773,7 +773,7 @@ class AppOperator(object):
|
|||
# sections of the chart schema other than "values, and can
|
||||
# affect the chartgroup or even the manifest.
|
||||
if self._helm.generate_meta_overrides(
|
||||
chart.name, chart.namespace):
|
||||
chart.name, chart.namespace, app_name, mode):
|
||||
overrides = chart.namespace + '-' + chart.name + \
|
||||
'-meta' + '.yaml'
|
||||
overrides_file = os.path.join(common.HELM_OVERRIDES_PATH,
|
||||
|
@ -952,7 +952,7 @@ class AppOperator(object):
|
|||
LOG.exception(e)
|
||||
self._abort_operation(app, constants.APP_UPLOAD_OP)
|
||||
|
||||
def perform_app_apply(self, rpc_app):
|
||||
def perform_app_apply(self, rpc_app, mode):
|
||||
"""Process application install request
|
||||
|
||||
This method processes node labels per configuration and invokes
|
||||
|
@ -969,6 +969,7 @@ class AppOperator(object):
|
|||
correct/update a previous manifest apply.
|
||||
|
||||
:param rpc_app: application object in the RPC request
|
||||
:param mode: mode to control how to apply application manifest
|
||||
:return boolean: whether application apply was successful
|
||||
"""
|
||||
|
||||
|
@ -985,9 +986,9 @@ class AppOperator(object):
|
|||
app, new_progress=constants.APP_PROGRESS_GENERATE_OVERRIDES)
|
||||
LOG.info("Generating application overrides...")
|
||||
self._helm.generate_helm_application_overrides(
|
||||
app.name, cnamespace=None, armada_format=True,
|
||||
app.name, mode, cnamespace=None, armada_format=True,
|
||||
combined=True)
|
||||
overrides_files = self._get_overrides_files(app.charts)
|
||||
overrides_files = self._get_overrides_files(app.charts, app.name, mode)
|
||||
if overrides_files:
|
||||
LOG.info("Application overrides generated.")
|
||||
# Ensure all chart overrides are readable by Armada
|
||||
|
|
|
@ -10664,15 +10664,16 @@ class ConductorManager(service.PeriodicService):
|
|||
"""
|
||||
self._app.perform_app_upload(rpc_app, tarfile)
|
||||
|
||||
def perform_app_apply(self, context, rpc_app, app_not_already_applied):
|
||||
def perform_app_apply(self, context, rpc_app, app_not_already_applied,
|
||||
mode):
|
||||
"""Handling of application install request (via AppOperator)
|
||||
|
||||
:param context: request context.
|
||||
:param rpc_app: data object provided in the rpc request
|
||||
:param app_not_already_applied: app not yet successfully applied
|
||||
|
||||
:param mode: mode to control how to apply application manifest
|
||||
"""
|
||||
app_installed = self._app.perform_app_apply(rpc_app)
|
||||
app_installed = self._app.perform_app_apply(rpc_app, mode)
|
||||
if app_installed and app_not_already_applied:
|
||||
# Update the VIM configuration as it may need to manage the newly
|
||||
# installed application. Only do this if the application
|
||||
|
|
|
@ -1745,18 +1745,21 @@ class ConductorAPI(sysinv.openstack.common.rpc.proxy.RpcProxy):
|
|||
rpc_app=rpc_app,
|
||||
tarfile=tarfile))
|
||||
|
||||
def perform_app_apply(self, context, rpc_app, app_not_already_applied):
|
||||
def perform_app_apply(self, context, rpc_app, app_not_already_applied,
|
||||
mode):
|
||||
"""Handle application apply request
|
||||
|
||||
:param context: request context.
|
||||
:param rpc_app: data object provided in the rpc request
|
||||
:param app_not_already_applied: app not already succesfully applied
|
||||
:param mode: mode to control how to apply application manifest
|
||||
"""
|
||||
return self.cast(context,
|
||||
self.make_msg(
|
||||
'perform_app_apply',
|
||||
rpc_app=rpc_app,
|
||||
app_not_already_applied=app_not_already_applied))
|
||||
app_not_already_applied=app_not_already_applied,
|
||||
mode=mode))
|
||||
|
||||
def perform_app_remove(self, context, rpc_app):
|
||||
"""Handle application remove request
|
||||
|
|
|
@ -214,7 +214,7 @@ class BaseHelm(object):
|
|||
"""
|
||||
return {}
|
||||
|
||||
def get_meta_overrides(self, namespace):
|
||||
def get_meta_overrides(self, namespace, app_name=None, mode=None):
|
||||
"""
|
||||
Return Armada-formatted chart-specific meta-overrides
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@ class GarbdHelm(base.BaseHelm):
|
|||
SUPPORTED_NAMESPACES = \
|
||||
base.BaseHelm.SUPPORTED_NAMESPACES + [common.HELM_NS_OPENSTACK]
|
||||
|
||||
def get_meta_overrides(self, namespace):
|
||||
def get_meta_overrides(self, namespace, app_name=None, mode=None):
|
||||
|
||||
def _meta_overrides():
|
||||
if (self._num_controllers() < 2 or
|
||||
|
|
|
@ -365,19 +365,21 @@ class HelmOperator(object):
|
|||
LOG.exception("chart name is required")
|
||||
|
||||
@helm_context
|
||||
def generate_meta_overrides(self, chart_name, chart_namespace):
|
||||
def generate_meta_overrides(self, chart_name, chart_namespace,
|
||||
app_name=None, mode=None):
|
||||
overrides = {}
|
||||
if chart_name in self.chart_operators:
|
||||
try:
|
||||
overrides.update(
|
||||
self.chart_operators[chart_name].get_meta_overrides(
|
||||
chart_namespace))
|
||||
chart_namespace, app_name, mode))
|
||||
except exception.InvalidHelmNamespace:
|
||||
raise
|
||||
return overrides
|
||||
|
||||
@helm_context
|
||||
def generate_helm_application_overrides(self, app_name, cnamespace=None,
|
||||
def generate_helm_application_overrides(self, app_name, mode=None,
|
||||
cnamespace=None,
|
||||
armada_format=False,
|
||||
combined=False):
|
||||
"""Create the system overrides files for a supported application
|
||||
|
@ -389,6 +391,7 @@ class HelmOperator(object):
|
|||
|
||||
:param app_name: name of the bundle of charts required to support an
|
||||
application
|
||||
:param mode: mode to control how to apply application manifest
|
||||
:param cnamespace: (optional) namespace
|
||||
:param armada_format: (optional) whether to emit in armada format
|
||||
instead of helm format (with extra header)
|
||||
|
@ -444,7 +447,9 @@ class HelmOperator(object):
|
|||
# armada format already.
|
||||
if armada_format:
|
||||
overrides = self.generate_meta_overrides(chart_name,
|
||||
cnamespace)
|
||||
cnamespace,
|
||||
app_name,
|
||||
mode)
|
||||
if overrides:
|
||||
chart_meta_name = chart_name + '-meta'
|
||||
self._write_chart_overrides(
|
||||
|
|
|
@ -21,6 +21,78 @@ class HelmToolkitHelm(base.BaseHelm):
|
|||
common.HELM_NS_HELM_TOOLKIT,
|
||||
]
|
||||
|
||||
# (WZ) This code will be moved to a proper place once meta-overrides
|
||||
# for the manifest can be generated not thru a specific chart.
|
||||
# Note: The application-apply mode is associated with the application not
|
||||
# the namespace. So app_name needs to be passed in.
|
||||
def get_meta_overrides(self, namespace, app_name=None, mode=None):
|
||||
def _meta_overrides(app_name, mode):
|
||||
if not app_name:
|
||||
# Application is unknown, so ignore mode.
|
||||
LOG.info("App is None. Ignore mode.")
|
||||
return {}
|
||||
elif app_name not in constants.HELM_APP_APPLY_MODES.keys():
|
||||
LOG.info("App %s is not supported. Ignore mode." % app_name)
|
||||
return {}
|
||||
elif mode == constants.OPENSTACK_RESTORE_DB:
|
||||
# During application restore, first bring up
|
||||
# MariaDB service.
|
||||
return {
|
||||
'schema': 'armada/Manifest/v1',
|
||||
'metadata': {
|
||||
'schema': 'metadata/Document/v1',
|
||||
'name': 'armada-manifest'
|
||||
},
|
||||
'data': {
|
||||
'release_prefix': 'osh',
|
||||
'chart_groups': [
|
||||
'kube-system-ingress',
|
||||
'openstack-ingress',
|
||||
'provisioner',
|
||||
'openstack-mariadb',
|
||||
]
|
||||
}
|
||||
}
|
||||
elif mode == constants.OPENSTACK_RESTORE_STORAGE:
|
||||
# After MariaDB data is restored, restore Keystone,
|
||||
# Glance and Cinder.
|
||||
return {
|
||||
'schema': 'armada/Manifest/v1',
|
||||
'metadata': {
|
||||
'schema': 'metadata/Document/v1',
|
||||
'name': 'armada-manifest'
|
||||
},
|
||||
'data': {
|
||||
'release_prefix': 'osh',
|
||||
'chart_groups': [
|
||||
'kube-system-ingress',
|
||||
'openstack-ingress',
|
||||
'provisioner',
|
||||
'openstack-mariadb',
|
||||
'openstack-memcached',
|
||||
'openstack-rabbitmq',
|
||||
'openstack-keystone',
|
||||
'openstack-glance',
|
||||
'openstack-cinder',
|
||||
]
|
||||
}
|
||||
}
|
||||
else:
|
||||
# When mode is OPENSTACK_RESTORE_NORMAL or None,
|
||||
# bring up all the openstack services.
|
||||
return {}
|
||||
|
||||
overrides = {
|
||||
common.HELM_NS_HELM_TOOLKIT: _meta_overrides(app_name, mode)
|
||||
}
|
||||
if namespace in self.SUPPORTED_NAMESPACES:
|
||||
return overrides[namespace]
|
||||
elif namespace:
|
||||
raise exception.InvalidHelmNamespace(chart=self.CHART,
|
||||
namespace=namespace)
|
||||
else:
|
||||
return overrides
|
||||
|
||||
def get_namespaces(self):
|
||||
return self.SUPPORTED_NAMESPACES
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ class KeystoneApiProxyHelm(openstack.OpenstackBaseHelm):
|
|||
SERVICE_NAME = constants.HELM_CHART_KEYSTONE_API_PROXY
|
||||
DCORCH_SERVICE_NAME = 'dcorch'
|
||||
|
||||
def get_meta_overrides(self, namespace):
|
||||
def get_meta_overrides(self, namespace, app_name=None, mode=None):
|
||||
|
||||
def _meta_overrides():
|
||||
if (self._distributed_cloud_role() ==
|
||||
|
|
Loading…
Reference in New Issue