Provide an API to control enabling/disabling application charts

Extend the helm_charts API to support an enable attribute. This
attribute is set on application upload and stored in the existing
system_overrides element of the helm_overrides table.

Changes include
- Add application metadata support for disabling charts on application
  upload.
- Add the system helm-chart-attribute-modify command to allow enabling
  and disabling charts from the command-line. This removes the current
  implementation of adding a faux label via the system host-label-assign
  command to enable and disable charts.
- Add a --long option to helm-override-list to enable easy viewing of
  what charts are enabled for a given application
- Enhance the ArmadaManifestOperator to make this a base class for
  application specific operator classes. Introduce classes for the
  stx-openstack and platform-integ-apps manifests with specific
  knowledge of the charts and chart groups within each class.
- Use stevedore to load the application specific manifest operators.
  This will allow future packaging of manifest operators with new
  application tarballs.
- Move the helm chart definition from the common/constants.py to
  helm/common.py. This limits helm/armada specific data leakage outside
  of the helm directory, which we may carve out of sysinv in the future.
- Clean up the code related to the faux labels: LABEL_IRONIC,
  LABEL_BARBICAN, and LABEL_TELEMETRY
- Rework the manifest update code in the plugins to include checks for
  if the chart for a given application has been disabled.

Change-Id: If284f622ceac48c4ffd74e7022fdd390971d0fd8
Closes-Bug: #1833746
Depends-On: I418f0fe4978946a44e512c3025817fb27216c078
Signed-off-by: Robert Church <robert.church@windriver.com>
This commit is contained in:
Robert Church 2019-07-21 17:41:24 -04:00
parent a7a1683d19
commit 3cd4032f55
46 changed files with 753 additions and 308 deletions

View File

