Helm Backend for chart specific system overrides

Mirror the current infrastructure that we use for puppet based
provisioning of openstack services to enable system specific helm
overrides.

This commit comprises the backend to the sysinv API helm commands that
allow a customer to update the system provided overrides or introduce
new overrides for specific charts.

Four conductor RPC functions are provided to the API to gather system
overrides and namespaces for supported charts and chart bundles (i.e. an
application):
 - get_helm_chart_namespaces()
 - get_helm_chart_overrides()
 - get_helm_application_overrides()
 - get_helm_application_namespaces()

An application in this context is a set of supported charts that we
would deploy to support some specific functionality (i.e. a customized
openstack solution)

As with the puppet infrastructure, a CLI is provided to get the latest
system-only overrides for a given chart or bundle of charts that make up
an application. This is provided for development purposes and removes
user-provided overrides from the picture.

The following is the chart command syntax, a command to generate
override files for all supported namespaces of the ingress chart, and a
command to generate overrides for just the openstack namespace of the
ingress chart:
 - sysinv-helm create-chart-overrides <path> <chart> <specific namespace>
 - sysinv-helm create-chart-overrides /root/overrides ingress
 - sysinv-helm create-chart-overrides /root/overrides ingress openstack

The following is the application command syntax, a command to generate
override files for all supported namespaces of the all chart in the
chart bundle, and a command to generate overrides for all charts in the
chart bundle that support the kube-system namespace:
 - sysinv-helm create-app-overrides <path> <app> <specific namespace>
 - sysinv-helm create-app-overrides /root/overrides wr-openstack
 - sysinv-helm create-app-overrides /root/overrides wr-openstack kube-system

Story: 2002876
Task: 22831
Depends-On: https://review.openstack.org/587390

Change-Id: Idbe0938ef196fb68f716a95d1e9202f6f77cb6a8
Signed-off-by: Jack Ding <jack.ding@windriver.com>
This commit is contained in:
Robert Church 2018-06-20 23:00:28 -05:00 committed by Jack Ding
parent b13cf38786
commit 8243f7d6ab
25 changed files with 1341 additions and 0 deletions

View File

@ -115,3 +115,4 @@ rm -rf $RPM_BUILD_ROOT
%{_bindir}/sysinv-rootwrap
%{_bindir}/sysinv-upgrade
%{_bindir}/sysinv-puppet
%{_bindir}/sysinv-helm

View File

@ -36,6 +36,7 @@ console_scripts =
sysinv-dnsmasq-lease-update = sysinv.cmd.dnsmasq_lease_update:main
sysinv-upgrade = sysinv.cmd.upgrade:main
sysinv-puppet = sysinv.cmd.puppet:main
sysinv-helm = sysinv.cmd.helm:main
[pbr]
autodoc_index_modules = True

View File

@ -0,0 +1,65 @@
#!/usr/bin/env python
#
# Copyright (c) 2018 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
"""
System Inventory Helm Utility.
"""
import sys
from oslo_config import cfg
from sysinv.common import service
from sysinv.db import api
from sysinv.helm import helm
CONF = cfg.CONF
def create_app_overrides_action(path, app_name=None, namespace=None):
dbapi = api.get_instance()
operator = helm.HelmOperator(dbapi=dbapi, path=path)
operator.generate_helm_application_overrides(app_name, namespace)
def create_chart_override_action(path, chart_name=None, namespace=None):
dbapi = api.get_instance()
operator = helm.HelmOperator(dbapi=dbapi, path=path)
operator.generate_helm_chart_overrides(chart_name, namespace)
def add_action_parsers(subparsers):
parser = subparsers.add_parser('create-app-overrides')
parser.set_defaults(func=create_app_overrides_action)
parser.add_argument('path', nargs='?')
parser.add_argument('app_name', nargs='?')
parser.add_argument('namespace', nargs='?')
parser = subparsers.add_parser('create-chart-overrides')
parser.set_defaults(func=create_chart_override_action)
parser.add_argument('path', nargs='?')
parser.add_argument('chart_name', nargs='?')
parser.add_argument('namespace', nargs='?')
CONF.register_cli_opt(
cfg.SubCommandOpt('action',
title='actions',
help='Perform helm override operation',
handler=add_action_parsers))
def main():
service.prepare_service(sys.argv)
if CONF.action.name == 'create-app-overrides':
CONF.action.func(CONF.action.path,
CONF.action.app_name,
CONF.action.namespace)
elif CONF.action.name == 'create-chart-overrides':
CONF.action.func(CONF.action.path,
CONF.action.chart_name,
CONF.action.namespace)

View File

