Add support for subordinate charms

These changes provide support for extending heat with
subordinate charms.

Change-Id: I9266390e1393bcf9c60fb294814100d6957320ae
Closes-Bug: #1626077
Closes-Bug: #1627703
This commit is contained in:
Ante Karamatic 2018-06-26 11:21:45 +02:00
parent a559903ba6
commit 4c9088b396
12 changed files with 234 additions and 3 deletions

View File

@ -0,0 +1 @@
heat_relations.py

View File

@ -0,0 +1 @@
heat_relations.py

View File

@ -13,7 +13,13 @@
# limitations under the License.
from charmhelpers.contrib.openstack import context
from charmhelpers.core.hookenv import config, leader_get
from charmhelpers.core.hookenv import (
config,
relation_ids,
related_units,
relation_get,
leader_get,
)
from charmhelpers.contrib.hahelpers.cluster import (
determine_apache_port,
determine_api_port,
@ -99,6 +105,37 @@ class HeatApacheSSLContext(context.ApacheSSLContext):
service_namespace = 'heat'
class HeatPluginContext(context.SubordinateConfigContext):
interfaces = 'heat-plugin-subordinate'
def __init__(self):
super(HeatPluginContext, self).__init__(
interface='heat-plugin-subordinate',
service='heat',
config_file='/etc/heat/heat.conf')
def __call__(self):
ctxt = super(HeatPluginContext, self).__call__()
defaults = {
'plugin-dirs': {
'templ_key': 'plugin_dirs',
'value': '/usr/lib64/heat,/usr/lib/heat',
},
}
for rid in relation_ids('heat-plugin-subordinate'):
for unit in related_units(rid):
rdata = relation_get(rid=rid, unit=unit)
for key in defaults.keys():
remote_value = rdata.get(key)
ctxt_key = defaults[key]['templ_key']
if remote_value:
ctxt[ctxt_key] = remote_value
else:
ctxt[ctxt_key] = defaults[key]['value']
return ctxt
return ctxt
class InstanceUserContext(context.OSContextGenerator):
def __call__(self):

View File

@ -429,6 +429,13 @@ def ha_changed():
identity_joined(rid=rid)
@hooks.hook('heat-plugin-subordinate-relation-joined',
'heat-plugin-subordinate-relation-changed')
@restart_on_change(restart_map(), stopstart=True)
def heat_plugin_subordinate_relation_joined(relid=None):
CONFIGS.write_all()
@hooks.hook('update-status')
@harden()
def update_status():

View File

@ -54,6 +54,7 @@ from heat_context import (
InstanceUserContext,
HeatApacheSSLContext,
HeatHAProxyContext,
HeatPluginContext,
)
TEMPLATES = 'templates/'
@ -108,6 +109,7 @@ CONFIG_FILES = OrderedDict([
HeatHAProxyContext(),
HeatSecurityContext(),
InstanceUserContext(),
HeatPluginContext(),
context.SyslogContext(),
context.LogLevelContext(),
context.WorkerConfigContext(),

View File

@ -28,6 +28,9 @@ requires:
scope: container
certificates:
interface: tls-certificates
heat-plugin-subordinate:
interface: heat-plugin-subordinate
scope: container
peers:
cluster:
interface: heat-ha

View File

@ -5,11 +5,20 @@ debug = {{ debug }}
log_dir = /var/log/heat
instance_user=ec2-user
instance_driver=heat.engine.nova
plugin_dirs=/usr/lib64/heat,/usr/lib/heat
{% if plugin_dirs -%}
plugin_dirs = {{ plugin_dirs }}
{% else -%}
plugin_dirs = /usr/lib64/heat,/usr/lib/heat
{% endif -%}
environment_dir=/etc/heat/environment.d
deferred_auth_method=password
host=heat
auth_encryption_key={{ encryption_key }}
{% if sections and 'DEFAULT' in sections -%}
{% for key, value in sections['DEFAULT'] -%}
{{ key }} = {{ value }}
{% endfor -%}
{% endif %}
{% if database_host -%}
# < Icehouse db config
@ -75,3 +84,12 @@ bind_port={{ api_cfn_listen_port }}
{% else -%}
bind_port=8000
{% endif %}
{% if sections -%}
{% for section in sections if section != 'DEFAULT' -%}
[{{ section }}]
{% for key, value in sections[section] -%}
{{ key }} = {{ value }}
{% endfor -%}
{% endfor -%}
{% endif %}

View File

@ -7,12 +7,22 @@ log_dir = /var/log/heat
# Not including instance_user at all results in 'ec2-user' being used
instance_user={{ instance_user }}
instance_driver=heat.engine.nova
plugin_dirs=/usr/lib64/heat,/usr/lib/heat
{% if plugin_dirs -%}
plugin_dirs = {{ plugin_dirs }}
{% else -%}
plugin_dirs = /usr/lib64/heat,/usr/lib/heat
{% endif -%}
environment_dir=/etc/heat/environment.d
deferred_auth_method=password
host=heat
auth_encryption_key={{ encryption_key }}
num_engine_workers = {{ workers }}
{% if sections and 'DEFAULT' in sections -%}
{% for key, value in sections['DEFAULT'] -%}
{{ key }} = {{ value }}
{% endfor -%}
{% endif %}
{% if user_config_flags -%}
{% for key, value in user_config_flags.items() -%}
{{ key }} = {{ value }}
@ -95,3 +105,12 @@ endpoint_type = internalURL
endpoint_type = publicURL
{%- endif %}
{% if sections -%}
{% for section in sections if section != 'DEFAULT' -%}
[{{ section }}]
{% for key, value in sections[section] -%}
{{ key }} = {{ value }}
{% endfor -%}
{% endfor -%}
{% endif %}

View File

@ -5,7 +5,11 @@ verbose = {{ verbose }}
log_dir = /var/log/heat
instance_user = {{ instance_user }}
instance_driver = heat.engine.nova
{% if plugin_dirs -%}
plugin_dirs = {{ plugin_dirs }}
{% else -%}
plugin_dirs = /usr/lib64/heat,/usr/lib/heat
{% endif -%}
environment_dir = /etc/heat/environment.d
host = heat
auth_encryption_key = {{ encryption_key }}
@ -14,6 +18,12 @@ stack_domain_admin = heat_domain_admin
stack_domain_admin_password = {{ heat_domain_admin_passwd }}
stack_user_domain_name = heat
num_engine_workers = {{ workers }}
{% if sections and 'DEFAULT' in sections -%}
{% for key, value in sections['DEFAULT'] -%}
{{ key }} = {{ value }}
{% endfor -%}
{% endif %}
{% if user_config_flags -%}
{% for key, value in user_config_flags.items() -%}
{{ key }} = {{ value }}
@ -66,3 +76,12 @@ workers = {{ workers }}
[clients]
endpoint_type = internalURL
{%- endif %}
{% if sections -%}
{% for section in sections if section != 'DEFAULT' -%}
[{{ section }}]
{% for key, value in sections[section] -%}
{{ key }} = {{ value }}
{% endfor -%}
{% endfor -%}
{% endif %}

View File

@ -5,7 +5,11 @@ verbose = {{ verbose }}
log_dir = /var/log/heat
instance_user = {{ instance_user }}
instance_driver = heat.engine.nova
{% if plugin_dirs -%}
plugin_dirs = {{ plugin_dirs }}
{% else -%}
plugin_dirs = /usr/lib64/heat,/usr/lib/heat
{% endif -%}
environment_dir = /etc/heat/environment.d
host = heat
auth_encryption_key = {{ encryption_key }}
@ -14,6 +18,12 @@ stack_domain_admin = heat_domain_admin
stack_domain_admin_password = {{ heat_domain_admin_passwd }}
stack_user_domain_name = heat
num_engine_workers = {{ workers }}
{% if sections and 'DEFAULT' in sections -%}
{% for key, value in sections['DEFAULT'] -%}
{{ key }} = {{ value }}
{% endfor -%}
{% endif %}
{% if user_config_flags -%}
{% for key, value in user_config_flags.items() -%}
{{ key }} = {{ value }}
@ -81,3 +91,12 @@ endpoint_type = internalURL
{%- endif %}
{% include "section-oslo-middleware" %}
{% if sections -%}
{% for section in sections if section != 'DEFAULT' -%}
[{{ section }}]
{% for key, value in sections[section] -%}
{{ key }} = {{ value }}
{% endfor -%}
{% endfor -%}
{% endif %}

View File

@ -5,7 +5,11 @@ verbose = {{ verbose }}
log_dir = /var/log/heat
instance_user = {{ instance_user }}
instance_driver = heat.engine.nova
{% if plugin_dirs -%}
plugin_dirs = {{ plugin_dirs }}
{% else -%}
plugin_dirs = /usr/lib64/heat,/usr/lib/heat
{% endif -%}
environment_dir = /etc/heat/environment.d
host = heat
auth_encryption_key = {{ encryption_key }}
@ -14,6 +18,12 @@ stack_domain_admin = heat_domain_admin
stack_domain_admin_password = {{ heat_domain_admin_passwd }}
stack_user_domain_name = heat
num_engine_workers = {{ workers }}
{% if sections and 'DEFAULT' in sections -%}
{% for key, value in sections['DEFAULT'] -%}
{{ key }} = {{ value }}
{% endfor -%}
{% endif %}
{% if user_config_flags -%}
{% for key, value in user_config_flags.items() -%}
{{ key }} = {{ value }}
@ -77,3 +87,12 @@ endpoint_type = publicURL
{%- endif %}
{% include "section-oslo-middleware" %}
{% if sections -%}
{% for section in sections if section != 'DEFAULT' -%}
[{{ section }}]
{% for key, value in sections[section] -%}
{{ key }} = {{ value }}
{% endfor -%}
{% endfor -%}
{% endif %}

View File

@ -12,7 +12,9 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import charmhelpers
import heat_context
import json
from mock import patch
from test_utils import CharmTestCase
@ -21,6 +23,9 @@ TO_PATCH = [
'generate_ec2_tokens',
'config',
'leader_get',
'relation_get',
'relation_ids',
'related_units',
]
@ -66,3 +71,84 @@ class TestHeatContext(CharmTestCase):
self.assertEqual(
heat_context.HeatIdentityServiceContext()(), final_result)
class HeatPluginContextTest(CharmTestCase):
def setUp(self):
super(HeatPluginContextTest, self).setUp(heat_context, TO_PATCH)
self.relation_get.side_effect = self.test_relation.get
def tearDown(self):
super(HeatPluginContextTest, self).tearDown()
def test_init(self):
heatp_ctxt = heat_context.HeatPluginContext()
self.assertEqual(
heatp_ctxt.interfaces,
['heat-plugin-subordinate']
)
self.assertEqual(heatp_ctxt.services, ['heat'])
self.assertEqual(
heatp_ctxt.config_file,
'/etc/heat/heat.conf'
)
@patch.object(charmhelpers.contrib.openstack.context, 'log')
@patch.object(charmhelpers.contrib.openstack.context, 'relation_get')
@patch.object(charmhelpers.contrib.openstack.context, 'related_units')
@patch.object(charmhelpers.contrib.openstack.context, 'relation_ids')
def ctxt_check(self, rel_settings, expect, _rids, _runits, _rget, _log):
self.test_relation.set(rel_settings)
_runits.return_value = ['unit1']
_rids.return_value = ['rid2']
_rget.side_effect = self.test_relation.get
self.relation_ids.return_value = ['rid2']
self.related_units.return_value = ['unit1']
heatp_ctxt = heat_context.HeatPluginContext()()
self.assertEqual(heatp_ctxt, expect)
def test_defaults(self):
self.ctxt_check(
{},
{
'plugin_dirs': '/usr/lib64/heat,/usr/lib/heat',
'sections': {},
}
)
def test_overrides(self):
self.ctxt_check(
{'plugin-dirs': '/usr/lib64/heat,/usr/lib/heat,/usr/local/lib'},
{
'plugin_dirs': '/usr/lib64/heat,/usr/lib/heat,/usr/local/lib',
'sections': {},
}
)
def test_subordinateconfig(self):
principle_config = {
"heat": {
"/etc/heat/heat.conf": {
"sections": {
'DEFAULT': [
('heatboost', True)
],
'heatplugin': [
('superkey', 'supervalue')
],
}
}
}
}
self.ctxt_check(
{
'plugin-dirs': '/usr/lib64/heat,/usr/lib/heat,/usr/local/lib',
'subordinate_configuration': json.dumps(principle_config)
},
{
'plugin_dirs': '/usr/lib64/heat,/usr/lib/heat,/usr/local/lib',
'sections': {u'DEFAULT': [[u'heatboost', True]],
u'heatplugin': [[u'superkey', u'supervalue']]},
}
)