@ -1,5 +1,6 @@
%global helm_folder /usr/lib/helm
%global armada_folder /usr/lib/armada
%global app_folder /usr/lib/application
%global toolkit_version 0.1.0
%global helmchart_version 0.1.0
@ -70,6 +71,8 @@ rm ./helm-toolkit-%{toolkit_version}.tgz
%install
# helm_folder is created by openstack-helm-infra
install -d -m 755 ${RPM_BUILD_ROOT}%{app_folder}
install -p -D -m 755 files/metadata.yaml ${RPM_BUILD_ROOT}%{app_folder}
install -d -m 755 ${RPM_BUILD_ROOT}%{helm_folder}
install -p -D -m 755 *.tgz ${RPM_BUILD_ROOT}%{helm_folder}
install -d -m 755 ${RPM_BUILD_ROOT}%{armada_folder}
@ -80,3 +83,4 @@ install -p -D -m 755 manifests/*.yaml ${RPM_BUILD_ROOT}%{armada_folder}
%defattr(-,root,root,-)
%{helm_folder}/*
%{armada_folder}/*
%{app_folder}/*

View File

@ -0,0 +1,7 @@
disabled_charts:
- aodh
- barbican
- ceilometer
- gnocchi
- ironic
- panko

View File

@ -59,7 +59,7 @@ class HelmManager(base.Manager):
This will return the end-user overrides for the specified chart.
"""
body = {'flag': flag, 'values': override_values}
body = {'flag': flag, 'values': override_values, 'attributes': {}}
return self._update(self._path(app) +
'?name=' + name +
'&namespace=' + namespace, body)
@ -74,3 +74,20 @@ class HelmManager(base.Manager):
return self._delete(self._path(app) +
'?name=' + name +
'&namespace=' + namespace)
def update_chart(self, app, name, namespace, attributes=None):
"""Update non-override attributes for a given chart.
:param app_name: name of application
:param name: name of the chart
:param namespace: namespace for the chart overrides
:param attributes: dict of chart attributes to be updated
This will return the updated attributes for the specified chart.
"""
if not attributes:
attributes = {}
body = {'flag': None, 'values': {}, 'attributes': attributes}
return self._update(self._path(app) +
'?name=' + name +
'&namespace=' + namespace, body)

View File

@ -39,11 +39,21 @@ def _find_overrides(cc, app, chart, namespace):
@utils.arg('app',
metavar='<app name>',
help="Name of the application")
@utils.arg('-l', '--long',
action='store_true',
help='List additional fields in output')
def do_helm_override_list(cc, args):
"""List system helm charts."""
app = app_utils._find_app(cc, args.app)
charts = cc.helm.list_charts(app.name)
utils.print_list(charts, ['name', 'namespaces'], ['chart name', 'overrides namespaces'], sortby=0)
keys = ['name', 'namespaces']
labels = ['chart name', 'overrides namespaces']
if args.long:
keys.append('enabled')
labels.append('chart enabled')
utils.print_list(charts, keys, labels, sortby=0)
@utils.arg('app',
@ -142,3 +152,37 @@ def do_helm_override_update(cc, args):
chart = cc.helm.update_overrides(args.app, args.chart, args.namespace,
flag, overrides)
_print_helm_chart(chart)
@utils.arg('app',
metavar='<app name>',
help="Name of the application")
@utils.arg('chart',
metavar='<chart name>',
help="Name of the chart")
@utils.arg('namespace',
metavar='<namespace>',
help="Namespace of the chart")
@utils.arg('--enabled',
metavar='<true/false>',
help="Chart enabled.")
def do_helm_chart_attribute_modify(cc, args):
"""Modify helm chart attributes.
This function is provided to modify system behaviorial attributes related to
a chart. This does not modify a chart nor does it modify chart overrides
which are managed through the helm-override-update command.
"""
# Make sure the chart is present
app = app_utils._find_app(cc, args.app)
chart = _find_overrides(cc, app, args.chart, args.namespace)
attributes = {}
if args.enabled is not None:
attributes.update({'enabled': args.enabled})
chart = cc.helm.update_chart(args.app, args.chart, args.namespace,
attributes)
_print_helm_chart(chart)

View File

@ -105,6 +105,11 @@ systemconfig.helm_plugins.stx_openstack =
026_nginx-ports-control = sysinv.helm.nginx_ports_control:NginxPortsControlHelm
027_version_check = sysinv.helm.openstack_version_check:StxOpenstackVersionCheckHelm
systemconfig.armada.manifest_ops =
generic = sysinv.helm.manifest_generic:GenericArmadaManifestOperator
stx-openstack = sysinv.helm.manifest_openstack:OpenstackArmadaManifestOperator
platform-integ-apps = sysinv.helm.manifest_platform:PlatformArmadaManifestOperator
sysinv.agent.lldp.drivers =
lldpd = sysinv.agent.lldp.drivers.lldpd.driver:SysinvLldpdAgentDriver
ovs = sysinv.agent.lldp.drivers.ovs.driver:SysinvOVSAgentDriver

View File

@ -6,6 +6,7 @@
import pecan
from pecan import rest
import six
import yaml
import wsme
@ -14,6 +15,7 @@ import wsmeext.pecan as wsme_pecan
from sysinv import objects
from sysinv.common import exception
from sysinv.helm import common
from sysinv.openstack.common import log
from sysinv.openstack.common.gettextutils import _
@ -34,8 +36,24 @@ class HelmChartsController(rest.RestController):
raise wsme.exc.ClientSideError(_("Unable to get the helm charts for "
"application %s: %s" % (app_name, str(e))))
charts = [{'name': chart, 'namespaces': namespaces[chart]}
for chart in namespaces]
charts = []
for chart in namespaces:
enabled = []
for ns in namespaces[chart]:
try:
app = objects.kube_app.get_by_name(
pecan.request.context, app_name)
db_chart = objects.helm_overrides.get_by_appid_name(
pecan.request.context, app.id, chart, ns)
except exception.KubeAppNotFound:
raise wsme.exc.ClientSideError(
_("Application %s not found." % app_name))
enabled.append(db_chart.system_overrides.get('enabled',
'true'))
charts.append({'name': chart, 'enabled': enabled,
'namespaces': namespaces[chart]})
return {'charts': charts}
@ -62,7 +80,7 @@ class HelmChartsController(rest.RestController):
user_overrides = None
system_apps = pecan.request.rpcapi.get_helm_applications(
pecan.request.context)
pecan.request.context)
if app_name in system_apps:
# Get any system overrides for system app.
try:
@ -92,8 +110,26 @@ class HelmChartsController(rest.RestController):
combined_overrides = pecan.request.rpcapi.merge_overrides(
pecan.request.context, file_overrides=file_overrides)
try:
attributes = {}
for k, v in six.iteritems(db_chart.system_overrides):
if k in common.HELM_CHART_ATTRS:
attributes.update({k: v})
if attributes:
attributes = yaml.safe_dump(attributes,
default_flow_style=False)
else:
attributes = None
except Exception as e:
raise wsme.exc.ClientSideError(
_("Unable to get the helm chart attributes for chart %s under "
"Namespace %s: %s" % (name, namespace, str(e))))
rpc_chart = {'name': name,
'namespace': namespace,
'attributes': attributes,
'system_overrides': system_overrides,
'user_overrides': user_overrides,
'combined_overrides': combined_overrides}
@ -106,9 +142,9 @@ class HelmChartsController(rest.RestController):
if not namespace:
raise wsme.exc.ClientSideError(_("Namespace must be specified."))
@wsme_pecan.wsexpose(wtypes.text, wtypes.text, wtypes.text,
@wsme_pecan.wsexpose(wtypes.text, wtypes.text, wtypes.text, wtypes.text,
wtypes.text, wtypes.text, wtypes.text)
def patch(self, app_name, name, namespace, flag, values):
def patch(self, app_name, name, namespace, attributes, flag, values):
""" Update user overrides.
:param app_name: name of application
@ -117,6 +153,7 @@ class HelmChartsController(rest.RestController):
:param flag: one of "reuse" or "reset", describes how to handle
previous user overrides
:param values: a dict of different types of user override values
:param attributes: a dict of non-overrides related chart attributes
"""
self.validate_name_and_namespace(name, namespace)
@ -154,21 +191,44 @@ class HelmChartsController(rest.RestController):
file_overrides.insert(0, user_overrides)
elif flag == 'reset':
user_overrides = None
else:
elif values:
raise wsme.exc.ClientSideError(_("Invalid flag: %s must be either "
"'reuse' or 'reset'.") % flag)
# Form the response
chart = {'name': name, 'namespace': namespace}
if file_overrides or set_overrides:
user_overrides = pecan.request.rpcapi.merge_overrides(
pecan.request.context, file_overrides=file_overrides,
set_overrides=set_overrides)
# update the response
chart.update({'user_overrides': user_overrides})
# save chart overrides back to DB
db_chart.user_overrides = user_overrides
db_chart.save()
chart = {'name': name, 'namespace': namespace,
'user_overrides': user_overrides}
if attributes:
for k, v in six.iteritems(attributes):
if k not in common.HELM_CHART_ATTRS:
raise wsme.exc.ClientSideError(
_("Invalid chart attribute: %s must be one of [%s]") %
(k, ','.join(common.HELM_CHART_ATTRS)))
if k == common.HELM_CHART_ATTR_ENABLED:
attributes[k] = attributes[k] in ['true', 'True']
# update the attribute changes
system_overrides = db_chart.system_overrides
system_overrides.update(attributes)
# update the response
chart.update({'attributes': attributes})
# save attributes back to DB
db_chart.system_overrides = system_overrides
db_chart.save()
return chart

View File

@ -1302,47 +1302,10 @@ SYSTEM_SECURITY_FEATURE_SPECTRE_MELTDOWN_OPTS = {
SYSTEM_SECURITY_FEATURE_SPECTRE_MELTDOWN_DEFAULT_OPTS = SYSTEM_SECURITY_FEATURE_SPECTRE_MELTDOWN_V1_OPTS
# Helm: Supported charts:
# These values match the names in the chart package's Chart.yaml
HELM_CHART_AODH = 'aodh'
HELM_CHART_BARBICAN = 'barbican'
HELM_CHART_CEILOMETER = 'ceilometer'
HELM_CHART_CINDER = 'cinder'
HELM_CHART_GARBD = 'garbd'
HELM_CHART_GLANCE = 'glance'
HELM_CHART_GNOCCHI = 'gnocchi'
HELM_CHART_HEAT = 'heat'
HELM_CHART_HORIZON = 'horizon'
HELM_CHART_INGRESS = 'ingress'
HELM_CHART_IRONIC = 'ironic'
HELM_CHART_KEYSTONE = 'keystone'
HELM_CHART_LIBVIRT = 'libvirt'
HELM_CHART_MAGNUM = 'magnum'
HELM_CHART_MARIADB = 'mariadb'
HELM_CHART_MEMCACHED = 'memcached'
HELM_CHART_NEUTRON = 'neutron'
HELM_CHART_NOVA = 'nova'
HELM_CHART_NOVA_API_PROXY = 'nova-api-proxy'
HELM_CHART_OPENVSWITCH = 'openvswitch'
HELM_CHART_PANKO = 'panko'
HELM_CHART_PLACEMENT = 'placement'
HELM_CHART_RABBITMQ = 'rabbitmq'
HELM_CHART_RBD_PROVISIONER = 'rbd-provisioner'
HELM_CHART_CEPH_POOLS_AUDIT = 'ceph-pools-audit'
HELM_CHART_HELM_TOOLKIT = 'helm-toolkit'
HELM_CHART_KEYSTONE_API_PROXY = 'keystone-api-proxy'
HELM_CHART_SWIFT = 'ceph-rgw'
HELM_CHART_NGINX_PORTS_CONTROL = "nginx-ports-control"
# Helm: Supported application (aka chart bundles)
HELM_APP_OPENSTACK = 'stx-openstack'
HELM_APP_PLATFORM = 'platform-integ-apps'
HELM_APPS_SUPPORTED = [
HELM_APP_OPENSTACK,
HELM_APP_PLATFORM,
]
# Apply mode for openstack app
OPENSTACK_RESTORE_DB = 'restore_db'
OPENSTACK_RESTORE_STORAGE = 'restore_storage'

View File

@ -1914,9 +1914,14 @@ def find_metadata_file(path, metadata_file):
app_name: <name>
app_version: <version>
patch_dependencies:
- <patch.1>
- <patch.2>
...
- <patch.1>
- <patch.2>
...
repo: <helm repo> - optional: defaults to HELM_REPO_FOR_APPS
disabled_charts: - optional: charts default to enabled
- <chart name>
- <chart name>
...
"""
app_name = ''
app_version = ''

View File

@ -18,6 +18,7 @@ import pwd
import re
import ruamel.yaml as yaml
import shutil
import six
import subprocess
import threading
import time
@ -39,7 +40,6 @@ from sysinv.common import utils as cutils
from sysinv.common.storage_backend_conf import K8RbdProvisioner
from sysinv.helm import common
from sysinv.helm import helm
from sysinv.helm import manifest
from sysinv.helm import utils as helm_utils
from sysinv.openstack.common.gettextutils import _
@ -770,28 +770,34 @@ class AppOperator(object):
raise exception.KubeAppUploadFailure(
name=app.name, version=app.version, reason="one or more charts failed validation.")
def _get_helm_repo_from_metadata(self, app):
"""Get helm repo from application metadata
def _get_chart_data_from_metadata(self, app):
"""Get chart related data from application metadata
This extracts the helm repo from the application metadata where the
chart should be loaded.
This also returns the list of charts that are disabled by default.
:param app: application
"""
repo = common.HELM_REPO_FOR_APPS
lfile = os.path.join(app.path, 'metadata.yaml')
disabled_charts = []
lfile = os.path.join(app.path, constants.APP_METADATA_FILE)
if os.path.exists(lfile) and os.path.getsize(lfile) > 0:
with open(lfile, 'r') as f:
try:
y = yaml.safe_load(f)
repo = y['helm_repo']
repo = y.get('helm_repo', common.HELM_REPO_FOR_APPS)
disabled_charts = y.get('disabled_charts', [])
except KeyError:
pass
LOG.info("Application %s (%s) will load charts to chart repo %s" % (
app.name, app.version, repo))
return repo
LOG.info("Application %s (%s) will disable charts %s by default" % (
app.name, app.version, disabled_charts))
return (repo, disabled_charts)
def _upload_helm_charts(self, app):
# Set env path for helm-upload execution
@ -801,7 +807,7 @@ class AppOperator(object):
for r, f in cutils.get_files_matching(app.charts_dir, '.tgz')]
orig_uid, orig_gid = get_app_install_root_path_ownership()
helm_repo = self._get_helm_repo_from_metadata(app)
(helm_repo, disabled_charts) = self._get_chart_data_from_metadata(app)
try:
# Temporarily change /scratch group ownership to sys_protected
os.chown(constants.APP_INSTALL_ROOT_PATH, orig_uid,
@ -821,6 +827,37 @@ class AppOperator(object):
finally:
os.chown(constants.APP_INSTALL_ROOT_PATH, orig_uid, orig_gid)
# For system applications with plugin support, establish user override
# entries and disable charts based on application metadata.
db_app = self._dbapi.kube_app_get(app.name)
app_ns = self._helm.get_helm_application_namespaces(db_app.name)
for chart, namespaces in six.iteritems(app_ns):
for namespace in namespaces:
try:
db_chart = self._dbapi.helm_override_get(
db_app.id, chart, namespace)
except exception.HelmOverrideNotFound:
# Create it
try:
db_chart = self._dbapi.helm_override_create(
{'app_id': db_app.id, 'name': chart,
'namespace': namespace})
except Exception as e:
LOG.exception(e)
# Since we are uploading a fresh application. Ensure that
# charts are disabled based on metadata
system_overrides = db_chart.system_overrides
system_overrides.update({common.HELM_CHART_ATTR_ENABLED:
chart not in disabled_charts})
try:
self._dbapi.helm_override_update(
db_app.id, chart, namespace, {'system_overrides':
system_overrides})
except exception.HelmOverrideNotFound:
LOG.exception(e)
def _validate_labels(self, labels):
expr = re.compile(r'[a-z0-9]([-a-z0-9]*[a-z0-9])')
for label in labels:
@ -1185,7 +1222,7 @@ class AppOperator(object):
return None
# Get the armada manifest overrides files
manifest_op = manifest.ArmadaManifestOperator()
manifest_op = self._helm.get_armada_manifest_operator(app_name)
armada_overrides = manifest_op.load_summary(overrides_dir)
return (available_helm_overrides, armada_overrides)

View File

@ -4,7 +4,6 @@
# SPDX-License-Identifier: Apache-2.0
#
from sysinv.common import constants
from sysinv.common import exception
from sysinv.openstack.common import log as logging
from sysinv.helm import common
@ -16,9 +15,9 @@ LOG = logging.getLogger(__name__)
class AodhHelm(openstack.OpenstackBaseHelm):
"""Class to encapsulate helm operations for the aodh chart"""
CHART = constants.HELM_CHART_AODH
CHART = common.HELM_CHART_AODH
SERVICE_NAME = 'aodh'
SERVICE_NAME = common.HELM_CHART_AODH
AUTH_USERS = ['aodh']
def get_overrides(self, namespace=None):

View File

@ -4,7 +4,6 @@
# SPDX-License-Identifier: Apache-2.0
#
from sysinv.common import constants
from sysinv.common import exception
from sysinv.helm import common
from sysinv.helm import openstack
@ -13,14 +12,9 @@ from sysinv.helm import openstack
class BarbicanHelm(openstack.OpenstackBaseHelm):
"""Class to encapsulate helm operations for the barbican chart"""
CHART = constants.HELM_CHART_BARBICAN
CHART = common.HELM_CHART_BARBICAN
AUTH_USERS = ['barbican']
SERVICE_NAME = constants.HELM_CHART_BARBICAN
def execute_manifest_updates(self, operator, app_name=None):
if not self._is_labeled(common.LABEL_BARBICAN, 'enabled'):
operator.manifest_chart_groups_delete(
'armada-manifest', 'openstack-barbican')
SERVICE_NAME = common.HELM_CHART_BARBICAN
def get_overrides(self, namespace=None):
overrides = {

View File

@ -31,7 +31,7 @@ class BaseHelm(object):
SUPPORTED_NAMESPACES = []
SUPPORTED_APP_NAMESPACES = {}
SYSTEM_CONTROLLER_SERVICES = [
constants.HELM_CHART_KEYSTONE_API_PROXY,
common.HELM_CHART_KEYSTONE_API_PROXY,
]
def __init__(self, operator):
@ -200,19 +200,6 @@ class BaseHelm(object):
cpus.append(c)
return cpus
def _is_labeled(self, k, v):
"""
Check whether the label key value pair are set
"""
if self.dbapi is None:
return False
label_list = self.dbapi.label_get_all()
for label in label_list:
if label.label_key == k:
if label.label_value == v:
return True
return False
def get_namespaces(self):
"""
Return list of namespaces supported by this chart
@ -250,7 +237,7 @@ class BaseHelm(object):
"""
return True
def execute_manifest_updates(self, operator, app_name=None):
def execute_manifest_updates(self, operator):
"""
Update the elements of the armada manifest.
@ -262,7 +249,26 @@ class BaseHelm(object):
armada/Manifest/v1, armada/ChartGroup/v1, armada/Chart/v1.
:param operator: an instance of the ArmadaManifestOperator
:parameter app_name: application for which the specific actions are
taken
"""
pass
def _is_enabled(self, app_name, chart_name, namespace):
"""
Check if the chart is enable at an application level
:param app_name: Application name
:param chart_name: Chart supplied with the application
:param namespace: Namespace where the chart will be executed
Returns true by default if an exception occurs as most charts are
enabled.
"""
try:
db_app = self.dbapi.kube_app_get(app_name)
db_chart = self.dbapi.helm_override_get(db_app.id, chart_name, namespace)
except exception.KubeAppNotFound:
return True
except exception.HelmOverrideNotFound:
return True
return db_chart.system_overrides.get(common.HELM_CHART_ATTR_ENABLED, False)

View File

@ -17,16 +17,11 @@ LOG = logging.getLogger(__name__)
class CeilometerHelm(openstack.OpenstackBaseHelm):
"""Class to encapsulate helm operations for the ceilometer chart"""
CHART = constants.HELM_CHART_CEILOMETER
CHART = common.HELM_CHART_CEILOMETER
SERVICE_NAME = 'ceilometer'
SERVICE_NAME = common.HELM_CHART_CEILOMETER
AUTH_USERS = ['ceilometer']
def execute_manifest_updates(self, operator, app_name=None):
if not self._is_labeled(common.LABEL_TELEMETRY, 'enabled'):
operator.manifest_chart_groups_delete(
'armada-manifest', 'openstack-telemetry')
def get_overrides(self, namespace=None):
overrides = {
common.HELM_NS_OPENSTACK: {

View File

@ -17,7 +17,7 @@ LOG = logging.getLogger(__name__)
class CephPoolsAuditHelm(base.BaseHelm):
"""Class to encapsulate helm operations for the ceph-pools-audit chart"""
CHART = constants.HELM_CHART_CEPH_POOLS_AUDIT
CHART = common.HELM_CHART_CEPH_POOLS_AUDIT
SUPPORTED_NAMESPACES = base.BaseHelm.SUPPORTED_NAMESPACES + \
[common.HELM_NS_STORAGE_PROVISIONER]
SUPPORTED_APP_NAMESPACES = {
@ -27,6 +27,15 @@ class CephPoolsAuditHelm(base.BaseHelm):
SERVICE_NAME = 'ceph-pools'
def execute_manifest_updates(self, operator):
# On application load this chart is enabled. Only disable if specified
# by the user
if not self._is_enabled(operator.APP, self.CHART,
common.HELM_NS_STORAGE_PROVISIONER):
operator.chart_group_chart_delete(
operator.CHART_GROUPS_LUT[self.CHART],
operator.CHARTS_LUT[self.CHART])
def get_namespaces(self):
return self.SUPPORTED_NAMESPACES

View File

@ -18,9 +18,9 @@ LOG = logging.getLogger(__name__)
class CinderHelm(openstack.OpenstackBaseHelm):
"""Class to encapsulate helm operations for the cinder chart"""
CHART = constants.HELM_CHART_CINDER
CHART = common.HELM_CHART_CINDER
SERVICE_NAME = 'cinder'
SERVICE_NAME = common.HELM_CHART_CINDER
SERVICE_TYPE = 'volume'
AUTH_USERS = ['cinder']

View File

@ -21,6 +21,42 @@ HELM_OVERRIDES_PATH = os.path.join(tsconfig.PLATFORM_PATH, 'helm', tsconfig.SW_V
HELM_REPO_FOR_APPS = 'starlingx'
HELM_REPO_FOR_PLATFORM = 'stx-platform'
# Supported chart attributes:
HELM_CHART_ATTR_ENABLED = 'enabled'
HELM_CHART_ATTRS = [HELM_CHART_ATTR_ENABLED]
# Helm: Supported charts:
# These values match the names in the chart package's Chart.yaml
HELM_CHART_AODH = 'aodh'
HELM_CHART_BARBICAN = 'barbican'
HELM_CHART_CEILOMETER = 'ceilometer'
HELM_CHART_CINDER = 'cinder'
HELM_CHART_GARBD = 'garbd'
HELM_CHART_GLANCE = 'glance'
HELM_CHART_GNOCCHI = 'gnocchi'
HELM_CHART_HEAT = 'heat'
HELM_CHART_HORIZON = 'horizon'
HELM_CHART_INGRESS = 'ingress'
HELM_CHART_IRONIC = 'ironic'
HELM_CHART_KEYSTONE = 'keystone'
HELM_CHART_LIBVIRT = 'libvirt'
HELM_CHART_MAGNUM = 'magnum'
HELM_CHART_MARIADB = 'mariadb'
HELM_CHART_MEMCACHED = 'memcached'
HELM_CHART_NEUTRON = 'neutron'
HELM_CHART_NOVA = 'nova'
HELM_CHART_NOVA_API_PROXY = 'nova-api-proxy'
HELM_CHART_OPENVSWITCH = 'openvswitch'
HELM_CHART_PANKO = 'panko'
HELM_CHART_PLACEMENT = 'placement'
HELM_CHART_RABBITMQ = 'rabbitmq'
HELM_CHART_RBD_PROVISIONER = 'rbd-provisioner'
HELM_CHART_CEPH_POOLS_AUDIT = 'ceph-pools-audit'
HELM_CHART_HELM_TOOLKIT = 'helm-toolkit'
HELM_CHART_KEYSTONE_API_PROXY = 'keystone-api-proxy'
HELM_CHART_SWIFT = 'ceph-rgw'
HELM_CHART_NGINX_PORTS_CONTROL = "nginx-ports-control"
# Namespaces
HELM_NS_CEPH = 'ceph'
HELM_NS_DEFAULT = 'default'
@ -50,9 +86,6 @@ LABEL_CONTROLLER = 'openstack-control-plane'
LABEL_COMPUTE_LABEL = 'openstack-compute-node'
LABEL_OPENVSWITCH = 'openvswitch'
LABEL_REMOTE_STORAGE = 'remote-storage'
LABEL_IRONIC = 'openstack-ironic'
LABEL_BARBICAN = 'openstack-barbican'
LABEL_TELEMETRY = 'openstack-telemetry'
# Label values
LABEL_VALUE_ENABLED = 'enabled'

View File

@ -20,9 +20,9 @@ class GarbdHelm(base.BaseHelm):
# The service name is used to build the standard docker image location.
# It is intentionally "mariadb" and not "garbd" as they both use the
# same docker image.
SERVICE_NAME = 'mariadb'
SERVICE_NAME = common.HELM_CHART_MARIADB
CHART = constants.HELM_CHART_GARBD
CHART = common.HELM_CHART_GARBD
SUPPORTED_NAMESPACES = \
base.BaseHelm.SUPPORTED_NAMESPACES + [common.HELM_NS_OPENSTACK]
SUPPORTED_APP_NAMESPACES = {
@ -30,19 +30,29 @@ class GarbdHelm(base.BaseHelm):
base.BaseHelm.SUPPORTED_NAMESPACES + [common.HELM_NS_OPENSTACK]
}
def execute_manifest_updates(self, operator, app_name=None):
if app_name == constants.HELM_APP_OPENSTACK:
if (self._num_controllers() < 2 or
utils.is_aio_duplex_system(self.dbapi) or
(self._distributed_cloud_role() ==
constants.DISTRIBUTED_CLOUD_ROLE_SYSTEMCONTROLLER)):
# If there are fewer than 2 controllers or we're on AIO-DX
# or we are on distributed cloud system controller
# we'll use a single mariadb server and so we don't want to
# run garbd. This will remove "openstack-garbd" from the
# charts in the openstack-mariadb chartgroup.
operator.chart_group_chart_delete('openstack-mariadb',
'openstack-garbd')
def _is_enabled(self, app_name, chart_name, namespace):
# First, see if this chart is enabled by the user then adjust based on
# system conditions
enabled = super(GarbdHelm, self)._is_enabled(
app_name, chart_name, namespace)
# If there are fewer than 2 controllers or we're on AIO-DX or we are on
# distributed cloud system controller, we'll use a single mariadb server
# and so we don't want to run garbd.
if enabled and (self._num_controllers() < 2 or
utils.is_aio_duplex_system(self.dbapi) or
(self._distributed_cloud_role() ==
constants.DISTRIBUTED_CLOUD_ROLE_SYSTEMCONTROLLER)):
enabled = False
return enabled
def execute_manifest_updates(self, operator):
# On application load this chart is enabled in the mariadb chart group
if not self._is_enabled(operator.APP,
self.CHART, common.HELM_NS_OPENSTACK):
operator.chart_group_chart_delete(
operator.CHART_GROUPS_LUT[self.CHART],
operator.CHARTS_LUT[self.CHART])
def get_overrides(self, namespace=None):
overrides = {

View File

@ -22,9 +22,9 @@ RBD_STORE_USER = 'images'
class GlanceHelm(openstack.OpenstackBaseHelm):
"""Class to encapsulate helm operations for the glance chart"""
CHART = constants.HELM_CHART_GLANCE
CHART = common.HELM_CHART_GLANCE
SERVICE_NAME = 'glance'
SERVICE_NAME = common.HELM_CHART_GLANCE
SERVICE_TYPE = 'image'
AUTH_USERS = ['glance']
@ -65,7 +65,7 @@ class GlanceHelm(openstack.OpenstackBaseHelm):
'image': {
'host_fqdn_override':
self._get_endpoints_host_fqdn_overrides(
constants.HELM_CHART_GLANCE),
common.HELM_CHART_GLANCE),
'scheme': self._get_endpoints_scheme_public_overrides(),
'port': self._get_endpoints_port_api_public_overrides(),
},

View File

@ -4,7 +4,6 @@
# SPDX-License-Identifier: Apache-2.0
#
from sysinv.common import constants
from sysinv.common import exception
from sysinv.openstack.common import log as logging
from sysinv.helm import common
@ -16,9 +15,9 @@ LOG = logging.getLogger(__name__)
class GnocchiHelm(openstack.OpenstackBaseHelm):
"""Class to encapsulate helm operations for the gnocchi chart"""
CHART = constants.HELM_CHART_GNOCCHI
CHART = common.HELM_CHART_GNOCCHI
SERVICE_NAME = 'gnocchi'
SERVICE_NAME = common.HELM_CHART_GNOCCHI
AUTH_USERS = ['gnocchi']
def get_overrides(self, namespace=None):

View File

@ -4,7 +4,6 @@
# SPDX-License-Identifier: Apache-2.0
#
from sysinv.common import constants
from sysinv.common import exception
from sysinv.openstack.common import log as logging
from sysinv.helm import common
@ -16,9 +15,9 @@ LOG = logging.getLogger(__name__)
class HeatHelm(openstack.OpenstackBaseHelm):
"""Class to encapsulate helm operations for the heat chart"""
CHART = constants.HELM_CHART_HEAT
CHART = common.HELM_CHART_HEAT
SERVICE_NAME = constants.HELM_CHART_HEAT
SERVICE_NAME = common.HELM_CHART_HEAT
AUTH_USERS = ['heat', 'heat_trustee', 'heat_stack_user']
def get_overrides(self, namespace=None):

View File

@ -17,12 +17,10 @@ import yaml
from six import iteritems
from stevedore import extension
from sysinv.common import constants
from sysinv.common import exception
from sysinv.common import utils
from sysinv.openstack.common import log as logging
from sysinv.helm import common
from sysinv.helm import manifest
LOG = logging.getLogger(__name__)
@ -66,6 +64,32 @@ class HelmOperator(object):
# dict containing sequence of helm charts per app
self.helm_system_applications = self.get_helm_applications()
# dict containing Armada manifest operators per app
self.armada_manifest_operators = self.load_armada_manifest_operators()
def load_armada_manifest_operators(self):
"""Build a dictionary of armada manifest operators"""
operators_dict = {}
armada_manifest_operators = extension.ExtensionManager(
namespace='systemconfig.armada.manifest_ops',
invoke_on_load=True, invoke_args=())
for op in armada_manifest_operators:
operators_dict[op.name] = op.obj
return operators_dict
def get_armada_manifest_operator(self, app_name):
"""Return a manifest operator based on app name"""
if app_name in self.armada_manifest_operators:
manifest_op = self.armada_manifest_operators[app_name]
else:
manifest_op = self.armada_manifest_operators['generic']
return manifest_op
def get_helm_applications(self):
"""Build a dictionary of supported helm applications"""
@ -482,9 +506,9 @@ class HelmOperator(object):
LOG.exception("Application %s not found." % app_name)
raise
# Get a manifest operator to provide a single point of manipulation for
# the chart, chart group and manifest schemas
manifest_op = manifest.ArmadaManifestOperator()
# Get a manifest operator to provide a single point of
# manipulation for the chart, chart group and manifest schemas
manifest_op = self.get_armada_manifest_operator(app_name)
# Load the manifest into the operator
armada_manifest = utils.generate_armada_manifest_filename_abs(
@ -544,11 +568,10 @@ class HelmOperator(object):
# Update manifest docs based on the plugin directives
if chart_name in self.chart_operators:
self.chart_operators[chart_name].execute_manifest_updates(
manifest_op, app_name)
manifest_op)
# Update the manifest based on platform conditions
manifest.platform_mode_manifest_updates(
self.dbapi, manifest_op, app_name, mode)
manifest_op.platform_mode_manifest_updates(self.dbapi, mode)
else:
# Generic applications
@ -686,7 +709,7 @@ class HelmOperatorData(HelmOperator):
@helm_context
def get_keystone_auth_data(self):
keystone_operator = self.chart_operators[constants.HELM_CHART_KEYSTONE]
keystone_operator = self.chart_operators[common.HELM_CHART_KEYSTONE]
auth_data = {
'admin_user_name':
keystone_operator.get_admin_user_name(),
@ -703,7 +726,7 @@ class HelmOperatorData(HelmOperator):
@helm_context
def get_nova_endpoint_data(self):
nova_operator = self.chart_operators[constants.HELM_CHART_NOVA]
nova_operator = self.chart_operators[common.HELM_CHART_NOVA]
endpoint_data = {
'endpoint_override':
'http://nova-api.openstack.svc.cluster.local:8774',
@ -714,7 +737,7 @@ class HelmOperatorData(HelmOperator):
@helm_context
def get_nova_oslo_messaging_data(self):
nova_operator = self.chart_operators[constants.HELM_CHART_NOVA]
nova_operator = self.chart_operators[common.HELM_CHART_NOVA]
endpoints_overrides = nova_operator._get_endpoints_overrides()
auth_data = {
'host':
@ -734,7 +757,7 @@ class HelmOperatorData(HelmOperator):
@helm_context
def get_cinder_endpoint_data(self):
cinder_operator = self.chart_operators[constants.HELM_CHART_CINDER]
cinder_operator = self.chart_operators[common.HELM_CHART_CINDER]
endpoint_data = {
'region_name':
cinder_operator.get_region_name(),
@ -747,7 +770,7 @@ class HelmOperatorData(HelmOperator):
@helm_context
def get_glance_endpoint_data(self):
glance_operator = self.chart_operators[constants.HELM_CHART_GLANCE]
glance_operator = self.chart_operators[common.HELM_CHART_GLANCE]
endpoint_data = {
'region_name':
glance_operator.get_region_name(),
@ -760,7 +783,7 @@ class HelmOperatorData(HelmOperator):
@helm_context
def get_neutron_endpoint_data(self):
neutron_operator = self.chart_operators[constants.HELM_CHART_NEUTRON]
neutron_operator = self.chart_operators[common.HELM_CHART_NEUTRON]
endpoint_data = {
'region_name':
neutron_operator.get_region_name(),
@ -769,7 +792,7 @@ class HelmOperatorData(HelmOperator):
@helm_context
def get_heat_endpoint_data(self):
heat_operator = self.chart_operators[constants.HELM_CHART_HEAT]
heat_operator = self.chart_operators[common.HELM_CHART_HEAT]
endpoint_data = {
'region_name':
heat_operator.get_region_name(),
@ -779,7 +802,7 @@ class HelmOperatorData(HelmOperator):
@helm_context
def get_ceilometer_endpoint_data(self):
ceilometer_operator = \
self.chart_operators[constants.HELM_CHART_CEILOMETER]
self.chart_operators[common.HELM_CHART_CEILOMETER]
endpoint_data = {
'region_name':
ceilometer_operator.get_region_name(),

View File

@ -4,7 +4,6 @@
# SPDX-License-Identifier: Apache-2.0
#
from sysinv.common import constants
from sysinv.common import exception
from sysinv.openstack.common import log as logging
from sysinv.helm import common
@ -16,7 +15,7 @@ LOG = logging.getLogger(__name__)
class HelmToolkitHelm(base.BaseHelm):
"""Class to encapsulate helm operations for the helm toolkit"""
CHART = constants.HELM_CHART_HELM_TOOLKIT
CHART = common.HELM_CHART_HELM_TOOLKIT
SUPPORTED_NAMESPACES = [
common.HELM_NS_HELM_TOOLKIT,
]

View File

@ -16,9 +16,9 @@ LOG = logging.getLogger(__name__)
class HorizonHelm(openstack.OpenstackBaseHelm):
"""Class to encapsulate helm operations for the horizon chart"""
CHART = constants.HELM_CHART_HORIZON
CHART = common.HELM_CHART_HORIZON
SERVICE_NAME = 'horizon'
SERVICE_NAME = common.HELM_CHART_HORIZON
def get_overrides(self, namespace=None):
overrides = {
@ -52,7 +52,7 @@ class HorizonHelm(openstack.OpenstackBaseHelm):
'dashboard': {
'host_fqdn_override':
self._get_endpoints_host_fqdn_overrides(
constants.HELM_CHART_HORIZON),
common.HELM_CHART_HORIZON),
'port': self._get_endpoints_port_api_public_overrides(),
'scheme': self._get_endpoints_scheme_public_overrides(),
},

View File

@ -16,7 +16,7 @@ LOG = logging.getLogger(__name__)
class IngressHelm(base.BaseHelm):
"""Class to encapsulate helm operations for the ingress chart"""
CHART = constants.HELM_CHART_INGRESS
CHART = common.HELM_CHART_INGRESS
SUPPORTED_NAMESPACES = base.BaseHelm.SUPPORTED_NAMESPACES + [
common.HELM_NS_KUBE_SYSTEM,

View File

@ -14,25 +14,33 @@ from sysinv.helm import openstack
class IronicHelm(openstack.OpenstackBaseHelm):
"""Class to encapsulate helm operations for the ironic chart"""
CHART = constants.HELM_CHART_IRONIC
CHART = common.HELM_CHART_IRONIC
SERVICE_NAME = 'ironic'
SERVICE_NAME = common.HELM_CHART_IRONIC
SERVICE_USERS = ['glance']
AUTH_USERS = ['ironic']
def execute_manifest_updates(self, operator, app_name=None):
if (self._num_controllers() >= 2 and
self._is_labeled(common.LABEL_IRONIC, 'enabled')):
# If there are fewer than 2 controllers or openstack-ironic
# label was not set, ironic chart won't be added to
# openstack-compute-kit chartgroup
operator.chart_group_chart_insert('openstack-compute-kit',
'openstack-ironic')
def _is_enabled(self, app_name, chart_name, namespace):
# First, see if this chart is enabled by the user then adjust based on
# system conditions
enabled = super(IronicHelm, self)._is_enabled(app_name,
chart_name, namespace)
if enabled and self._num_controllers() < 2:
enabled = False
return enabled
def execute_manifest_updates(self, operator):
# On application load, this chart is disabled in the metadata. Insert as
# needed.
if self._is_enabled(operator.APP,
self.CHART, common.HELM_NS_OPENSTACK):
operator.chart_group_chart_insert(
operator.CHART_GROUPS_LUT[self.CHART],
operator.CHARTS_LUT[self.CHART])
def get_overrides(self, namespace=None):
overrides = {
common.HELM_NS_OPENSTACK: {
'manifests': self._get_ironic_manifests(),
'pod': {
'replicas': {
'api': self._num_controllers(),
@ -52,35 +60,6 @@ class IronicHelm(openstack.OpenstackBaseHelm):
else:
return overrides
def _ironic_manifests(self, is_labeled):
manifests = {
'configmap_bin': is_labeled,
'configmap_etc': is_labeled,
'deployment_api': is_labeled,
'ingress_api': is_labeled,
'job_bootstrap': is_labeled,
'job_db_init': is_labeled,
'job_db_sync': is_labeled,
'job_image_repo_sync': is_labeled,
'job_ks_endpoints': is_labeled,
'job_ks_service': is_labeled,
'job_ks_user': is_labeled,
'job_manage_cleaning_network': is_labeled,
'job_rabbit_init': is_labeled,
'pdb_api': is_labeled,
'secret_db': is_labeled,
'secret_keystone': is_labeled,
'secret_rabbitmq': is_labeled,
'service_api': is_labeled,
'service_ingress_api': is_labeled,
'statefulset_conductor': is_labeled
}
return manifests
def _get_ironic_manifests(self):
ironic_label = self._is_labeled(common.LABEL_IRONIC, 'enabled')
return self._ironic_manifests(ironic_label)
def _get_endpoints_overrides(self):
overrides = {
'identity': {

View File

@ -22,9 +22,9 @@ OPENSTACK_PASSWORD_RULES_FILE = '/etc/keystone/password-rules.conf'
class KeystoneHelm(openstack.OpenstackBaseHelm):
"""Class to encapsulate helm operations for the keystone chart"""
CHART = constants.HELM_CHART_KEYSTONE
CHART = common.HELM_CHART_KEYSTONE
SERVICE_NAME = constants.HELM_CHART_KEYSTONE
SERVICE_NAME = common.HELM_CHART_KEYSTONE
SERVICE_PATH = '/v3'
DEFAULT_DOMAIN_NAME = 'default'

View File

@ -16,16 +16,29 @@ LOG = logging.getLogger(__name__)
class KeystoneApiProxyHelm(openstack.OpenstackBaseHelm):
"""Class to encapsulate helm operations for the keystone api proxy chart"""
CHART = constants.HELM_CHART_KEYSTONE_API_PROXY
CHART = common.HELM_CHART_KEYSTONE_API_PROXY
SERVICE_NAME = constants.HELM_CHART_KEYSTONE_API_PROXY
SERVICE_NAME = common.HELM_CHART_KEYSTONE_API_PROXY
DCORCH_SERVICE_NAME = 'dcorch'
def execute_manifest_updates(self, operator, app_name=None):
if (self._distributed_cloud_role() ==
constants.DISTRIBUTED_CLOUD_ROLE_SYSTEMCONTROLLER):
def _is_enabled(self, app_name, chart_name, namespace):
# First, see if this chart is enabled by the user then adjust based on
# system conditions
enabled = super(KeystoneApiProxyHelm, self)._is_enabled(
app_name, chart_name, namespace)
if enabled and (self._distributed_cloud_role() !=
constants.DISTRIBUTED_CLOUD_ROLE_SYSTEMCONTROLLER):
enabled = False
return enabled
def execute_manifest_updates(self, operator):
# This chart group is not included by default in the manifest. Insert as
# needed.
if self._is_enabled(operator.APP,
self.CHART, common.HELM_NS_OPENSTACK):
operator.manifest_chart_groups_insert(
'armada-manifest', 'openstack-keystone-api-proxy')
operator.ARMADA_MANIFEST,
operator.CHART_GROUPS_LUT[self.CHART])
def get_overrides(self, namespace=None):
overrides = {
@ -71,7 +84,7 @@ class KeystoneApiProxyHelm(openstack.OpenstackBaseHelm):
'keystone_api_proxy': {
'host_fqdn_override':
self._get_endpoints_host_fqdn_overrides(
constants.HELM_CHART_KEYSTONE_API_PROXY),
common.HELM_CHART_KEYSTONE_API_PROXY),
'port': self._get_endpoints_port_api_public_overrides(),
'scheme': self._get_endpoints_scheme_public_overrides(),
}

View File

@ -4,7 +4,6 @@
# SPDX-License-Identifier: Apache-2.0
#
from sysinv.common import constants
from sysinv.common import exception
from sysinv.openstack.common import log as logging
from sysinv.helm import common
@ -16,9 +15,9 @@ LOG = logging.getLogger(__name__)
class LibvirtHelm(openstack.OpenstackBaseHelm):
"""Class to encapsulate helm operations for the libvirt chart"""
CHART = constants.HELM_CHART_LIBVIRT
CHART = common.HELM_CHART_LIBVIRT
SERVICE_NAME = 'libvirt'
SERVICE_NAME = common.HELM_CHART_LIBVIRT
def get_overrides(self, namespace=None):
overrides = {

View File

@ -4,7 +4,6 @@
# SPDX-License-Identifier: Apache-2.0
#
from sysinv.common import constants
from sysinv.common import exception
from sysinv.helm import common
@ -14,9 +13,9 @@ from sysinv.helm import openstack
class MagnumHelm(openstack.OpenstackBaseHelm):
"""Class to encapsulate helm operations for the magnum chart"""
CHART = constants.HELM_CHART_MAGNUM
CHART = common.HELM_CHART_MAGNUM
SERVICE_NAME = constants.HELM_CHART_MAGNUM
SERVICE_NAME = common.HELM_CHART_MAGNUM
def get_overrides(self, namespace=None):
overrides = {

View File

@ -9,15 +9,15 @@
""" System inventory Armada manifest operator."""
import abc
import os
import json
import ruamel.yaml as yaml
import six
import tempfile
from glob import glob
from six import iteritems
from sysinv.common import constants
from sysinv.common import exception
from sysinv.openstack.common import log as logging
LOG = logging.getLogger(__name__)
@ -45,6 +45,7 @@ FILE_SUFFIX = '-meta.yaml'
SUMMARY_FILE = 'armada-overrides.yaml'
@six.add_metaclass(abc.ABCMeta)
class ArmadaManifestOperator(object):
def __init__(self, manifest_fqpn=None):
@ -386,6 +387,8 @@ class ArmadaManifestOperator(object):
self.docs[KEY_DATA_CHART_GROUPS][manifest][KEY_DATA][KEY_DATA_CHART_GROUPS] = chart_group_list
self.updated[KEY_DATA_CHART_GROUPS].update([manifest])
else:
LOG.error("Cannot set the manifest chart_groups to an empty list")
@ -470,6 +473,8 @@ class ArmadaManifestOperator(object):
self.docs[KEY_DATA_CHART_GROUP][chart_group][KEY_DATA][KEY_DATA_CHART_GROUP] = chart_list
self.updated[KEY_DATA_CHART_GROUP].update([chart_group])
else:
LOG.error("Cannot set the chart_group charts to an empty list")
@ -497,68 +502,11 @@ class ArmadaManifestOperator(object):
# Not implemented... yet.
pass
@abc.abstractmethod
def platform_mode_manifest_updates(self, dbapi, mode):
""" Update the application manifest based on the platform
def platform_mode_manifest_updates(dbapi, manifest_op, app_name, mode):
""" Update the application manifest based on the platform
This is used for
:param dbapi: DB api object
:param manifest_op: ArmadaManifestOperator for updating the application
manifest
:param app_name: application name
:param mode: mode to control how to apply the application manifest
"""
if not app_name:
LOG.info("App is None. No platform mode based manifest updates taken.")
elif app_name not in constants.HELM_APP_APPLY_MODES.keys():
LOG.info("App %s is not supported. No platform mode based manifest "
"updates taken." % app_name)
elif app_name == constants.HELM_APP_OPENSTACK:
if mode == constants.OPENSTACK_RESTORE_DB:
# During application restore, first bring up
# MariaDB service.
manifest_op.manifest_chart_groups_set(
'armada-manifest',
['kube-system-ingress',
'openstack-ingress',
'openstack-mariadb'])
elif mode == constants.OPENSTACK_RESTORE_STORAGE:
# After MariaDB data is restored, restore Keystone,
# Glance and Cinder.
manifest_op.manifest_chart_groups_set(
'armada-manifest',
['kube-system-ingress',
'openstack-ingress',
'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.
try:
system = dbapi.isystem_get_one()
except exception.NotFound:
LOG.exception("System %s not found.")
raise
if (system.distributed_cloud_role ==
constants.DISTRIBUTED_CLOUD_ROLE_SYSTEMCONTROLLER):
# remove the chart_groups not needed in this configuration
manifest_op.manifest_chart_groups_delete(
'armada-manifest', 'openstack-ceph-rgw')
manifest_op.manifest_chart_groups_delete(
'armada-manifest', 'openstack-compute-kit')
manifest_op.manifest_chart_groups_delete(
'armada-manifest', 'openstack-heat')
manifest_op.manifest_chart_groups_delete(
'armada-manifest', 'openstack-telemetry')
:param dbapi: DB api object
:param mode: mode to control how to apply the application manifest
"""
pass

View File

@ -0,0 +1,32 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
#
# Copyright (c) 2019 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
# All Rights Reserved.
#
""" System inventory Armada manifest operator."""
from sysinv.helm import manifest_base as base
from sysinv.openstack.common import log as logging
LOG = logging.getLogger(__name__)
class GenericArmadaManifestOperator(base.ArmadaManifestOperator):
APP = None
ARMADA_MANIFEST = None
CHART_GROUPS_LUT = {}
CHARTS_LUT = {}
def platform_mode_manifest_updates(self, dbapi, mode):
""" Update the application manifest based on the platform
:param dbapi: DB api object
:param mode: mode to control how to apply the application manifest
"""
pass

View File

@ -0,0 +1,178 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
#
# Copyright (c) 2019 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
# All Rights Reserved.
#
""" System inventory Armada manifest operator."""
from sysinv.common import constants
from sysinv.common import exception
from sysinv.helm import manifest_base as base
from sysinv.helm.aodh import AodhHelm
from sysinv.helm.barbican import BarbicanHelm
from sysinv.helm.ceilometer import CeilometerHelm
from sysinv.helm.cinder import CinderHelm
from sysinv.helm.garbd import GarbdHelm
from sysinv.helm.glance import GlanceHelm
from sysinv.helm.gnocchi import GnocchiHelm
from sysinv.helm.heat import HeatHelm
from sysinv.helm.horizon import HorizonHelm
from sysinv.helm.ingress import IngressHelm
from sysinv.helm.ironic import IronicHelm
from sysinv.helm.keystone import KeystoneHelm
from sysinv.helm.keystone_api_proxy import KeystoneApiProxyHelm
from sysinv.helm.libvirt import LibvirtHelm
from sysinv.helm.magnum import MagnumHelm
from sysinv.helm.mariadb import MariadbHelm
from sysinv.helm.memcached import MemcachedHelm
from sysinv.helm.neutron import NeutronHelm
from sysinv.helm.nginx_ports_control import NginxPortsControlHelm
from sysinv.helm.nova import NovaHelm
from sysinv.helm.nova_api_proxy import NovaApiProxyHelm
from sysinv.helm.openvswitch import OpenvswitchHelm
from sysinv.helm.panko import PankoHelm
from sysinv.helm.placement import PlacementHelm
from sysinv.helm.rabbitmq import RabbitmqHelm
from sysinv.helm.swift import SwiftHelm
from sysinv.openstack.common import log as logging
LOG = logging.getLogger(__name__)
class OpenstackArmadaManifestOperator(base.ArmadaManifestOperator):
APP = constants.HELM_APP_OPENSTACK
ARMADA_MANIFEST = 'armada-manifest'
CHART_INGRESS_KS = CHART_GROUP_INGRESS_KS = 'kube-system-ingress'
CHART_GROUP_INGRESS_OS = 'openstack-ingress'
CHART_GROUP_MAGNUM = 'openstack-magnum'
CHART_GROUP_MARIADB = 'openstack-mariadb'
CHART_GROUP_MEMCACHED = 'openstack-memcached'
CHART_GROUP_RABBITMQ = 'openstack-rabbitmq'
CHART_GROUP_KEYSTONE = 'openstack-keystone'
CHART_GROUP_KS_API_PROXY = 'openstack-keystone-api-proxy'
CHART_GROUP_BARBICAN = 'openstack-barbican'
CHART_GROUP_GLANCE = 'openstack-glance'
CHART_GROUP_SWIFT = 'openstack-ceph-rgw'
CHART_GROUP_CINDER = 'openstack-cinder'
CHART_GROUP_COMPUTE_KIT = 'openstack-compute-kit'
CHART_GROUP_HEAT = 'openstack-heat'
CHART_GROUP_HORIZON = 'openstack-horizon'
CHART_GROUP_TELEMETRY = 'openstack-telemetry'
CHART_GROUPS_LUT = {
AodhHelm.CHART: CHART_GROUP_TELEMETRY,
BarbicanHelm.CHART: CHART_GROUP_BARBICAN,
CeilometerHelm.CHART: CHART_GROUP_TELEMETRY,
CinderHelm.CHART: CHART_GROUP_CINDER,
GarbdHelm.CHART: CHART_GROUP_MARIADB,
GlanceHelm.CHART: CHART_GROUP_GLANCE,
GnocchiHelm.CHART: CHART_GROUP_TELEMETRY,
HeatHelm.CHART: CHART_GROUP_HEAT,
HorizonHelm.CHART: CHART_GROUP_HORIZON,
IngressHelm.CHART: CHART_GROUP_INGRESS_OS,
IronicHelm.CHART: CHART_GROUP_COMPUTE_KIT,
KeystoneHelm.CHART: CHART_GROUP_KEYSTONE,
KeystoneApiProxyHelm.CHART: CHART_GROUP_KS_API_PROXY,
LibvirtHelm.CHART: CHART_GROUP_COMPUTE_KIT,
MagnumHelm.CHART: CHART_GROUP_MAGNUM,
MariadbHelm.CHART: CHART_GROUP_MARIADB,
MemcachedHelm.CHART: CHART_GROUP_MEMCACHED,
NeutronHelm.CHART: CHART_GROUP_COMPUTE_KIT,
NginxPortsControlHelm.CHART: CHART_GROUP_INGRESS_OS,
NovaHelm.CHART: CHART_GROUP_COMPUTE_KIT,
NovaApiProxyHelm.CHART: CHART_GROUP_COMPUTE_KIT,
OpenvswitchHelm.CHART: CHART_GROUP_COMPUTE_KIT,
PankoHelm.CHART: CHART_GROUP_TELEMETRY,
PlacementHelm.CHART: CHART_GROUP_COMPUTE_KIT,
RabbitmqHelm.CHART: CHART_GROUP_RABBITMQ,
SwiftHelm.CHART: CHART_GROUP_SWIFT,
}
CHARTS_LUT = {
AodhHelm.CHART: 'openstack-aodh',
BarbicanHelm.CHART: 'openstack-barbican',
CeilometerHelm.CHART: 'openstack-ceilometer',
CinderHelm.CHART: 'openstack-cinder',
GarbdHelm.CHART: 'openstack-garbd',
GlanceHelm.CHART: 'openstack-glance',
GnocchiHelm.CHART: 'openstack-gnocchi',
HeatHelm.CHART: 'openstack-heat',
HorizonHelm.CHART: 'openstack-horizon',
IngressHelm.CHART: 'openstack-ingress',
IronicHelm.CHART: 'openstack-ironic',
KeystoneHelm.CHART: 'openstack-keystone',
KeystoneApiProxyHelm.CHART: 'openstack-keystone-api-proxy',
LibvirtHelm.CHART: 'openstack-libvirt',
MagnumHelm.CHART: 'openstack-magnum',
MariadbHelm.CHART: 'openstack-mariadb',
MemcachedHelm.CHART: 'openstack-memcached',
NeutronHelm.CHART: 'openstack-neutron',
NginxPortsControlHelm.CHART: 'openstack-nginx-ports-control',
NovaHelm.CHART: 'openstack-nova',
NovaApiProxyHelm.CHART: 'openstack-nova-api-proxy',
OpenvswitchHelm.CHART: 'openstack-openvswitch',
PankoHelm.CHART: 'openstack-panko',
PlacementHelm.CHART: 'openstack-placement',
RabbitmqHelm.CHART: 'openstack-rabbitmq',
SwiftHelm.CHART: 'openstack-ceph-rgw',
}
def platform_mode_manifest_updates(self, dbapi, mode):
""" Update the application manifest based on the platform
This is used for
:param dbapi: DB api object
:param mode: mode to control how to apply the application manifest
"""
if mode == constants.OPENSTACK_RESTORE_DB:
# During application restore, first bring up
# MariaDB service.
self.manifest_chart_groups_set(
self.ARMADA_MANIFEST,
[self.CHART_GROUP_INGRESS_KS,
self.CHART_GROUP_INGRESS_OS,
self.CHART_GROUP_MARIADB])
elif mode == constants.OPENSTACK_RESTORE_STORAGE:
# After MariaDB data is restored, restore Keystone,
# Glance and Cinder.
self.manifest_chart_groups_set(
self.ARMADA_MANIFEST,
[self.CHART_GROUP_INGRESS_KS,
self.CHART_GROUP_INGRESS_OS,
self.CHART_GROUP_MARIADB,
self.CHART_GROUP_MEMCACHED,
self.CHART_GROUP_RABBITMQ,
self.CHART_GROUP_KEYSTONE,
self.CHART_GROUP_GLANCE,
self.CHART_GROUP_CINDER])
else:
# When mode is OPENSTACK_RESTORE_NORMAL or None,
# bring up all the openstack services.
try:
system = dbapi.isystem_get_one()
except exception.NotFound:
LOG.exception("System %s not found.")
raise
if (system.distributed_cloud_role ==
constants.DISTRIBUTED_CLOUD_ROLE_SYSTEMCONTROLLER):
# remove the chart_groups not needed in this configuration
self.manifest_chart_groups_delete(
self.ARMADA_MANIFEST, self.CHART_GROUP_SWIFT)
self.manifest_chart_groups_delete(
self.ARMADA_MANIFEST, self.CHART_GROUP_COMPUTE_KIT)
self.manifest_chart_groups_delete(
self.ARMADA_MANIFEST, self.CHART_GROUP_HEAT)
self.manifest_chart_groups_delete(
self.ARMADA_MANIFEST, self.CHART_GROUP_TELEMETRY)

View File

@ -0,0 +1,43 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
#
# Copyright (c) 2019 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
# All Rights Reserved.
#
""" System inventory Armada manifest operator."""
from sysinv.common import constants
from sysinv.helm import manifest_base as base
from sysinv.helm.ceph_pools_audit import CephPoolsAuditHelm
from sysinv.helm.rbd_provisioner import RbdProvisionerHelm
from sysinv.openstack.common import log as logging
LOG = logging.getLogger(__name__)
class PlatformArmadaManifestOperator(base.ArmadaManifestOperator):
APP = constants.HELM_APP_PLATFORM
ARMADA_MANIFEST = 'platform-integration-manifest'
CHART_GROUP_CEPH = 'starlingx-ceph-charts'
CHART_GROUPS_LUT = {
CephPoolsAuditHelm.CHART: CHART_GROUP_CEPH,
RbdProvisionerHelm.CHART: CHART_GROUP_CEPH
}
CHARTS_LUT = {
CephPoolsAuditHelm.CHART: 'kube-system-ceph-pools-audit',
RbdProvisionerHelm.CHART: 'kube-system-rbd-provisioner'
}
def platform_mode_manifest_updates(self, dbapi, mode):
""" Update the application manifest based on the platform
:param dbapi: DB api object
:param mode: mode to control how to apply the application manifest
"""
pass

View File

@ -4,7 +4,6 @@
# SPDX-License-Identifier: Apache-2.0
#
from sysinv.common import constants
from sysinv.common import exception
from sysinv.openstack.common import log as logging
from sysinv.helm import common
@ -16,7 +15,7 @@ LOG = logging.getLogger(__name__)
class MariadbHelm(openstack.OpenstackBaseHelm):
"""Class to encapsulate helm operations for the mariadb chart"""
CHART = constants.HELM_CHART_MARIADB
CHART = common.HELM_CHART_MARIADB
def _num_server_replicas(self):
return self._num_controllers()

View File

@ -16,7 +16,7 @@ LOG = logging.getLogger(__name__)
class MemcachedHelm(base.BaseHelm):
"""Class to encapsulate helm operations for the memcached chart"""
CHART = constants.HELM_CHART_MEMCACHED
CHART = common.HELM_CHART_MEMCACHED
SUPPORTED_NAMESPACES = \
base.BaseHelm.SUPPORTED_NAMESPACES + [common.HELM_NS_OPENSTACK]
SUPPORTED_APP_NAMESPACES = {

View File

@ -20,9 +20,9 @@ SRIOV_NETWORK_TYPES = [constants.NETWORK_TYPE_PCI_SRIOV]
class NeutronHelm(openstack.OpenstackBaseHelm):
"""Class to encapsulate helm operations for the neutron chart"""
CHART = constants.HELM_CHART_NEUTRON
CHART = common.HELM_CHART_NEUTRON
SERVICE_NAME = 'neutron'
SERVICE_NAME = common.HELM_CHART_NEUTRON
AUTH_USERS = ['neutron']
SERVICE_USERS = ['nova']

View File

@ -4,7 +4,6 @@
# SPDX-License-Identifier: Apache-2.0
#
from sysinv.common import constants
from sysinv.common import exception
from sysinv.openstack.common import log as logging
from sysinv.helm import common
@ -16,7 +15,7 @@ LOG = logging.getLogger(__name__)
class NginxPortsControlHelm(base.BaseHelm):
"""Class to encapsulate helm operations for nginx-ports-control chart"""
CHART = constants.HELM_CHART_NGINX_PORTS_CONTROL
CHART = common.HELM_CHART_NGINX_PORTS_CONTROL
SUPPORTED_NAMESPACES = \
base.BaseHelm.SUPPORTED_NAMESPACES + [common.HELM_NS_OPENSTACK]

View File

@ -43,9 +43,9 @@ DEFAULT_NOVA_PCI_ALIAS = [
class NovaHelm(openstack.OpenstackBaseHelm):
"""Class to encapsulate helm operations for the nova chart"""
CHART = constants.HELM_CHART_NOVA
CHART = common.HELM_CHART_NOVA
SERVICE_NAME = 'nova'
SERVICE_NAME = common.HELM_CHART_NOVA
AUTH_USERS = ['nova', ]
SERVICE_USERS = ['neutron', 'ironic', 'placement']
NOVNCPROXY_SERVICE_NAME = 'novncproxy'
@ -125,15 +125,14 @@ class NovaHelm(openstack.OpenstackBaseHelm):
})
return overrides
def _compute_ironic_manifests(self, is_labeled):
manifests = {
'statefulset_compute_ironic': is_labeled
}
return manifests
def _get_compute_ironic_manifests(self):
ironic_label = self._is_labeled(common.LABEL_IRONIC, 'enabled')
return self._compute_ironic_manifests(ironic_label)
ironic_operator = self._operator.chart_operators[
common.HELM_CHART_IRONIC]
enabled = ironic_operator._is_enabled(constants.HELM_APP_OPENSTACK,
common.HELM_CHART_IRONIC, common.HELM_NS_OPENSTACK)
return {
'statefulset_compute_ironic': enabled
}
def _get_endpoints_overrides(self):
overrides = {

View File

@ -4,7 +4,6 @@
# SPDX-License-Identifier: Apache-2.0
#
from sysinv.common import constants
from sysinv.common import exception
from sysinv.openstack.common import log as logging
from sysinv.helm import common
@ -16,9 +15,9 @@ LOG = logging.getLogger(__name__)
class NovaApiProxyHelm(openstack.OpenstackBaseHelm):
"""Class to encapsulate helm operations for the nova chart"""
CHART = constants.HELM_CHART_NOVA_API_PROXY
CHART = common.HELM_CHART_NOVA_API_PROXY
SERVICE_NAME = 'nova-api-proxy'
SERVICE_NAME = common.HELM_CHART_NOVA_API_PROXY
AUTH_USERS = ['nova']
def get_overrides(self, namespace=None):
@ -56,7 +55,7 @@ class NovaApiProxyHelm(openstack.OpenstackBaseHelm):
def _get_endpoints_overrides(self):
nova_service_name = self._operator.chart_operators[
constants.HELM_CHART_NOVA].SERVICE_NAME
common.HELM_CHART_NOVA].SERVICE_NAME
return {
'identity': {
@ -66,7 +65,7 @@ class NovaApiProxyHelm(openstack.OpenstackBaseHelm):
'compute': {
'host_fqdn_override':
self._get_endpoints_host_fqdn_overrides(
constants.HELM_CHART_NOVA),
common.HELM_CHART_NOVA),
'port': self._get_endpoints_port_api_public_overrides(),
'scheme': self._get_endpoints_scheme_public_overrides(),
},

View File

@ -70,7 +70,7 @@ class OpenstackBaseHelm(base.BaseHelm):
def _get_admin_user_name(self):
keystone_operator = self._operator.chart_operators[
constants.HELM_CHART_KEYSTONE]
common.HELM_CHART_KEYSTONE]
return keystone_operator.get_admin_user_name()
def _get_identity_password(self, service, user):
@ -469,3 +469,36 @@ class OpenstackBaseHelm(base.BaseHelm):
K8RbdProvisioner.get_user_secret_name({
'name': constants.SB_DEFAULT_NAMES[constants.SB_TYPE_CEPH]})
}
def execute_manifest_updates(self, operator):
"""
Update the elements of the armada manifest.
This allows a helm chart plugin to use the ArmadaManifestOperator to
make dynamic structural changes to the application manifest based on the
current conditions in the platform
Changes include updates to manifest documents for the following schemas:
armada/Manifest/v1, armada/ChartGroup/v1, armada/Chart/v1.
:param operator: an instance of the ArmadaManifestOperator
"""
if not self._is_enabled(operator.APP, self.CHART,
common.HELM_NS_OPENSTACK):
operator.chart_group_chart_delete(
operator.CHART_GROUPS_LUT[self.CHART],
operator.CHARTS_LUT[self.CHART])
def _is_enabled(self, app_name, chart_name, namespace):
"""
Check if the chart is enable at a system level
:param app_name: Application name
:param chart_name: Chart supplied with the application
:param namespace: Namespace where the chart will be executed
Returns true by default if an exception occurs as most charts are
enabled.
"""
return super(OpenstackBaseHelm, self)._is_enabled(
app_name, chart_name, namespace)

View File

@ -17,15 +17,27 @@ LOG = logging.getLogger(__name__)
class OpenvswitchHelm(openstack.OpenstackBaseHelm):
"""Class to encapsulate helm operations for the openvswitch chart"""
CHART = constants.HELM_CHART_OPENVSWITCH
CHART = common.HELM_CHART_OPENVSWITCH
def execute_manifest_updates(self, operator, app_name=None):
if utils.get_vswitch_type(self.dbapi) == constants.VSWITCH_TYPE_NONE:
# add the openvswitch chart into computekit chart group
def _is_enabled(self, app_name, chart_name, namespace):
# First, see if this chart is enabled by the user then adjust based on
# system conditions
enabled = super(OpenvswitchHelm, self)._is_enabled(
app_name, chart_name, namespace)
if enabled and (utils.get_vswitch_type(self.dbapi) !=
constants.VSWITCH_TYPE_NONE):
enabled = False
return enabled
def execute_manifest_updates(self, operator):
# On application load, this chart in not included in the compute-kit
# chart group . Insert as needed.
if self._is_enabled(operator.APP,
self.CHART, common.HELM_NS_OPENSTACK):
operator.chart_group_chart_insert(
'openstack-compute-kit',
'openstack-openvswitch',
before_chart='openstack-nova')
operator.CHART_GROUPS_LUT[self.CHART],
operator.CHARTS_LUT[self.CHART],
before_chart=operator.CHARTS_LUT[common.HELM_CHART_NOVA])
def get_overrides(self, namespace=None):
overrides = {

View File

@ -4,7 +4,6 @@
# SPDX-License-Identifier: Apache-2.0
#
from sysinv.common import constants
from sysinv.common import exception
from sysinv.openstack.common import log as logging
from sysinv.helm import common
@ -16,9 +15,9 @@ LOG = logging.getLogger(__name__)
class PankoHelm(openstack.OpenstackBaseHelm):
"""Class to encapsulate helm operations for the panko chart"""
CHART = constants.HELM_CHART_PANKO
CHART = common.HELM_CHART_PANKO
SERVICE_NAME = 'panko'
SERVICE_NAME = common.HELM_CHART_PANKO
AUTH_USERS = ['panko']
def get_overrides(self, namespace=None):

View File

@ -4,7 +4,6 @@
# SPDX-License-Identifier: Apache-2.0
#
from sysinv.common import constants
from sysinv.common import exception
from sysinv.helm import common
from sysinv.helm import openstack
@ -13,9 +12,9 @@ from sysinv.helm import openstack
class PlacementHelm(openstack.OpenstackBaseHelm):
"""Class to encapsulate helm operations for the placement chart"""
CHART = constants.HELM_CHART_PLACEMENT
CHART = common.HELM_CHART_PLACEMENT
SERVICE_NAME = 'placement'
SERVICE_NAME = common.HELM_CHART_PLACEMENT
AUTH_USERS = ['placement']
def get_overrides(self, namespace=None):

View File

@ -4,7 +4,6 @@
# SPDX-License-Identifier: Apache-2.0
#
from sysinv.common import constants
from sysinv.common import exception
from sysinv.openstack.common import log as logging
from sysinv.helm import common
@ -16,7 +15,7 @@ LOG = logging.getLogger(__name__)
class RabbitmqHelm(openstack.OpenstackBaseHelm):
"""Class to encapsulate helm operations for the rabbitmq chart"""
CHART = constants.HELM_CHART_RABBITMQ
CHART = common.HELM_CHART_RABBITMQ
def get_overrides(self, namespace=None):
overrides = {

View File

@ -18,7 +18,7 @@ LOG = logging.getLogger(__name__)
class RbdProvisionerHelm(base.BaseHelm):
"""Class to encapsulate helm operations for the rbd-provisioner chart"""
CHART = constants.HELM_CHART_RBD_PROVISIONER
CHART = common.HELM_CHART_RBD_PROVISIONER
SUPPORTED_NAMESPACES = base.BaseHelm.SUPPORTED_NAMESPACES + \
[common.HELM_NS_STORAGE_PROVISIONER]
SUPPORTED_APP_NAMESPACES = {
@ -26,9 +26,18 @@ class RbdProvisionerHelm(base.BaseHelm):
base.BaseHelm.SUPPORTED_NAMESPACES + [common.HELM_NS_STORAGE_PROVISIONER],
}
SERVICE_NAME = 'rbd-provisioner'
SERVICE_NAME = common.HELM_CHART_RBD_PROVISIONER
SERVICE_PORT_MON = 6789
def execute_manifest_updates(self, operator):
# On application load this chart is enabled. Only disable if specified
# by the user
if not self._is_enabled(operator.APP, self.CHART,
common.HELM_NS_STORAGE_PROVISIONER):
operator.chart_group_chart_delete(
operator.CHART_GROUPS_LUT[self.CHART],
operator.CHARTS_LUT[self.CHART])
def get_overrides(self, namespace=None):
backends = self.dbapi.storage_backend_get_list()

View File

@ -4,7 +4,6 @@
# SPDX-License-Identifier: Apache-2.0
#
from sysinv.common import constants
from sysinv.common import exception
from sysinv.openstack.common import log as logging
@ -18,7 +17,7 @@ LOG = logging.getLogger(__name__)
class SwiftHelm(openstack.OpenstackBaseHelm):
"""Class to encapsulate helm operations for the swift chart"""
CHART = constants.HELM_CHART_SWIFT
CHART = common.HELM_CHART_SWIFT
SERVICE_NAME = 'swift'
SERVICE_TYPE = 'object-store'