@ -1251,3 +1251,74 @@ SYSTEM_SECURITY_FEATURE_SPECTRE_MELTDOWN_OPTS = {
SYSTEM_SECURITY_FEATURE_SPECTRE_MELTDOWN_DEFAULT_OPTS = SYSTEM_SECURITY_FEATURE_SPECTRE_MELTDOWN_V1_OPTS
# Helm: Supported charts
HELM_CHART_INGRESS = 'ingress'
HELM_CHART_NFS_PROVISIONER = 'nfs-provisioner'
HELM_CHART_MARIADB = 'mariadb'
HELM_CHART_RABBITMQ = 'rabbitmq'
HELM_CHART_MEMCACHED = 'memcached'
HELM_CHART_KEYSTONE = 'keystone'
HELM_CHART_HEAT = 'heat'
HELM_CHART_HORIZON = 'horizon'
HELM_CHART_GLANCE = 'glance'
HELM_CHART_OPENVSWITCH = 'openvswitch'
HELM_CHART_LIBVIRT = 'libvirt'
HELM_CHART_NOVA = 'nova'
HELM_CHART_NEUTRON = 'neutron'
SUPPORTED_HELM_CHARTS = [
HELM_CHART_INGRESS,
HELM_CHART_NFS_PROVISIONER,
HELM_CHART_MARIADB,
HELM_CHART_RABBITMQ,
HELM_CHART_MEMCACHED,
HELM_CHART_KEYSTONE,
HELM_CHART_HEAT,
HELM_CHART_HORIZON,
HELM_CHART_GLANCE,
HELM_CHART_OPENVSWITCH,
HELM_CHART_LIBVIRT,
HELM_CHART_NOVA,
HELM_CHART_NEUTRON
]
# Helm: Supported application (aka chart bundles)
# TODO (rchurch): remove OSHELM applications.These are temporary chart bundles
# until we fully integrate our k8s openstack application. Not
# sure at this point if we'll need an AIO flavor (without Ceph
# but with NFS support)
HELM_APP_OPENSTACK = 'wr-openstack'
HELM_APP_OSHELM_DEVELOPER = 'openstack-helm-developer'
HELM_APP_OSHELM_MULTINODE = 'openstack-helm-multinode'
SUPPORTED_HELM_APP_NAMES = [
HELM_APP_OPENSTACK,
HELM_APP_OSHELM_DEVELOPER,
HELM_APP_OSHELM_MULTINODE
]
SUPPORTED_HELM_APP_CHARTS = {
HELM_APP_OPENSTACK: [
HELM_CHART_INGRESS
],
HELM_APP_OSHELM_DEVELOPER: [
HELM_CHART_INGRESS,
HELM_CHART_NFS_PROVISIONER,
HELM_CHART_MARIADB,
HELM_CHART_RABBITMQ,
HELM_CHART_MEMCACHED,
HELM_CHART_KEYSTONE,
HELM_CHART_HEAT,
HELM_CHART_HORIZON,
HELM_CHART_GLANCE,
HELM_CHART_OPENVSWITCH,
HELM_CHART_LIBVIRT,
HELM_CHART_NOVA,
HELM_CHART_NEUTRON
],
HELM_APP_OSHELM_MULTINODE: [
HELM_CHART_INGRESS
]
}

View File

@ -1236,3 +1236,7 @@ class IncompleteCephMonNetworkConfig(CephFailure):
message = _("IP address for controller-0, controller-1 and "
"storage-0 must be allocated. Expected: %(targets)s, "
"found: %(results)s")
class InvalidHelmNamespace(Invalid):
message = _("Invalid helm overrides namespace (%(namespace)s) for chart %(chart)s.")

View File

@ -90,6 +90,7 @@ from sysinv.openstack.common import uuidutils
from sysinv.openstack.common.gettextutils import _
from sysinv.puppet import common as puppet_common
from sysinv.puppet import puppet
from sysinv.helm import helm
MANAGER_TOPIC = 'sysinv.conductor_manager'
@ -176,6 +177,7 @@ class ConductorManager(service.PeriodicService):
self._openstack = openstack.OpenStackOperator(self.dbapi)
self._puppet = puppet.PuppetOperator(self.dbapi)
self._ceph = iceph.CephOperator(self.dbapi)
self._helm = helm.HelmOperator(self.dbapi)
# create /var/run/sysinv if required. On DOR, the manifests
# may not run to create this volatile directory.
@ -10009,3 +10011,113 @@ class ConductorManager(service.PeriodicService):
f.write(file_content)
return signature
def get_helm_chart_namespaces(self, context, chart_name):
"""Get supported chart namespaces.
This method retrieves the namespace supported by a given chart.
:param context: request context.
:param chart_name: name of the chart
:returns: list of supported namespaces that associated overrides may be
provided.
"""
return self._helm.get_helm_chart_namespaces(chart_name)
def get_helm_chart_overrides(self, context, chart_name, cnamespace=None):
"""Get the overrides for a supported chart.
This method retrieves overrides for a supported chart. Overrides for
all supported namespaces will be returned unless a specific namespace
is requested.
:param context: request context.
:param chart_name: name of a supported chart
:param cnamespace: (optional) namespace
:returns: dict of overrides.
Example Without a cnamespace parameter:
{
'kube-system': {
'deployment': {
'mode': 'cluster',
'type': 'DaemonSet'
},
},
'openstack': {
'pod': {
'replicas': {
'server': 1
}
}
}
}
Example with a cnamespace parameter: cnamespace='kube-system'
{
'deployment': {
'mode': 'cluster',
'type': 'DaemonSet'
}
}
"""
return self._helm.get_helm_chart_overrides(chart_name,
cnamespace)
def get_helm_application_namespaces(self, context, app_name):
"""Get supported application namespaces.
This method retrieves a dict of charts and their supported namespaces
for an application.
:param app_name: name of the bundle of charts required to support an
application
:returns: dict of charts and supported namespaces that associated
overrides may be provided.
"""
return self._helm.get_helm_application_namespaces(app_name)
def get_helm_application_overrides(self, context, app_name, cnamespace):
"""Get the overrides for a supported set of charts.
This method retrieves overrides for a set of supported charts that
comprise an application. Overrides for all charts and all supported
namespaces will be returned unless a specific namespace is requested.
If a specific namespace is requested, then only charts that that
support that specified namespace will be returned.
:param context: request context.
:param app_name: name of a supported application (set of charts)
:param cnamespace: (optional) namespace
:returns: dict of overrides.
Example:
{
'ingress': {
'kube-system': {
'deployment': {
'mode': 'cluster',
'type': 'DaemonSet'
},
},
'openstack': {
'pod': {
'replicas': {
'server': 1
}
}
}
},
'glance': {
'openstack': {
'pod': {
'replicas': {
'server': 1
}
}
}
}
}
"""
return self._helm.get_helm_application_overrides(app_name, cnamespace)

View File

@ -1556,3 +1556,57 @@ class ConductorAPI(sysinv.openstack.common.rpc.proxy.RpcProxy):
pem_contents=pem_contents,
config_dict=config_dict,
))
def get_helm_chart_namespaces(self, context, chart_name):
"""Get supported chart namespaces.
This method retrieves the namespace supported by a given chart.
:param context: request context.
:param chart_name: name of the chart
:returns: list of supported namespaces that associated overrides may be
provided.
"""
return self.call(context,
self.make_msg('get_helm_chart_namespaces',
chart_name=chart_name))
def get_helm_chart_overrides(self, context, chart_name, cnamespace=None):
"""Get the overrides for a supported chart.
:param context: request context.
:param chart_name: name of a supported chart
:param cnamespace: (optional) namespace
:returns: dict of overrides.
"""
return self.call(context,
self.make_msg('get_helm_chart_overrides',
chart_name=chart_name,
cnamespace=cnamespace))
def get_helm_application_namespaces(self, context, app_name):
"""Get supported application namespaces.
:param app_name: name of the bundle of charts required to support an
application
:returns: dict of charts and supported namespaces that associated
overrides may be provided.
"""
return self.call(context,
self.make_msg('get_helm_application_namespaces',
app_name=app_name))
def get_helm_application_overrides(self, context, app_name, cnamespace=None):
"""Get the overrides for a supported set of charts.
:param context: request context.
:param app_name: name of a supported application (set of charts)
:param cnamespace: (optional) namespace
:returns: dict of overrides.
"""
return self.call(context,
self.make_msg('get_helm_application_overrides',
app_name=app_name,
cnamespace=cnamespace))

