charm-swift-proxy/lib/swift_context.py

236 lines
8.1 KiB
Python

import os
import uuid
from charmhelpers.core.hookenv import (
config,
log,
relation_ids,
related_units,
relation_get,
unit_get,
service_name,
leader_get,
)
from charmhelpers.contrib.openstack.context import (
OSContextGenerator,
ApacheSSLContext as SSLContext,
context_complete,
IdentityServiceContext,
)
from charmhelpers.contrib.hahelpers.cluster import (
determine_api_port,
determine_apache_port,
)
from charmhelpers.contrib.network.ip import (
format_ipv6_addr,
get_ipv6_addr,
)
from charmhelpers.contrib.openstack.utils import get_host_ip
SWIFT_HASH_FILE = '/var/lib/juju/swift-hash-path.conf'
WWW_DIR = '/var/www/swift-rings'
class HAProxyContext(OSContextGenerator):
interfaces = ['cluster']
def __call__(self):
"""Extends the main charmhelpers HAProxyContext with a port mapping
specific to this charm.
Also used to extend cinder.conf context with correct api_listening_port
"""
haproxy_port = config('bind-port')
api_port = determine_apache_port(config('bind-port'),
singlenode_mode=True)
ctxt = {
'service_ports': {'swift_api': [haproxy_port, api_port]},
}
return ctxt
class ApacheSSLContext(SSLContext):
interfaces = ['https']
service_namespace = 'swift'
# We make this a property so that we avoid import-time
# dependencies on config()
@property
def external_ports(self):
return [config('bind-port')]
class SwiftRingContext(OSContextGenerator):
def __call__(self):
allowed_hosts = []
for relid in relation_ids('swift-storage'):
for unit in related_units(relid):
host = relation_get('private-address', unit, relid)
if config('prefer-ipv6'):
host_ip = get_ipv6_addr(exc_list=[config('vip')])[0]
else:
host_ip = get_host_ip(host)
allowed_hosts.append(host_ip)
ctxt = {
'www_dir': WWW_DIR,
'allowed_hosts': allowed_hosts
}
return ctxt
class SwiftIdentityContext(OSContextGenerator):
interfaces = ['identity-service']
def __call__(self):
bind_port = config('bind-port')
workers = config('workers')
if workers == 0:
import multiprocessing
workers = multiprocessing.cpu_count()
if config('prefer-ipv6'):
proxy_ip = '[%s]' % get_ipv6_addr(exc_list=[config('vip')])[0]
memcached_ip = 'ip6-localhost'
else:
proxy_ip = get_host_ip(unit_get('private-address'))
memcached_ip = get_host_ip(unit_get('private-address'))
ctxt = {
'proxy_ip': proxy_ip,
'memcached_ip': memcached_ip,
'bind_port': determine_api_port(bind_port, singlenode_mode=True),
'workers': workers,
'operator_roles': config('operator-roles'),
'delay_auth_decision': config('delay-auth-decision'),
'node_timeout': config('node-timeout'),
'recoverable_node_timeout': config('recoverable-node-timeout'),
'log_headers': config('log-headers'),
}
admin_key = leader_get('swauth-admin-key')
if admin_key is not None:
ctxt['swauth_admin_key'] = admin_key
if config('debug'):
ctxt['log_level'] = 'DEBUG'
else:
ctxt['log_level'] = 'INFO'
# Instead of duplicating code lets use charm-helpers to set signing_dir
# TODO(hopem): refactor this context handler to use charm-helpers
# code.
_ctxt = IdentityServiceContext(service='swift', service_user='swift')()
signing_dir = _ctxt.get('signing_dir')
if signing_dir:
ctxt['signing_dir'] = signing_dir
ctxt['ssl'] = False
auth_type = config('auth-type')
ctxt['auth_type'] = auth_type
auth_host = config('keystone-auth-host')
admin_user = config('keystone-admin-user')
admin_password = config('keystone-admin-user')
if (auth_type == 'keystone' and auth_host and
admin_user and admin_password):
log('Using user-specified Keystone configuration.')
ks_auth = {
'auth_type': 'keystone',
'auth_protocol': config('keystone-auth-protocol'),
'keystone_host': auth_host,
'auth_port': config('keystone-auth-port'),
'service_user': admin_user,
'service_password': admin_password,
'service_tenant': config('keystone-admin-tenant-name'),
}
ctxt.update(ks_auth)
for relid in relation_ids('identity-service'):
log('Using Keystone configuration from identity-service.')
for unit in related_units(relid):
ks_auth = {
'auth_type': 'keystone',
'auth_protocol': relation_get('auth_protocol',
unit, relid) or 'http',
'service_protocol': relation_get('service_protocol',
unit, relid) or 'http',
'keystone_host': relation_get('auth_host',
unit, relid),
'service_host': relation_get('service_host',
unit, relid),
'auth_port': relation_get('auth_port',
unit, relid),
'service_user': relation_get('service_username',
unit, relid),
'service_password': relation_get('service_password',
unit, relid),
'service_tenant': relation_get('service_tenant',
unit, relid),
'service_port': relation_get('service_port',
unit, relid),
'admin_token': relation_get('admin_token',
unit, relid),
'api_version': relation_get('api_version',
unit, relid) or '2',
}
if ks_auth['api_version'] == '3':
ks_auth['admin_domain_id'] = relation_get(
'admin_domain_id', unit, relid)
ks_auth['service_tenant_id'] = relation_get(
'service_tenant_id', unit, relid)
if context_complete(ks_auth):
ctxt.update(ks_auth)
if config('prefer-ipv6'):
for key in ['keystone_host', 'service_host']:
host = ctxt.get(key)
if host:
ctxt[key] = format_ipv6_addr(host)
return ctxt
class MemcachedContext(OSContextGenerator):
def __call__(self):
ctxt = {}
if config('prefer-ipv6'):
ctxt['memcached_ip'] = 'ip6-localhost'
else:
ctxt['memcached_ip'] = get_host_ip(unit_get('private-address'))
return ctxt
def get_swift_hash():
if os.path.isfile(SWIFT_HASH_FILE):
with open(SWIFT_HASH_FILE, 'r') as hashfile:
swift_hash = hashfile.read().strip()
elif config('swift-hash'):
swift_hash = config('swift-hash')
with open(SWIFT_HASH_FILE, 'w') as hashfile:
hashfile.write(swift_hash)
else:
model_uuid = os.environ.get("JUJU_ENV_UUID",
os.environ.get("JUJU_MODEL_UUID"))
swift_hash = str(uuid.uuid3(uuid.UUID(model_uuid),
service_name()))
with open(SWIFT_HASH_FILE, 'w') as hashfile:
hashfile.write(swift_hash)
return swift_hash
class SwiftHashContext(OSContextGenerator):
def __call__(self):
ctxt = {
'swift_hash': get_swift_hash()
}
return ctxt