Sync helpers.

This commit is contained in:
Adam Gandelman 2013-08-16 17:29:10 -07:00
parent 67d8ae7a7e
commit 406c38fdef
4 changed files with 170 additions and 18 deletions

View File

@ -97,12 +97,14 @@ def https():
return True
for r_id in relation_ids('identity-service'):
for unit in relation_list(r_id):
if None not in [
rel_state = [
relation_get('https_keystone', rid=r_id, unit=unit),
relation_get('ssl_cert', rid=r_id, unit=unit),
relation_get('ssl_key', rid=r_id, unit=unit),
relation_get('ca_cert', rid=r_id, unit=unit),
]:
]
# NOTE: works around (LP: #1203241)
if (None not in rel_state) and ('' not in rel_state):
return True
return False

View File

@ -6,6 +6,12 @@ from subprocess import (
check_call
)
from charmhelpers.core.host import (
apt_install,
filter_installed_packages,
)
from charmhelpers.core.hookenv import (
config,
local_unit,
@ -14,6 +20,8 @@ from charmhelpers.core.hookenv import (
relation_ids,
related_units,
unit_get,
unit_private_ip,
WARNING,
)
from charmhelpers.contrib.hahelpers.cluster import (
@ -29,6 +37,10 @@ from charmhelpers.contrib.hahelpers.apache import (
get_ca_cert,
)
from charmhelpers.contrib.openstack.neutron import (
neutron_plugin_attribute,
)
CA_CERT_PATH = '/usr/local/share/ca-certificates/keystone_juju_ca_cert.crt'
@ -57,26 +69,39 @@ class OSContextGenerator(object):
class SharedDBContext(OSContextGenerator):
interfaces = ['shared-db']
def __init__(self, database=None, user=None, relation_prefix=None):
'''
Allows inspecting relation for settings prefixed with relation_prefix.
This is useful for parsing access for multiple databases returned via
the shared-db interface (eg, nova_password, quantum_password)
'''
self.relation_prefix = relation_prefix
self.database = database
self.user = user
def __call__(self):
log('Generating template context for shared-db')
conf = config()
try:
database = conf['database']
username = conf['database-user']
except KeyError as e:
self.database = self.database or config('database')
self.user = self.user or config('database-user')
if None in [self.database, self.user]:
log('Could not generate shared_db context. '
'Missing required charm config options: %s.' % e)
'Missing required charm config options. '
'(database name and user)')
raise OSContextError
ctxt = {}
password_setting = 'password'
if self.relation_prefix:
password_setting = self.relation_prefix + '_password'
for rid in relation_ids('shared-db'):
for unit in related_units(rid):
passwd = relation_get(password_setting, rid=rid, unit=unit)
ctxt = {
'database_host': relation_get('db_host', rid=rid,
unit=unit),
'database': database,
'database_user': username,
'database_password': relation_get('password', rid=rid,
unit=unit)
'database': self.database,
'database_user': self.user,
'database_password': passwd,
}
if not context_complete(ctxt):
return {}
@ -207,7 +232,7 @@ class HAProxyContext(OSContextGenerator):
class ImageServiceContext(OSContextGenerator):
interfaces = ['image-servce']
interfaces = ['image-service']
def __call__(self):
'''
@ -292,3 +317,90 @@ class ApacheSSLContext(OSContextGenerator):
portmap = (int(ext_port), int(int_port))
ctxt['endpoints'].append(portmap)
return ctxt
class NeutronContext(object):
interfaces = []
@property
def plugin(self):
return None
@property
def network_manager(self):
return None
@property
def packages(self):
return neutron_plugin_attribute(
self.plugin, 'packages', self.network_manager)
@property
def neutron_security_groups(self):
return None
def _ensure_packages(self):
'''Install but do not upgrade required plugin packages'''
required = filter_installed_packages(self.packages)
if required:
apt_install(required, fatal=True)
def _save_flag_file(self):
if self.network_manager == 'quantum':
_file = '/etc/nova/quantum_plugin.conf'
else:
_file = '/etc/nova/neutron_plugin.conf'
with open(_file, 'wb') as out:
out.write(self.plugin + '\n')
def ovs_ctxt(self):
driver = neutron_plugin_attribute(self.plugin, 'driver',
self.network_manager)
ovs_ctxt = {
'core_plugin': driver,
'neutron_plugin': 'ovs',
'neutron_security_groups': self.neutron_security_groups,
'local_ip': unit_private_ip(),
}
return ovs_ctxt
def __call__(self):
self._ensure_packages()
if self.network_manager not in ['quantum', 'neutron']:
return {}
if not self.plugin:
return {}
ctxt = {'network_manager': self.network_manager}
if self.plugin == 'ovs':
ctxt.update(self.ovs_ctxt())
self._save_flag_file()
return ctxt
class OSConfigFlagContext(OSContextGenerator):
'''
Responsible adding user-defined config-flags in charm config to a
to a template context.
'''
def __call__(self):
config_flags = config('config-flags')
if not config_flags or config_flags in ['None', '']:
return {}
config_flags = config_flags.split(',')
flags = {}
for flag in config_flags:
if '=' not in flag:
log('Improperly formatted config-flag, expected k=v '
'got %s' % flag, level=WARNING)
continue
k, v = flag.split('=')
flags[k.strip()] = v
ctxt = {'user_config_flags': flags}
return ctxt

View File

@ -11,10 +11,10 @@ from charmhelpers.core.hookenv import (
from charmhelpers.contrib.openstack.utils import OPENSTACK_CODENAMES
try:
from jinja2 import FileSystemLoader, ChoiceLoader, Environment
from jinja2 import FileSystemLoader, ChoiceLoader, Environment, exceptions
except ImportError:
# python-jinja2 may not be installed yet, or we're running unittests.
FileSystemLoader = ChoiceLoader = Environment = None
FileSystemLoader = ChoiceLoader = Environment = exceptions = None
class OSConfigException(Exception):
@ -220,9 +220,24 @@ class OSConfigRenderer(object):
log('Config not registered: %s' % config_file, level=ERROR)
raise OSConfigException
ctxt = self.templates[config_file].context()
_tmpl = os.path.basename(config_file)
try:
template = self._get_template(_tmpl)
except exceptions.TemplateNotFound:
# if no template is found with basename, try looking for it
# using a munged full path, eg:
# /etc/apache2/apache2.conf -> etc_apache2_apache2.conf
_tmpl = '_'.join(config_file.split('/')[1:])
try:
template = self._get_template(_tmpl)
except exceptions.TemplateNotFound as e:
log('Could not load template from %s by %s or %s.' %
(self.templates_dir, os.path.basename(config_file), _tmpl),
level=ERROR)
raise e
log('Rendering from template: %s' % _tmpl, level=INFO)
template = self._get_template(_tmpl)
return template.render(ctxt)
def write(self, config_file):
@ -232,8 +247,12 @@ class OSConfigRenderer(object):
if config_file not in self.templates:
log('Config not registered: %s' % config_file, level=ERROR)
raise OSConfigException
_out = self.render(config_file)
with open(config_file, 'wb') as out:
out.write(self.render(config_file))
out.write(_out)
log('Wrote template %s.' % config_file, level=INFO)
def write_all(self):

View File

@ -163,6 +163,25 @@ def get_os_version_package(pkg, fatal=True):
#error_out(e)
os_rel = None
def os_release(package, base='essex'):
'''
Returns OpenStack release codename from a cached global.
If the codename can not be determined from either an installed package or
the installation source, the earliest release supported by the charm should
be returned.
'''
global os_rel
if os_rel:
return os_rel
os_rel = (get_os_codename_package(package, fatal=False) or
get_os_codename_install_source(config('openstack-origin')) or
base)
return os_rel
def import_key(keyid):
cmd = "apt-key adv --keyserver keyserver.ubuntu.com " \
"--recv-keys %s" % keyid