View File

@ -0,0 +1,19 @@
#
# Copyright (c) 2018 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
import yaml
class quoted_str(str):
pass
# force strings to be single-quoted to avoid interpretation as numeric values
def quoted_presenter(dumper, data):
return dumper.represent_scalar(u'tag:yaml.org,2002:str', data, style="'")
yaml.add_representer(quoted_str, quoted_presenter)

View File

@ -0,0 +1,24 @@
#
# Copyright (c) 2018 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
import abc
import six
@six.add_metaclass(abc.ABCMeta)
class BaseHelm(object):
"""Base class to encapsulate helm operations for chart overrides"""
def __init__(self, operator):
self._operator = operator
@property
def dbapi(self):
return self._operator.dbapi
@property
def context(self):
return self._operator.context

View File

@ -0,0 +1,23 @@
#
# Copyright (c) 2018 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
""" System Inventory Helm common top level code."""
import os
from sysinv.openstack.common import log as logging
from tsconfig import tsconfig
LOG = logging.getLogger(__name__)
HELM_OVERRIDES_PATH = os.path.join(tsconfig.PLATFORM_PATH, 'helm', tsconfig.SW_VERSION)
# Common Namespaces
HELM_NS_KUBE_SYSTEM = 'kube-system'
HELM_NS_NFS = 'nfs'
HELM_NS_OPENSTACK = 'openstack'

