Juju Charm - Keystone LDAP backend
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 

143 lines
4.8 KiB

#
# Copyright 2017 Canonical Ltd
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import charmhelpers.core as core
import charmhelpers.core.host as ch_host
import charmhelpers.core.hookenv as hookenv
import charmhelpers.contrib.openstack.templating as os_templating
import charmhelpers.contrib.openstack.utils as os_utils
import charms_openstack.charm
import charms_openstack.adapters
import os
# release detection is done via keystone package given that
# openstack-origin is not present in the subordinate charm
# see https://github.com/juju/charm-helpers/issues/83
import charmhelpers.core.unitdata as unitdata
from charms_openstack.charm.core import (
register_os_release_selector
)
OPENSTACK_RELEASE_KEY = 'charmers.openstack-release-version'
DOMAIN_CONF = "/etc/keystone/domains/keystone.{}.conf"
KEYSTONE_CONF_TEMPLATE = "keystone.conf"
@register_os_release_selector
def select_release():
"""Determine the release based on the keystone package version.
Note that this function caches the release after the first install so
that it doesn't need to keep going and getting it from the package
information.
"""
release_version = unitdata.kv().get(OPENSTACK_RELEASE_KEY, None)
if release_version is None:
release_version = os_utils.os_release('keystone')
unitdata.kv().set(OPENSTACK_RELEASE_KEY, release_version)
return release_version
class KeystoneLDAPConfigurationAdapter(
charms_openstack.adapters.ConfigurationAdapter):
'''Charm specific configuration adapter to deal with ldap
config flag parsing
'''
@property
def ldap_options(self):
return os_utils.config_flags_parser(
hookenv.config('ldap-config-flags')
)
class KeystoneLDAPCharm(charms_openstack.charm.OpenStackCharm):
# Internal name of charm
service_name = name = 'keystone-ldap'
# Package to derive application version from
version_package = 'keystone'
# First release supported
release = 'mitaka'
# List of packages to install for this charm
packages = ['python-ldappool']
configuration_class = KeystoneLDAPConfigurationAdapter
@property
def domain_name(self):
"""Domain name for the running application
:returns: string: containing the current domain name for the
application
"""
return hookenv.config('domain-name') or hookenv.service_name()
@staticmethod
def configuration_complete():
"""Determine whether sufficient configuration has been provided
to configure keystone for use with a LDAP backend
:returns: boolean indicating whether configuration is complete
"""
required_config = {
'ldap_server': hookenv.config('ldap-server'),
'ldap_user': hookenv.config('ldap-user'),
'ldap_password': hookenv.config('ldap-password'),
'ldap_suffix': hookenv.config('ldap-suffix'),
}
return all(required_config.values())
@property
def configuration_file(self):
"""Configuration file for domain configuration"""
return DOMAIN_CONF.format(self.domain_name)
def assess_status(self):
"""Determine the current application status for the charm"""
hookenv.application_version_set(self.application_version)
if not self.configuration_complete():
hookenv.status_set('blocked',
'LDAP configuration incomplete')
else:
hookenv.status_set('active',
'Unit is ready')
def render_config(self, restart_trigger):
"""Render the domain specific LDAP configuration for the application
"""
checksum = ch_host.file_hash(self.configuration_file)
core.templating.render(
source=KEYSTONE_CONF_TEMPLATE,
template_loader=os_templating.get_loader(
'templates/', self.release),
target=self.configuration_file,
context=self.adapters_instance)
if checksum != ch_host.file_hash(self.configuration_file):
restart_trigger()
def remove_config(self):
"""
Remove the domain-specific LDAP configuration file and trigger
keystone restart.
"""
if os.path.exists(self.configuration_file):
os.unlink(self.configuration_file)