View File

@ -0,0 +1,40 @@
#
# Copyright (c) 2018 Wind River Systems, Inc.
#
# 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 . import common
from . import openstack
LOG = logging.getLogger(__name__)
class GlanceHelm(openstack.OpenstackBaseHelm):
"""Class to encapsulate helm operations for the glance chart"""
CHART = constants.HELM_CHART_GLANCE
SUPPORTED_NAMESPACES = [
common.HELM_NS_OPENSTACK
]
def get_namespaces(self):
return self.SUPPORTED_NAMESPACES
def get_overrides(self, namespace=None):
overrides = {
common.HELM_NS_OPENSTACK: {
'storage': 'pvc'
}
}
if namespace in self.SUPPORTED_NAMESPACES:
return overrides[namespace]
elif namespace:
raise exception.InvalidHelmNamespace(chart=self.CHART,
namespace=namespace)
else:
return overrides

View File

@ -0,0 +1,39 @@
#
# Copyright (c) 2018 Wind River Systems, Inc.
#
# 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 . import common
from . import openstack
LOG = logging.getLogger(__name__)
class HeatHelm(openstack.OpenstackBaseHelm):
"""Class to encapsulate helm operations for the heat chart"""
CHART = constants.HELM_CHART_HEAT
SUPPORTED_NAMESPACES = [
common.HELM_NS_OPENSTACK
]
def get_namespaces(self):
return self.SUPPORTED_NAMESPACES
def get_overrides(self, namespace=None):
overrides = {
common.HELM_NS_OPENSTACK: {
}
}
if namespace in self.SUPPORTED_NAMESPACES:
return overrides[namespace]
elif namespace:
raise exception.InvalidHelmNamespace(chart=self.CHART,
namespace=namespace)
else:
return overrides

View File

@ -0,0 +1,356 @@
#
# Copyright (c) 2018 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
""" System Inventory Helm Overrides Operator."""
from __future__ import absolute_import
import eventlet
import os
import tempfile
import yaml
from six import iteritems
from sysinv.common import constants
from sysinv.common import exception
from sysinv.openstack.common import log as logging
from . import common
# Import Chart Override Helpers:
# Chart source: openstack-helm
from . import glance
from . import heat
from . import horizon
from . import ingress
from . import keystone
from . import libvirt
from . import mariadb
from . import memcached
from . import neutron
from . import nfs_provisioner
from . import nova
from . import openvswitch
from . import rabbitmq
LOG = logging.getLogger(__name__)
def helm_context(func):
"""Decorate to initialize the local threading context"""
def _wrapper(self, *args, **kwargs):
thread_context = eventlet.greenthread.getcurrent()
setattr(thread_context, '_helm_context', dict())
func(self, *args, **kwargs)
return _wrapper
class HelmOperator(object):
"""Class to encapsulate helm override operations for System Inventory"""
def __init__(self, dbapi=None, path=None):
if path is None:
path = common.HELM_OVERRIDES_PATH
self.dbapi = dbapi
self.path = path
# register chart operators for lookup
self.chart_operators = {
constants.HELM_CHART_GLANCE: glance.GlanceHelm(self),
constants.HELM_CHART_HEAT: heat.HeatHelm(self),
constants.HELM_CHART_HORIZON: horizon.HorizonHelm(self),
constants.HELM_CHART_INGRESS: ingress.IngressHelm(self),
constants.HELM_CHART_KEYSTONE: keystone.KeystoneHelm(self),
constants.HELM_CHART_LIBVIRT: libvirt.LibvirtHelm(self),
constants.HELM_CHART_MARIADB: mariadb.MariadbHelm(self),
constants.HELM_CHART_MEMCACHED: memcached.MemcachedHelm(self),
constants.HELM_CHART_NEUTRON: neutron.NeutronHelm(self),
constants.HELM_CHART_NFS_PROVISIONER:
nfs_provisioner.NfsProvisionerHelm(self),
constants.HELM_CHART_NOVA: nova.NovaHelm(self),
constants.HELM_CHART_OPENVSWITCH:
openvswitch.OpenvswitchHelm(self),
constants.HELM_CHART_RABBITMQ: rabbitmq.RabbitmqHelm(self),
}
# build the list of registered supported charts
self.implemented_charts = []
for chart in constants.SUPPORTED_HELM_CHARTS:
if chart in self.chart_operators.keys():
self.implemented_charts.append(chart)
@property
def context(self):
thread_context = eventlet.greenthread.getcurrent()
return getattr(thread_context, '_helm_context')
def get_helm_chart_namespaces(self, chart_name):
"""Get supported chart namespaces.
This method retrieves the namespace supported by a given chart.
:param chart_name: name of the chart
:returns: list of supported namespaces that associated overrides may be
provided.
"""
namespaces = []
if chart_name in self.implemented_charts:
namespaces = self.chart_operators[chart_name].get_namespaces()
return namespaces
def get_helm_chart_overrides(self, chart_name, cnamespace=None):
"""Get the overrides for a supported chart.
This method retrieves overrides for a supported chart. Overrides for
all supported namespaces will be returned unless a specific namespace
is requested.
:param chart_name: name of a supported chart
:param cnamespace: (optional) namespace
:returns: dict of overrides.
Example Without a cnamespace parameter:
{
'kube-system': {
'deployment': {
'mode': 'cluster',
'type': 'DaemonSet'
},
},
'openstack': {
'pod': {
'replicas': {
'server': 1
}
}
}
}
Example with a cnamespace parameter: cnamespace='kube-system'
{
'deployment': {
'mode': 'cluster',
'type': 'DaemonSet'
}
}
"""
overrides = {}
if chart_name in self.implemented_charts:
try:
overrides.update(
self.chart_operators[chart_name].get_overrides(
cnamespace))
except exception.InvalidHelmNamespace:
raise
return overrides
def get_helm_application_namespaces(self, app_name):
"""Get supported application namespaces.
This method retrieves a dict of charts and their supported namespaces
for an application.
:param app_name: name of the bundle of charts required to support an
application
:returns: dict of charts and supported namespaces that associated
overrides may be provided.
"""
app_namespaces = {}
if app_name in constants.SUPPORTED_HELM_APP_NAMES:
for chart_name in constants.SUPPORTED_HELM_APP_CHARTS[app_name]:
if chart_name in self.implemented_charts:
try:
app_namespaces.update({chart_name:
self.get_helm_chart_namespaces(
chart_name)})
except exception.InvalidHelmNamespace as e:
LOG.info(e)
return app_namespaces
def get_helm_application_overrides(self, app_name, cnamespace=None):
"""Get the overrides for a supported set of charts.
This method retrieves overrides for a set of supported charts that
comprise an application. Overrides for all charts and all supported
namespaces will be returned unless a specific namespace is requested.
If a specific namespace is requested, then only charts that that
support that specified namespace will be returned.
:param app_name: name of a supported application (set of charts)
:param cnamespace: (optional) namespace
:returns: dict of overrides.
Example:
{
'ingress': {
'kube-system': {
'deployment': {
'mode': 'cluster',
'type': 'DaemonSet'
},
},
'openstack': {
'pod': {
'replicas': {
'server': 1
}
}
}
},
'glance': {
'openstack': {
'pod': {
'replicas': {
'server': 1
}
}
}
}
}
"""
overrides = {}
if app_name in constants.SUPPORTED_HELM_APP_NAMES:
for chart_name in constants.SUPPORTED_HELM_APP_CHARTS[app_name]:
if chart_name in self.implemented_charts:
try:
overrides.update({chart_name:
self.get_helm_chart_overrides(
chart_name,
cnamespace)})
except exception.InvalidHelmNamespace as e:
LOG.info(e)
return overrides
@helm_context
def generate_helm_chart_overrides(self, chart_name, cnamespace=None):
"""Generate system helm chart overrides
This method will generate system helm chart override an write them to a
yaml file.for use with the helm command. If the namespace is provided
only the overrides file for that specified namespace will be written.
:param chart_name: name of a supported chart
:param cnamespace: (optional) namespace
"""
if chart_name in self.implemented_charts:
namespaces = self.chart_operators[chart_name].get_namespaces()
if cnamespace and cnamespace not in namespaces:
LOG.exception("The %s chart does not support namespace: %s" %
(chart_name, cnamespace))
return
try:
overrides = self.get_helm_chart_overrides(
chart_name,
cnamespace)
self._write_chart_overrides(chart_name,
cnamespace,
overrides)
except Exception as e:
LOG.exception("failed to create chart overrides for %s: %s" %
(chart_name, e))
elif chart_name:
LOG.exception("%s chart is not supported" % chart_name)
else:
LOG.exception("chart name is required")
@helm_context
def generate_helm_application_overrides(self, app_name, cnamespace=None):
"""Create the system overrides files for a supported application
This method will generate system helm chart overrides yaml files for a
set of supported charts that comprise an application.. If the namespace
is provided only the overrides files for that specified namespace will
be written..
:param app_name: name of the bundle of charts required to support an
application
:param cnamespace: (optional) namespace
"""
if app_name in constants.SUPPORTED_HELM_APP_NAMES:
app_overrides = self.get_helm_application_overrides(app_name,
cnamespace)
for (chart_name, overrides) in iteritems(app_overrides):
self._write_chart_overrides(chart_name, cnamespace, overrides)
elif app_name:
LOG.exception("%s application is not supported" % app_name)
else:
LOG.exception("application name is required")
def remove_helm_chart_overrides(self, chart_name, cnamespace=None):
"""Remove the overrides files for a chart"""
if chart_name in self.implemented_charts:
namespaces = self.chart_operators[chart_name].get_namespaces
filenames = []
if cnamespace and cnamespace in namespaces:
filenames.append("%s-%s.yaml" % (cnamespace, chart_name))
else:
for n in namespaces:
filenames.append("%s-%s.yaml" % (n, chart_name))
for f in filenames:
try:
self._remove_overrides(f)
except Exception as e:
LOG.exception("failed to remove %s overrides: %s: %s" % (
chart_name, f, e))
else:
LOG.exception("chart %s not supported for system overrides" %
chart_name)
def _write_chart_overrides(self, chart_name, cnamespace, overrides):
"""Write a one or more overrides files for a chart. """
def _write_file(filename, values):
try:
self._write_overrides(filename, values)
except Exception as e:
LOG.exception("failed to write %s overrides: %s: %s" % (
chart_name, filename, e))
if cnamespace:
_write_file("%s-%s.yaml" % (cnamespace, chart_name), overrides)
else:
for ns in overrides.keys():
_write_file("%s-%s.yaml" % (ns, chart_name), overrides[ns])
def _write_overrides(self, filename, overrides):
"""Write a single overrides file. """
filepath = os.path.join(self.path, filename)
try:
fd, tmppath = tempfile.mkstemp(dir=self.path, prefix=filename,
text=True)
with open(tmppath, 'w') as f:
yaml.dump(overrides, f, default_flow_style=False)
os.close(fd)
os.rename(tmppath, filepath)
except Exception:
LOG.exception("failed to write overrides file: %s" % filepath)
raise
def _remove_overrides(self, filename):
"""Remove a single overrides file. """
filepath = os.path.join(self.path, filename)
try:
if os.path.exists(filepath):
os.unlink(filepath)
except Exception:
LOG.exception("failed to delete overrides file: %s" % filepath)
raise

View File

@ -0,0 +1,45 @@
#
# Copyright (c) 2018 Wind River Systems, Inc.
#
# 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 . import common
from . import openstack
LOG = logging.getLogger(__name__)
class HorizonHelm(openstack.OpenstackBaseHelm):
"""Class to encapsulate helm operations for the horizon chart"""
CHART = constants.HELM_CHART_HORIZON
SUPPORTED_NAMESPACES = [
common.HELM_NS_OPENSTACK
]
def get_namespaces(self):
return self.SUPPORTED_NAMESPACES
def get_overrides(self, namespace=None):
overrides = {
common.HELM_NS_OPENSTACK: {
'network': {
'node_port': {
'enabled': 'true',
'port': 31000
}
}
}
}
if namespace in self.SUPPORTED_NAMESPACES:
return overrides[namespace]
elif namespace:
raise exception.InvalidHelmNamespace(chart=self.CHART,
namespace=namespace)
else:
return overrides

View File

@ -0,0 +1,59 @@
#
# Copyright (c) 2018 Wind River Systems, Inc.
#
# 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 . import common
from . import openstack
LOG = logging.getLogger(__name__)
class IngressHelm(openstack.OpenstackBaseHelm):
"""Class to encapsulate helm operations for the ingress chart"""
CHART = constants.HELM_CHART_INGRESS
SUPPORTED_NAMESPACES = [
common.HELM_NS_KUBE_SYSTEM,
common.HELM_NS_OPENSTACK
]
def get_namespaces(self):
return self.SUPPORTED_NAMESPACES
def get_overrides(self, namespace=None):
# Currently have conflicts with ports 80 and 8080, use 8081 for now
overrides = {
common.HELM_NS_KUBE_SYSTEM: {
'deployment': {
'mode': 'cluster',
'type': 'DaemonSet'
},
'network': {
'host_namespace': 'true'
},
'endpoints': {
'ingress': {
'port': {
'http': {
'default': 8081
}
}
}
}
},
common.HELM_NS_OPENSTACK: {
}
}
if namespace in self.SUPPORTED_NAMESPACES:
return overrides[namespace]
elif namespace:
raise exception.InvalidHelmNamespace(chart=self.CHART,
namespace=namespace)
else:
return overrides

View File

@ -0,0 +1,39 @@
#
# Copyright (c) 2018 Wind River Systems, Inc.
#
# 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 . import common
from . import openstack
LOG = logging.getLogger(__name__)
class KeystoneHelm(openstack.OpenstackBaseHelm):
"""Class to encapsulate helm operations for the keystone chart"""
CHART = constants.HELM_CHART_KEYSTONE
SUPPORTED_NAMESPACES = [
common.HELM_NS_OPENSTACK
]
def get_namespaces(self):
return self.SUPPORTED_NAMESPACES
def get_overrides(self, namespace=None):
overrides = {
common.HELM_NS_OPENSTACK: {
}
}
if namespace in self.SUPPORTED_NAMESPACES:
return overrides[namespace]
elif namespace:
raise exception.InvalidHelmNamespace(chart=self.CHART,
namespace=namespace)
else:
return overrides

View File

@ -0,0 +1,44 @@
#
# Copyright (c) 2018 Wind River Systems, Inc.
#
# 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 . import common
from . import openstack
LOG = logging.getLogger(__name__)
class LibvirtHelm(openstack.OpenstackBaseHelm):
"""Class to encapsulate helm operations for the libvirt chart"""
CHART = constants.HELM_CHART_LIBVIRT
SUPPORTED_NAMESPACES = [
common.HELM_NS_OPENSTACK
]
def get_namespaces(self):
return self.SUPPORTED_NAMESPACES
def get_overrides(self, namespace=None):
overrides = {
common.HELM_NS_OPENSTACK: {
'conf': {
'ceph': {
'enabled': 'false'
}
}
}
}
if namespace in self.SUPPORTED_NAMESPACES:
return overrides[namespace]
elif namespace:
raise exception.InvalidHelmNamespace(chart=self.CHART,
namespace=namespace)
else:
return overrides

View File

@ -0,0 +1,44 @@
#
# Copyright (c) 2018 Wind River Systems, Inc.
#
# 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 . import common
from . import openstack
LOG = logging.getLogger(__name__)
class MariadbHelm(openstack.OpenstackBaseHelm):
"""Class to encapsulate helm operations for the mariadb chart"""
CHART = constants.HELM_CHART_MARIADB
SUPPORTED_NAMESPACES = [
common.HELM_NS_OPENSTACK
]
def get_namespaces(self):
return self.SUPPORTED_NAMESPACES
def get_overrides(self, namespace=None):
overrides = {
common.HELM_NS_OPENSTACK: {
'pod': {
'replicas': {
'server': 1
}
}
}
}
if namespace in self.SUPPORTED_NAMESPACES:
return overrides[namespace]
elif namespace:
raise exception.InvalidHelmNamespace(chart=self.CHART,
namespace=namespace)
else:
return overrides

View File

@ -0,0 +1,39 @@
#
# Copyright (c) 2018 Wind River Systems, Inc.
#
# 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 . import common
from . import openstack
LOG = logging.getLogger(__name__)
class MemcachedHelm(openstack.OpenstackBaseHelm):
"""Class to encapsulate helm operations for the memcached chart"""
CHART = constants.HELM_CHART_MEMCACHED
SUPPORTED_NAMESPACES = [
common.HELM_NS_OPENSTACK
]
def get_namespaces(self):
return self.SUPPORTED_NAMESPACES
def get_overrides(self, namespace=None):
overrides = {
common.HELM_NS_OPENSTACK: {
}
}
if namespace in self.SUPPORTED_NAMESPACES:
return overrides[namespace]
elif namespace:
raise exception.InvalidHelmNamespace(chart=self.CHART,
namespace=namespace)
else:
return overrides

View File

@ -0,0 +1,75 @@
#
# Copyright (c) 2018 Wind River Systems, Inc.
#
# 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 . import common
from . import openstack
LOG = logging.getLogger(__name__)
class NeutronHelm(openstack.OpenstackBaseHelm):
"""Class to encapsulate helm operations for the memcached chart"""
CHART = constants.HELM_CHART_NEUTRON
SUPPORTED_NAMESPACES = [
common.HELM_NS_OPENSTACK
]
def get_namespaces(self):
return self.SUPPORTED_NAMESPACES
def get_overrides(self, namespace=None):
overrides = {
common.HELM_NS_OPENSTACK: {
'network': {
'interface': {
'tunnel': 'docker0'
}
},
'conf': {
'neutron': {
'DEFAULT': {
'l3_ha': 'False',
'min_l3_agents_per_router': 1,
'max_l3_agents_per_router': 1,
'l3_ha_network_type': 'vxlan',
'dhcp_agents_per_network': 1
}
},
'plugins': {
'ml2_conf': {
'ml2_type_flat': {
'flat_networks': 'public'
}
},
'openvswitch_agent': {
'agent': {
'tunnel_types': 'vxlan'
},
'ovs': {
'bridge_mappings': 'public:br-ex'
}
},
'linuxbridge_agent': {
'linux_bridge': {
'bridge_mappings': 'public:br-ex'
}
}
}
}
}
}
if namespace in self.SUPPORTED_NAMESPACES:
return overrides[namespace]
elif namespace:
raise exception.InvalidHelmNamespace(chart=self.CHART,
namespace=namespace)
else:
return overrides

View File

@ -0,0 +1,42 @@
#
# Copyright (c) 2018 Wind River Systems, Inc.
#
# 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 . import common
from . import openstack
LOG = logging.getLogger(__name__)
class NfsProvisionerHelm(openstack.OpenstackBaseHelm):
"""Class to encapsulate helm operations for the nfs-provisioner chart"""
CHART = constants.HELM_CHART_NFS_PROVISIONER
SUPPORTED_NAMESPACES = [
common.HELM_NS_NFS
]
def get_namespaces(self):
return self.SUPPORTED_NAMESPACES
def get_overrides(self, namespace=None):
overrides = {
common.HELM_NS_NFS: {
'storageclass': {
'name': 'general'
}
}
}
if namespace in self.SUPPORTED_NAMESPACES:
return overrides[namespace]
elif namespace:
raise exception.InvalidHelmNamespace(chart=self.CHART,
namespace=namespace)
else:
return overrides

View File

@ -0,0 +1,49 @@
#
# Copyright (c) 2018 Wind River Systems, Inc.
#
# 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 . import common
from . import openstack
LOG = logging.getLogger(__name__)
class NovaHelm(openstack.OpenstackBaseHelm):
"""Class to encapsulate helm operations for the nova chart"""
CHART = constants.HELM_CHART_NOVA
SUPPORTED_NAMESPACES = [
common.HELM_NS_OPENSTACK
]
def get_namespaces(self):
return self.SUPPORTED_NAMESPACES
def get_overrides(self, namespace=None):
overrides = {
common.HELM_NS_OPENSTACK: {
'conf': {
'ceph': {
'enabled': 'false'
},
'nova': {
'libvirt': {
'virt_type': 'qemu'
}
}
}
}
}
if namespace in self.SUPPORTED_NAMESPACES:
return overrides[namespace]
elif namespace:
raise exception.InvalidHelmNamespace(chart=self.CHART,
namespace=namespace)
else:
return overrides

View File

@ -0,0 +1,13 @@
#
# Copyright (c) 2018 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
from . import base
class OpenstackBaseHelm(base.BaseHelm):
"""Class to encapsulate Openstack service operations for helm"""
pass

View File

@ -0,0 +1,39 @@
#
# Copyright (c) 2018 Wind River Systems, Inc.
#
# 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 . import common
from . import openstack
LOG = logging.getLogger(__name__)
class OpenvswitchHelm(openstack.OpenstackBaseHelm):
"""Class to encapsulate helm operations for the openvswitch chart"""
CHART = constants.HELM_CHART_OPENVSWITCH
SUPPORTED_NAMESPACES = [
common.HELM_NS_OPENSTACK
]
def get_namespaces(self):
return self.SUPPORTED_NAMESPACES
def get_overrides(self, namespace=None):
overrides = {
common.HELM_NS_OPENSTACK: {
}
}
if namespace in self.SUPPORTED_NAMESPACES:
return overrides[namespace]
elif namespace:
raise exception.InvalidHelmNamespace(chart=self.CHART,
namespace=namespace)
else:
return overrides

View File

@ -0,0 +1,44 @@
#
# Copyright (c) 2018 Wind River Systems, Inc.
#
# 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 . import common
from . import openstack
LOG = logging.getLogger(__name__)
class RabbitmqHelm(openstack.OpenstackBaseHelm):
"""Class to encapsulate helm operations for the rabbitmq chart"""
CHART = constants.HELM_CHART_RABBITMQ
SUPPORTED_NAMESPACES = [
common.HELM_NS_OPENSTACK
]
def get_namespaces(self):
return self.SUPPORTED_NAMESPACES
def get_overrides(self, namespace=None):
overrides = {
common.HELM_NS_OPENSTACK: {
'pod': {
'replicas': {
'server': 1
}
}
}
}
if namespace in self.SUPPORTED_NAMESPACES:
return overrides[namespace]
elif namespace:
raise exception.InvalidHelmNamespace(chart=self.CHART,
namespace=namespace)
else:
return overrides