Merge "Snap install OpenStack in Charms"
This commit is contained in:
commit
2359950179
|
@ -12,3 +12,4 @@ xenial/
|
|||
func-results.json
|
||||
.local
|
||||
__pycache__
|
||||
.stestr
|
||||
|
|
|
@ -802,8 +802,9 @@ class ApacheSSLContext(OSContextGenerator):
|
|||
else:
|
||||
# Expect cert/key provided in config (currently assumed that ca
|
||||
# uses ip for cn)
|
||||
cn = resolve_address(endpoint_type=INTERNAL)
|
||||
self.configure_cert(cn)
|
||||
for net_type in (INTERNAL, ADMIN, PUBLIC):
|
||||
cn = resolve_address(endpoint_type=net_type)
|
||||
self.configure_cert(cn)
|
||||
|
||||
addresses = self.get_network_addresses()
|
||||
for address, endpoint in addresses:
|
||||
|
|
|
@ -95,7 +95,7 @@ from charmhelpers.fetch import (
|
|||
from charmhelpers.fetch.snap import (
|
||||
snap_install,
|
||||
snap_refresh,
|
||||
SNAP_CHANNELS,
|
||||
valid_snap_channel,
|
||||
)
|
||||
|
||||
from charmhelpers.contrib.storage.linux.utils import is_block_device, zap_disk
|
||||
|
@ -579,6 +579,9 @@ def configure_installation_source(source_plus_key):
|
|||
Note that the behaviour on error is to log the error to the juju log and
|
||||
then call sys.exit(1).
|
||||
"""
|
||||
if source_plus_key.startswith('snap'):
|
||||
# Do nothing for snap installs
|
||||
return
|
||||
# extract the key if there is one, denoted by a '|' in the rel
|
||||
source, key = get_source_and_pgp_key(source_plus_key)
|
||||
|
||||
|
@ -2048,7 +2051,7 @@ def update_json_file(filename, items):
|
|||
def snap_install_requested():
|
||||
""" Determine if installing from snaps
|
||||
|
||||
If openstack-origin is of the form snap:channel-series-release
|
||||
If openstack-origin is of the form snap:track/channel
|
||||
and channel is in SNAPS_CHANNELS return True.
|
||||
"""
|
||||
origin = config('openstack-origin') or ""
|
||||
|
@ -2056,10 +2059,12 @@ def snap_install_requested():
|
|||
return False
|
||||
|
||||
_src = origin[5:]
|
||||
channel, series, release = _src.split('-')
|
||||
if channel.lower() in SNAP_CHANNELS:
|
||||
return True
|
||||
return False
|
||||
if '/' in _src:
|
||||
_track, channel = _src.split('/')
|
||||
else:
|
||||
# Hanlde snap:track with no channel
|
||||
channel = 'stable'
|
||||
return valid_snap_channel(channel)
|
||||
|
||||
|
||||
def get_snaps_install_info_from_origin(snaps, src, mode='classic'):
|
||||
|
@ -2067,7 +2072,7 @@ def get_snaps_install_info_from_origin(snaps, src, mode='classic'):
|
|||
|
||||
@param snaps: List of snaps
|
||||
@param src: String of openstack-origin or source of the form
|
||||
snap:channel-series-track
|
||||
snap:track/channel
|
||||
@param mode: String classic, devmode or jailmode
|
||||
@returns: Dictionary of snaps with channels and modes
|
||||
"""
|
||||
|
@ -2077,8 +2082,7 @@ def get_snaps_install_info_from_origin(snaps, src, mode='classic'):
|
|||
return {}
|
||||
|
||||
_src = src[5:]
|
||||
_channel, _series, _release = _src.split('-')
|
||||
channel = '--channel={}/{}'.format(_release, _channel)
|
||||
channel = '--channel={}'.format(_src)
|
||||
|
||||
return {snap: {'channel': channel, 'mode': mode}
|
||||
for snap in snaps}
|
||||
|
@ -2090,8 +2094,8 @@ def install_os_snaps(snaps, refresh=False):
|
|||
@param snaps: Dictionary of snaps with channels and modes of the form:
|
||||
{'snap_name': {'channel': 'snap_channel',
|
||||
'mode': 'snap_mode'}}
|
||||
Where channel a snapstore channel and mode is --classic, --devmode or
|
||||
--jailmode.
|
||||
Where channel is a snapstore channel and mode is --classic, --devmode
|
||||
or --jailmode.
|
||||
@param post_snap_install: Callback function to run after snaps have been
|
||||
installed
|
||||
"""
|
||||
|
|
|
@ -41,6 +41,10 @@ class CouldNotAcquireLockException(Exception):
|
|||
pass
|
||||
|
||||
|
||||
class InvalidSnapChannel(Exception):
|
||||
pass
|
||||
|
||||
|
||||
def _snap_exec(commands):
|
||||
"""
|
||||
Execute snap commands.
|
||||
|
@ -132,3 +136,15 @@ def snap_refresh(packages, *flags):
|
|||
|
||||
log(message, level='INFO')
|
||||
return _snap_exec(['refresh'] + flags + packages)
|
||||
|
||||
|
||||
def valid_snap_channel(channel):
|
||||
""" Validate snap channel exists
|
||||
|
||||
:raises InvalidSnapChannel: When channel does not exist
|
||||
:return: Boolean
|
||||
"""
|
||||
if channel.lower() in SNAP_CHANNELS:
|
||||
return True
|
||||
else:
|
||||
raise InvalidSnapChannel("Invalid Snap Channel: {}".format(channel))
|
||||
|
|
|
@ -30,6 +30,7 @@ from charmhelpers.contrib.hahelpers.cluster import (
|
|||
determine_apache_port,
|
||||
determine_api_port,
|
||||
is_elected_leader,
|
||||
https,
|
||||
)
|
||||
|
||||
from charmhelpers.core.hookenv import (
|
||||
|
@ -56,11 +57,90 @@ def is_cert_provided_in_config():
|
|||
return bool(ca and cert and key)
|
||||
|
||||
|
||||
class ApacheSSLContext(context.ApacheSSLContext):
|
||||
class SSLContext(context.ApacheSSLContext):
|
||||
|
||||
def configure_cert(self, cn):
|
||||
from keystone_utils import (
|
||||
SSH_USER,
|
||||
get_ca,
|
||||
ensure_permissions,
|
||||
is_ssl_cert_master,
|
||||
KEYSTONE_USER,
|
||||
)
|
||||
|
||||
# Ensure ssl dir exists whether master or not
|
||||
perms = 0o775
|
||||
mkdir(path=self.ssl_dir, owner=SSH_USER, group=KEYSTONE_USER,
|
||||
perms=perms)
|
||||
# Ensure accessible by keystone ssh user and group (for sync)
|
||||
ensure_permissions(self.ssl_dir, user=SSH_USER, group=KEYSTONE_USER,
|
||||
perms=perms)
|
||||
|
||||
if not is_cert_provided_in_config() and not is_ssl_cert_master():
|
||||
log("Not ssl-cert-master - skipping apache cert config until "
|
||||
"master is elected", level=INFO)
|
||||
return
|
||||
|
||||
log("Creating apache ssl certs in %s" % (self.ssl_dir), level=INFO)
|
||||
|
||||
cert = config('ssl_cert')
|
||||
key = config('ssl_key')
|
||||
|
||||
if not (cert and key):
|
||||
ca = get_ca(user=SSH_USER)
|
||||
cert, key = ca.get_cert_and_key(common_name=cn)
|
||||
else:
|
||||
cert = b64decode(cert)
|
||||
key = b64decode(key)
|
||||
|
||||
write_file(path=os.path.join(self.ssl_dir, 'cert_{}'.format(cn)),
|
||||
content=cert, owner=SSH_USER, group=KEYSTONE_USER,
|
||||
perms=0o644)
|
||||
write_file(path=os.path.join(self.ssl_dir, 'key_{}'.format(cn)),
|
||||
content=key, owner=SSH_USER, group=KEYSTONE_USER,
|
||||
perms=0o644)
|
||||
|
||||
def configure_ca(self):
|
||||
from keystone_utils import (
|
||||
SSH_USER,
|
||||
get_ca,
|
||||
ensure_permissions,
|
||||
is_ssl_cert_master,
|
||||
KEYSTONE_USER,
|
||||
)
|
||||
|
||||
if not is_cert_provided_in_config() and not is_ssl_cert_master():
|
||||
log("Not ssl-cert-master - skipping apache ca config until "
|
||||
"master is elected", level=INFO)
|
||||
return
|
||||
|
||||
ca_cert = config('ssl_ca')
|
||||
if ca_cert is None:
|
||||
ca = get_ca(user=SSH_USER)
|
||||
ca_cert = ca.get_ca_bundle()
|
||||
else:
|
||||
ca_cert = b64decode(ca_cert)
|
||||
|
||||
# Ensure accessible by keystone ssh user and group (unison)
|
||||
install_ca_cert(ca_cert)
|
||||
ensure_permissions(CA_CERT_PATH, user=SSH_USER, group=KEYSTONE_USER,
|
||||
perms=0o0644)
|
||||
|
||||
def canonical_names(self):
|
||||
addresses = self.get_network_addresses()
|
||||
addrs = []
|
||||
for address, endpoint in addresses:
|
||||
addrs.append(endpoint)
|
||||
|
||||
return list(set(addrs))
|
||||
|
||||
|
||||
class ApacheSSLContext(SSLContext):
|
||||
|
||||
interfaces = ['https']
|
||||
external_ports = []
|
||||
service_namespace = 'keystone'
|
||||
ssl_dir = os.path.join('/etc/apache2/ssl/', service_namespace)
|
||||
|
||||
def __call__(self):
|
||||
# late import to work around circular dependency
|
||||
|
@ -69,9 +149,7 @@ class ApacheSSLContext(context.ApacheSSLContext):
|
|||
update_hash_from_path,
|
||||
)
|
||||
|
||||
ssl_paths = [CA_CERT_PATH,
|
||||
os.path.join('/etc/apache2/ssl/',
|
||||
self.service_namespace)]
|
||||
ssl_paths = [CA_CERT_PATH, self.ssl_dir]
|
||||
|
||||
self.external_ports = determine_ports()
|
||||
before = hashlib.sha256()
|
||||
|
@ -90,76 +168,75 @@ class ApacheSSLContext(context.ApacheSSLContext):
|
|||
|
||||
return ret
|
||||
|
||||
def configure_cert(self, cn):
|
||||
|
||||
class NginxSSLContext(SSLContext):
|
||||
|
||||
interfaces = ['https']
|
||||
external_ports = []
|
||||
service_namespace = 'keystone'
|
||||
ssl_dir = ('/var/snap/{}/common/lib/juju_ssl/{}/'
|
||||
''.format(service_namespace, service_namespace))
|
||||
|
||||
def __call__(self):
|
||||
# late import to work around circular dependency
|
||||
from keystone_utils import (
|
||||
SSH_USER,
|
||||
get_ca,
|
||||
ensure_permissions,
|
||||
is_ssl_cert_master,
|
||||
determine_ports,
|
||||
update_hash_from_path,
|
||||
APACHE_SSL_DIR
|
||||
)
|
||||
|
||||
# Ensure ssl dir exists whether master or not
|
||||
ssl_dir = os.path.join('/etc/apache2/ssl/', self.service_namespace)
|
||||
perms = 0o755
|
||||
mkdir(path=ssl_dir, owner=SSH_USER, group='keystone', perms=perms)
|
||||
# Ensure accessible by keystone ssh user and group (for sync)
|
||||
ensure_permissions(ssl_dir, user=SSH_USER, group='keystone',
|
||||
perms=perms)
|
||||
ssl_paths = [CA_CERT_PATH, APACHE_SSL_DIR]
|
||||
|
||||
if not is_cert_provided_in_config() and not is_ssl_cert_master():
|
||||
log("Not ssl-cert-master - skipping apache cert config until "
|
||||
"master is elected", level=INFO)
|
||||
return
|
||||
self.external_ports = determine_ports()
|
||||
before = hashlib.sha256()
|
||||
for path in ssl_paths:
|
||||
update_hash_from_path(before, path)
|
||||
|
||||
log("Creating apache ssl certs in %s" % (ssl_dir), level=INFO)
|
||||
ret = super(NginxSSLContext, self).__call__()
|
||||
if not ret:
|
||||
log("SSL not used", level='DEBUG')
|
||||
return {}
|
||||
|
||||
cert = config('ssl_cert')
|
||||
key = config('ssl_key')
|
||||
after = hashlib.sha256()
|
||||
for path in ssl_paths:
|
||||
update_hash_from_path(after, path)
|
||||
|
||||
if not (cert and key):
|
||||
ca = get_ca(user=SSH_USER)
|
||||
cert, key = ca.get_cert_and_key(common_name=cn)
|
||||
else:
|
||||
cert = b64decode(cert)
|
||||
key = b64decode(key)
|
||||
# Ensure that Nginx is restarted if these change
|
||||
if before.hexdigest() != after.hexdigest():
|
||||
service_restart('snap.keystone.nginx')
|
||||
|
||||
write_file(path=os.path.join(ssl_dir, 'cert_{}'.format(cn)),
|
||||
content=cert, owner=SSH_USER, group='keystone', perms=0o644)
|
||||
write_file(path=os.path.join(ssl_dir, 'key_{}'.format(cn)),
|
||||
content=key, owner=SSH_USER, group='keystone', perms=0o644)
|
||||
# Transform for use by Nginx
|
||||
"""
|
||||
{'endpoints': [(u'10.5.0.30', u'10.5.0.30', 4990, 4980),
|
||||
(u'10.5.0.30', u'10.5.0.30', 35347, 35337)],
|
||||
'ext_ports': [4990, 35347],
|
||||
'namespace': 'keystone'}
|
||||
"""
|
||||
|
||||
def configure_ca(self):
|
||||
from keystone_utils import (
|
||||
SSH_USER,
|
||||
get_ca,
|
||||
ensure_permissions,
|
||||
is_ssl_cert_master,
|
||||
)
|
||||
nginx_ret = {}
|
||||
nginx_ret['ssl'] = https()
|
||||
nginx_ret['namespace'] = self.service_namespace
|
||||
endpoints = {}
|
||||
for ep in ret['endpoints']:
|
||||
int_address, address, ext, internal = ep
|
||||
if ext <= 5000:
|
||||
endpoints['public'] = {
|
||||
'socket': 'public',
|
||||
'address': address,
|
||||
'ext': ext}
|
||||
elif ext >= 35337:
|
||||
endpoints['admin'] = {
|
||||
'socket': 'admin',
|
||||
'address': address,
|
||||
'ext': ext}
|
||||
else:
|
||||
log("Unrecognized internal port", level='ERROR')
|
||||
nginx_ret['endpoints'] = endpoints
|
||||
|
||||
if not is_cert_provided_in_config() and not is_ssl_cert_master():
|
||||
log("Not ssl-cert-master - skipping apache ca config until "
|
||||
"master is elected", level=INFO)
|
||||
return
|
||||
return nginx_ret
|
||||
|
||||
ca_cert = config('ssl_ca')
|
||||
if ca_cert is None:
|
||||
ca = get_ca(user=SSH_USER)
|
||||
ca_cert = ca.get_ca_bundle()
|
||||
else:
|
||||
ca_cert = b64decode(ca_cert)
|
||||
|
||||
# Ensure accessible by keystone ssh user and group (unison)
|
||||
install_ca_cert(ca_cert)
|
||||
ensure_permissions(CA_CERT_PATH, user=SSH_USER, group='keystone',
|
||||
perms=0o0644)
|
||||
|
||||
def canonical_names(self):
|
||||
addresses = self.get_network_addresses()
|
||||
addrs = []
|
||||
for address, endpoint in addresses:
|
||||
addrs.append(endpoint)
|
||||
|
||||
return list(set(addrs))
|
||||
def enable_modules(self):
|
||||
return
|
||||
|
||||
|
||||
class HAProxyContext(context.HAProxyContext):
|
||||
|
@ -207,6 +284,7 @@ class KeystoneContext(context.OSContextGenerator):
|
|||
from keystone_utils import (
|
||||
api_port, set_admin_token, endpoint_url, resolve_address,
|
||||
PUBLIC, ADMIN, PKI_CERTS_DIR, ensure_pki_cert_paths, ADMIN_DOMAIN,
|
||||
snap_install_requested,
|
||||
)
|
||||
ctxt = {}
|
||||
ctxt['token'] = set_admin_token(config('admin-token'))
|
||||
|
@ -271,12 +349,27 @@ class KeystoneContext(context.OSContextGenerator):
|
|||
resolve_address(ADMIN),
|
||||
api_port('keystone-admin')).replace('v2.0', '')
|
||||
|
||||
if snap_install_requested():
|
||||
ctxt['domain_config_dir'] = (
|
||||
'/var/snap/keystone/common/etc/keystone/domains')
|
||||
ctxt['log_config'] = (
|
||||
'/var/snap/keystone/common/etc/keystone/logging.conf')
|
||||
ctxt['paste_config_file'] = (
|
||||
'/var/snap/keystone/common/etc/keystone/keystone-paste.ini')
|
||||
else:
|
||||
ctxt['domain_config_dir'] = '/etc/keystone/domains'
|
||||
ctxt['log_config'] = ('/etc/keystone/logging.conf')
|
||||
ctxt['paste_config_file'] = '/etc/keystone/keystone-paste.ini'
|
||||
|
||||
return ctxt
|
||||
|
||||
|
||||
class KeystoneLoggingContext(context.OSContextGenerator):
|
||||
|
||||
def __call__(self):
|
||||
from keystone_utils import (
|
||||
snap_install_requested,
|
||||
)
|
||||
ctxt = {}
|
||||
debug = config('debug')
|
||||
if debug:
|
||||
|
@ -289,6 +382,11 @@ class KeystoneLoggingContext(context.OSContextGenerator):
|
|||
log("log-level must be one of the following states "
|
||||
"(WARNING, INFO, DEBUG, ERROR) keeping the current state.")
|
||||
ctxt['log_level'] = None
|
||||
if snap_install_requested():
|
||||
ctxt['log_file'] = (
|
||||
'/var/snap/keystone/common/log/keystone.log')
|
||||
else:
|
||||
ctxt['log_file'] = '/var/log/keystone/keystone.log'
|
||||
|
||||
return ctxt
|
||||
|
||||
|
|
|
@ -71,6 +71,9 @@ from charmhelpers.contrib.openstack.utils import (
|
|||
pausable_restart_on_change as restart_on_change,
|
||||
is_unit_paused_set,
|
||||
CompareOpenStackReleases,
|
||||
snap_install_requested,
|
||||
install_os_snaps,
|
||||
get_snaps_install_info_from_origin,
|
||||
)
|
||||
|
||||
from keystone_utils import (
|
||||
|
@ -84,12 +87,14 @@ from keystone_utils import (
|
|||
git_install,
|
||||
migrate_database,
|
||||
save_script_rc,
|
||||
post_snap_install,
|
||||
synchronize_ca_if_changed,
|
||||
register_configs,
|
||||
restart_map,
|
||||
services,
|
||||
CLUSTER_RES,
|
||||
KEYSTONE_CONF,
|
||||
KEYSTONE_USER,
|
||||
POLICY_JSON,
|
||||
TOKEN_FLUSH_CRON_FILE,
|
||||
SSH_USER,
|
||||
|
@ -170,20 +175,32 @@ def install():
|
|||
status_set('maintenance', 'Installing apt packages')
|
||||
apt_update()
|
||||
apt_install(determine_packages(), fatal=True)
|
||||
# unconfigured keystone service will prevent start of haproxy in some
|
||||
# circumstances. make sure haproxy runs. LP #1648396
|
||||
service_stop('keystone')
|
||||
service_start('haproxy')
|
||||
if run_in_apache():
|
||||
disable_unused_apache_sites()
|
||||
if not git_install_requested():
|
||||
service_pause('keystone')
|
||||
|
||||
if snap_install_requested():
|
||||
status_set('maintenance', 'Installing keystone snap')
|
||||
# NOTE(thedac) Setting devmode until LP#1719636 is fixed
|
||||
install_os_snaps(
|
||||
get_snaps_install_info_from_origin(
|
||||
['keystone'],
|
||||
config('openstack-origin'),
|
||||
mode='devmode'))
|
||||
post_snap_install()
|
||||
service_stop('snap.keystone.*')
|
||||
else:
|
||||
# unconfigured keystone service will prevent start of haproxy in some
|
||||
# circumstances. make sure haproxy runs. LP #1648396
|
||||
service_stop('keystone')
|
||||
service_start('haproxy')
|
||||
if run_in_apache():
|
||||
disable_unused_apache_sites()
|
||||
if not git_install_requested():
|
||||
service_pause('keystone')
|
||||
|
||||
status_set('maintenance', 'Git install')
|
||||
git_install(config('openstack-origin-git'))
|
||||
|
||||
unison.ensure_user(user=SSH_USER, group='juju_keystone')
|
||||
unison.ensure_user(user=SSH_USER, group='keystone')
|
||||
unison.ensure_user(user=SSH_USER, group=SSH_USER)
|
||||
unison.ensure_user(user=SSH_USER, group=KEYSTONE_USER)
|
||||
|
||||
|
||||
@hooks.hook('config-changed')
|
||||
|
@ -197,11 +214,11 @@ def config_changed():
|
|||
sync_db_with_multi_ipv6_addresses(config('database'),
|
||||
config('database-user'))
|
||||
|
||||
unison.ensure_user(user=SSH_USER, group='juju_keystone')
|
||||
unison.ensure_user(user=SSH_USER, group='keystone')
|
||||
unison.ensure_user(user=SSH_USER, group=SSH_USER)
|
||||
unison.ensure_user(user=SSH_USER, group=KEYSTONE_USER)
|
||||
homedir = unison.get_homedir(SSH_USER)
|
||||
if not os.path.isdir(homedir):
|
||||
mkdir(homedir, SSH_USER, 'juju_keystone', 0o775)
|
||||
mkdir(homedir, SSH_USER, SSH_USER, 0o775)
|
||||
|
||||
if git_install_requested():
|
||||
if config_value_changed('openstack-origin-git'):
|
||||
|
@ -226,7 +243,8 @@ def config_changed_postupgrade():
|
|||
# Ensure ssl dir exists and is unison-accessible
|
||||
ensure_ssl_dir()
|
||||
|
||||
check_call(['chmod', '-R', 'g+wrx', '/var/lib/keystone/'])
|
||||
if not snap_install_requested():
|
||||
check_call(['chmod', '-R', 'g+wrx', '/var/lib/keystone/'])
|
||||
|
||||
ensure_ssl_dirs()
|
||||
|
||||
|
@ -239,16 +257,23 @@ def config_changed_postupgrade():
|
|||
# when deployed from source, init scripts aren't installed
|
||||
if not git_install_requested():
|
||||
service_pause('keystone')
|
||||
|
||||
disable_unused_apache_sites()
|
||||
CONFIGS.write(WSGI_KEYSTONE_API_CONF)
|
||||
if WSGI_KEYSTONE_API_CONF in CONFIGS.templates:
|
||||
CONFIGS.write(WSGI_KEYSTONE_API_CONF)
|
||||
if not is_unit_paused_set():
|
||||
restart_pid_check('apache2')
|
||||
|
||||
configure_https()
|
||||
open_port(config('service-port'))
|
||||
|
||||
update_nrpe_config()
|
||||
|
||||
CONFIGS.write_all()
|
||||
|
||||
if snap_install_requested() and not is_unit_paused_set():
|
||||
service_restart('snap.keystone.*')
|
||||
|
||||
initialise_pki()
|
||||
|
||||
update_all_identity_relation_units()
|
||||
|
@ -276,16 +301,25 @@ def initialise_pki():
|
|||
ensure_pki_cert_paths()
|
||||
if not peer_units() or is_ssl_cert_master():
|
||||
log("Ensuring PKI token certs created", level=DEBUG)
|
||||
cmd = ['keystone-manage', 'pki_setup', '--keystone-user', 'keystone',
|
||||
'--keystone-group', 'keystone']
|
||||
if snap_install_requested():
|
||||
cmd = ['/snap/bin/keystone-manage', 'pki_setup',
|
||||
'--keystone-user', KEYSTONE_USER,
|
||||
'--keystone-group', KEYSTONE_USER]
|
||||
_log_dir = '/var/snap/keystone/common/log'
|
||||
else:
|
||||
cmd = ['keystone-manage', 'pki_setup',
|
||||
'--keystone-user', KEYSTONE_USER,
|
||||
'--keystone-group', KEYSTONE_USER]
|
||||
_log_dir = '/var/log/keystone'
|
||||
check_call(cmd)
|
||||
|
||||
# Ensure logfile has keystone perms since we may have just created it
|
||||
# with root.
|
||||
ensure_permissions('/var/log/keystone', user='keystone',
|
||||
group='keystone', perms=0o744)
|
||||
ensure_permissions('/var/log/keystone/keystone.log', user='keystone',
|
||||
group='keystone', perms=0o644)
|
||||
ensure_permissions(_log_dir, user=KEYSTONE_USER,
|
||||
group=KEYSTONE_USER, perms=0o744)
|
||||
ensure_permissions('{}/keystone.log'.format(_log_dir),
|
||||
user=KEYSTONE_USER, group=KEYSTONE_USER,
|
||||
perms=0o644)
|
||||
|
||||
ensure_pki_dir_permissions()
|
||||
|
||||
|
@ -559,7 +593,7 @@ def send_ssl_sync_request():
|
|||
@hooks.hook('cluster-relation-joined')
|
||||
def cluster_joined(rid=None, ssl_sync_request=True):
|
||||
unison.ssh_authorized_peers(user=SSH_USER,
|
||||
group='juju_keystone',
|
||||
group=SSH_USER,
|
||||
peer_interface='cluster',
|
||||
ensure_local_user=True)
|
||||
|
||||
|
@ -585,7 +619,7 @@ def cluster_joined(rid=None, ssl_sync_request=True):
|
|||
@update_certs_if_available
|
||||
def cluster_changed():
|
||||
unison.ssh_authorized_peers(user=SSH_USER,
|
||||
group='juju_keystone',
|
||||
group=SSH_USER,
|
||||
peer_interface='cluster',
|
||||
ensure_local_user=True)
|
||||
# NOTE(jamespage) re-echo passwords for peer storage
|
||||
|
@ -775,7 +809,10 @@ def domain_backend_changed(relation_id=None, unit=None):
|
|||
db = unitdata.kv()
|
||||
if restart_nonce != db.get(domain_nonce_key):
|
||||
if not is_unit_paused_set():
|
||||
service_restart(keystone_service())
|
||||
if snap_install_requested():
|
||||
service_restart('snap.keystone.*')
|
||||
else:
|
||||
service_restart(keystone_service())
|
||||
db.set(domain_nonce_key, restart_nonce)
|
||||
db.flush()
|
||||
|
||||
|
@ -789,6 +826,10 @@ def configure_https():
|
|||
# need to write all to ensure changes to the entire request pipeline
|
||||
# propagate (c-api, haprxy, apache)
|
||||
CONFIGS.write_all()
|
||||
# NOTE (thedac): When using snaps, nginx is installed, skip any apache2
|
||||
# config.
|
||||
if snap_install_requested():
|
||||
return
|
||||
if 'https' in CONFIGS.complete_contexts():
|
||||
cmd = ['a2ensite', 'openstack_https_frontend']
|
||||
check_call(cmd)
|
||||
|
@ -805,7 +846,7 @@ def upgrade_charm():
|
|||
status_set('maintenance', 'Installing apt packages')
|
||||
apt_install(filter_installed_packages(determine_packages()))
|
||||
unison.ssh_authorized_peers(user=SSH_USER,
|
||||
group='juju_keystone',
|
||||
group=SSH_USER,
|
||||
peer_interface='cluster',
|
||||
ensure_local_user=True)
|
||||
|
||||
|
@ -842,7 +883,12 @@ def update_nrpe_config():
|
|||
current_unit = nrpe.get_nagios_unit_name()
|
||||
nrpe_setup = nrpe.NRPE(hostname=hostname)
|
||||
nrpe.copy_nrpe_checks()
|
||||
nrpe.add_init_service_checks(nrpe_setup, services(), current_unit)
|
||||
_services = []
|
||||
for service in services():
|
||||
if service.startswith('snap.'):
|
||||
service = service.split('.')[1]
|
||||
_services.append(service)
|
||||
nrpe.add_init_service_checks(nrpe_setup, _services, current_unit)
|
||||
nrpe.add_haproxy_checks(nrpe_setup, current_unit)
|
||||
nrpe_setup.write()
|
||||
|
||||
|
|
|
@ -28,6 +28,7 @@ import threading
|
|||
import time
|
||||
import urlparse
|
||||
import uuid
|
||||
import sys
|
||||
|
||||
from itertools import chain
|
||||
from base64 import b64encode
|
||||
|
@ -75,6 +76,9 @@ from charmhelpers.contrib.openstack.utils import (
|
|||
os_application_version_set,
|
||||
CompareOpenStackReleases,
|
||||
reset_os_release,
|
||||
snap_install_requested,
|
||||
install_os_snaps,
|
||||
get_snaps_install_info_from_origin,
|
||||
)
|
||||
|
||||
from charmhelpers.contrib.python.packages import (
|
||||
|
@ -160,6 +164,15 @@ BASE_PACKAGES = [
|
|||
'uuid',
|
||||
]
|
||||
|
||||
BASE_PACKAGES_SNAP = [
|
||||
'haproxy',
|
||||
'openssl',
|
||||
'python-six',
|
||||
'pwgen',
|
||||
'unison',
|
||||
'uuid',
|
||||
]
|
||||
|
||||
VERSION_PACKAGE = 'keystone'
|
||||
|
||||
BASE_GIT_PACKAGES = [
|
||||
|
@ -175,37 +188,76 @@ BASE_GIT_PACKAGES = [
|
|||
'zlib1g-dev',
|
||||
]
|
||||
|
||||
BASE_SERVICES = [
|
||||
'keystone',
|
||||
]
|
||||
|
||||
# ubuntu packages that should not be installed when deploying from git
|
||||
GIT_PACKAGE_BLACKLIST = [
|
||||
'keystone',
|
||||
]
|
||||
|
||||
KEYSTONE_CONF = "/etc/keystone/keystone.conf"
|
||||
KEYSTONE_LOGGER_CONF = "/etc/keystone/logging.conf"
|
||||
KEYSTONE_CONF_DIR = os.path.dirname(KEYSTONE_CONF)
|
||||
STORED_PASSWD = "/var/lib/keystone/keystone.passwd"
|
||||
STORED_TOKEN = "/var/lib/keystone/keystone.token"
|
||||
STORED_ADMIN_DOMAIN_ID = "/var/lib/keystone/keystone.admin_domain_id"
|
||||
STORED_DEFAULT_DOMAIN_ID = "/var/lib/keystone/keystone.default_domain_id"
|
||||
SERVICE_PASSWD_PATH = '/var/lib/keystone/services.passwd'
|
||||
|
||||
SSH_USER = 'juju_keystone'
|
||||
if snap_install_requested():
|
||||
SNAP_BASE_DIR = "/snap/keystone/current"
|
||||
SNAP_COMMON_DIR = "/var/snap/keystone/common"
|
||||
SNAP_COMMON_ETC_DIR = "{}/etc".format(SNAP_COMMON_DIR)
|
||||
SNAP_COMMON_KEYSTONE_DIR = "{}/keystone".format(SNAP_COMMON_ETC_DIR)
|
||||
KEYSTONE_USER = 'root'
|
||||
KEYSTONE_CONF = ('{}/keystone.conf.d/keystone.conf'
|
||||
''.format(SNAP_COMMON_KEYSTONE_DIR))
|
||||
KEYSTONE_CONF_DIR = os.path.dirname(KEYSTONE_CONF)
|
||||
KEYSTONE_NGINX_SITE_CONF = ("{}/nginx/sites-enabled/keystone-nginx.conf"
|
||||
"".format(SNAP_COMMON_ETC_DIR))
|
||||
KEYSTONE_NGINX_CONF = "{}/nginx/nginx.conf".format(SNAP_COMMON_ETC_DIR)
|
||||
KEYSTONE_LOGGER_CONF = "{}/logging.conf".format(SNAP_COMMON_KEYSTONE_DIR)
|
||||
SNAP_LIB_DIR = '{}/lib'.format(SNAP_COMMON_DIR)
|
||||
STORED_PASSWD = "{}/keystone.passwd".format(SNAP_LIB_DIR)
|
||||
STORED_TOKEN = "{}/keystone.token".format(SNAP_LIB_DIR)
|
||||
STORED_ADMIN_DOMAIN_ID = ("{}/keystone.admin_domain_id"
|
||||
"".format(SNAP_LIB_DIR))
|
||||
STORED_DEFAULT_DOMAIN_ID = ("{}/keystone.default_domain_id"
|
||||
"".format(SNAP_LIB_DIR))
|
||||
SERVICE_PASSWD_PATH = '{}/services.passwd'.format(SNAP_LIB_DIR)
|
||||
|
||||
SSH_USER_HOME = '/home/{}'.format(SSH_USER)
|
||||
SYNC_FLAGS_DIR = '{}/juju_sync_flags/'.format(SSH_USER_HOME)
|
||||
SYNC_DIR = '{}/juju_sync/'.format(SSH_USER_HOME)
|
||||
SSL_SYNC_ARCHIVE = os.path.join(SYNC_DIR, 'juju-ssl-sync.tar')
|
||||
SSL_DIR = '{}/juju_ssl/'.format(SNAP_LIB_DIR)
|
||||
PKI_CERTS_DIR = os.path.join(SSL_DIR, 'pki')
|
||||
POLICY_JSON = ('{}/keystone.conf.d/policy.json'
|
||||
''.format(SNAP_COMMON_KEYSTONE_DIR))
|
||||
BASE_SERVICES = ['snap.keystone.uwsgi', 'snap.keystone.nginx']
|
||||
APACHE_SSL_DIR = '{}/keystone'.format(SSL_DIR)
|
||||
else:
|
||||
APACHE_SSL_DIR = '/etc/apache2/ssl/keystone'
|
||||
KEYSTONE_USER = 'keystone'
|
||||
KEYSTONE_CONF = "/etc/keystone/keystone.conf"
|
||||
KEYSTONE_NGINX_CONF = None
|
||||
KEYSTONE_NGINX_SITE_CONF = None
|
||||
KEYSTONE_LOGGER_CONF = "/etc/keystone/logging.conf"
|
||||
KEYSTONE_CONF_DIR = os.path.dirname(KEYSTONE_CONF)
|
||||
STORED_PASSWD = "/var/lib/keystone/keystone.passwd"
|
||||
STORED_TOKEN = "/var/lib/keystone/keystone.token"
|
||||
STORED_ADMIN_DOMAIN_ID = "/var/lib/keystone/keystone.admin_domain_id"
|
||||
STORED_DEFAULT_DOMAIN_ID = "/var/lib/keystone/keystone.default_domain_id"
|
||||
SERVICE_PASSWD_PATH = '/var/lib/keystone/services.passwd'
|
||||
|
||||
SYNC_FLAGS_DIR = '/var/lib/keystone/juju_sync_flags/'
|
||||
SYNC_DIR = '/var/lib/keystone/juju_sync/'
|
||||
SSL_SYNC_ARCHIVE = os.path.join(SYNC_DIR, 'juju-ssl-sync.tar')
|
||||
SSL_DIR = '/var/lib/keystone/juju_ssl/'
|
||||
PKI_CERTS_DIR = os.path.join(SSL_DIR, 'pki')
|
||||
POLICY_JSON = '/etc/keystone/policy.json'
|
||||
BASE_SERVICES = [
|
||||
'keystone',
|
||||
]
|
||||
|
||||
|
||||
HAPROXY_CONF = '/etc/haproxy/haproxy.cfg'
|
||||
APACHE_CONF = '/etc/apache2/sites-available/openstack_https_frontend'
|
||||
APACHE_24_CONF = '/etc/apache2/sites-available/openstack_https_frontend.conf'
|
||||
|
||||
APACHE_SSL_DIR = '/etc/apache2/ssl/keystone'
|
||||
SYNC_FLAGS_DIR = '/var/lib/keystone/juju_sync_flags/'
|
||||
SYNC_DIR = '/var/lib/keystone/juju_sync/'
|
||||
SSL_SYNC_ARCHIVE = os.path.join(SYNC_DIR, 'juju-ssl-sync.tar')
|
||||
SSL_DIR = '/var/lib/keystone/juju_ssl/'
|
||||
PKI_CERTS_DIR = os.path.join(SSL_DIR, 'pki')
|
||||
SSL_CA_NAME = 'Ubuntu Cloud'
|
||||
CLUSTER_RES = 'grp_ks_vips'
|
||||
SSH_USER = 'juju_keystone'
|
||||
CA_CERT_PATH = '/usr/local/share/ca-certificates/keystone_juju_ca_cert.crt'
|
||||
SSL_SYNC_SEMAPHORE = threading.Semaphore()
|
||||
SSL_DIRS = [SSL_DIR, APACHE_SSL_DIR, CA_CERT_PATH]
|
||||
|
@ -213,7 +265,6 @@ ADMIN_DOMAIN = 'admin_domain'
|
|||
ADMIN_PROJECT = 'admin'
|
||||
DEFAULT_DOMAIN = 'default'
|
||||
SERVICE_DOMAIN = 'service_domain'
|
||||
POLICY_JSON = '/etc/keystone/policy.json'
|
||||
TOKEN_FLUSH_CRON_FILE = '/etc/cron.d/keystone-token-flush'
|
||||
WSGI_KEYSTONE_API_CONF = '/etc/apache2/sites-enabled/wsgi-openstack-api.conf'
|
||||
UNUSED_APACHE_SITE_FILES = ['/etc/apache2/sites-enabled/keystone.conf',
|
||||
|
@ -239,6 +290,28 @@ BASE_RESOURCE_MAP = OrderedDict([
|
|||
keystone_context.HAProxyContext()],
|
||||
'services': ['haproxy'],
|
||||
}),
|
||||
(KEYSTONE_NGINX_CONF, {
|
||||
'services': BASE_SERVICES,
|
||||
'contexts': [keystone_context.KeystoneContext(),
|
||||
keystone_context.NginxSSLContext(),
|
||||
context.SharedDBContext(ssl_dir=KEYSTONE_CONF_DIR),
|
||||
context.PostgresqlDBContext(),
|
||||
context.SyslogContext(),
|
||||
keystone_context.HAProxyContext(),
|
||||
context.BindHostContext(),
|
||||
context.WorkerConfigContext()],
|
||||
}),
|
||||
(KEYSTONE_NGINX_SITE_CONF, {
|
||||
'services': BASE_SERVICES,
|
||||
'contexts': [keystone_context.KeystoneContext(),
|
||||
context.SharedDBContext(ssl_dir=KEYSTONE_CONF_DIR),
|
||||
context.PostgresqlDBContext(),
|
||||
context.SyslogContext(),
|
||||
keystone_context.HAProxyContext(),
|
||||
keystone_context.NginxSSLContext(),
|
||||
context.BindHostContext(),
|
||||
context.WorkerConfigContext()],
|
||||
}),
|
||||
(APACHE_CONF, {
|
||||
'contexts': [keystone_context.ApacheSSLContext()],
|
||||
'services': ['apache2'],
|
||||
|
@ -440,25 +513,48 @@ def resource_map():
|
|||
else:
|
||||
resource_map.pop(APACHE_24_CONF)
|
||||
|
||||
if run_in_apache():
|
||||
if snap_install_requested():
|
||||
if APACHE_CONF in resource_map:
|
||||
resource_map.pop(APACHE_CONF)
|
||||
if APACHE_24_CONF in resource_map:
|
||||
resource_map.pop(APACHE_24_CONF)
|
||||
else:
|
||||
if KEYSTONE_NGINX_CONF in resource_map:
|
||||
resource_map.pop(KEYSTONE_NGINX_CONF)
|
||||
if KEYSTONE_NGINX_SITE_CONF in resource_map:
|
||||
resource_map.pop(KEYSTONE_NGINX_SITE_CONF)
|
||||
|
||||
if snap_install_requested():
|
||||
for cfile in resource_map:
|
||||
svcs = resource_map[cfile]['services']
|
||||
if 'apache2' in svcs:
|
||||
svcs.remove('apache2')
|
||||
if 'keystone' in svcs:
|
||||
svcs.remove('keystone')
|
||||
svcs.append('snap.keystone.nginx')
|
||||
svcs.append('snap.keystone.uwsgi')
|
||||
|
||||
if run_in_apache():
|
||||
if not snap_install_requested():
|
||||
for cfile in resource_map:
|
||||
svcs = resource_map[cfile]['services']
|
||||
if 'keystone' in svcs:
|
||||
svcs.remove('keystone')
|
||||
if 'apache2' not in svcs:
|
||||
svcs.append('apache2')
|
||||
admin_script = os.path.join(git_determine_usr_bin(),
|
||||
"keystone-wsgi-admin")
|
||||
public_script = os.path.join(git_determine_usr_bin(),
|
||||
"keystone-wsgi-public")
|
||||
resource_map[WSGI_KEYSTONE_API_CONF] = {
|
||||
'contexts': [
|
||||
context.WSGIWorkerConfigContext(name="keystone",
|
||||
admin_script=admin_script,
|
||||
public_script=public_script),
|
||||
keystone_context.KeystoneContext()],
|
||||
'services': ['apache2']
|
||||
}
|
||||
admin_script = os.path.join(git_determine_usr_bin(),
|
||||
"keystone-wsgi-admin")
|
||||
public_script = os.path.join(git_determine_usr_bin(),
|
||||
"keystone-wsgi-public")
|
||||
resource_map[WSGI_KEYSTONE_API_CONF] = {
|
||||
'contexts': [
|
||||
context.WSGIWorkerConfigContext(
|
||||
name="keystone",
|
||||
admin_script=admin_script,
|
||||
public_script=public_script),
|
||||
keystone_context.KeystoneContext()],
|
||||
'services': ['apache2']
|
||||
}
|
||||
return resource_map
|
||||
|
||||
|
||||
|
@ -495,7 +591,8 @@ def run_in_apache():
|
|||
"""Return true if keystone API is run under apache2 with mod_wsgi in
|
||||
this release.
|
||||
"""
|
||||
return CompareOpenStackReleases(os_release('keystone')) >= 'liberty'
|
||||
return (CompareOpenStackReleases(os_release('keystone')) >= 'liberty' and
|
||||
not snap_install_requested())
|
||||
|
||||
|
||||
def disable_unused_apache_sites():
|
||||
|
@ -548,13 +645,16 @@ def api_port(service):
|
|||
|
||||
def determine_packages():
|
||||
# currently all packages match service names
|
||||
packages = set(services()).union(BASE_PACKAGES)
|
||||
if git_install_requested():
|
||||
packages |= set(BASE_GIT_PACKAGES)
|
||||
packages -= set(GIT_PACKAGE_BLACKLIST)
|
||||
if run_in_apache():
|
||||
packages.add('libapache2-mod-wsgi')
|
||||
return sorted(packages)
|
||||
if snap_install_requested():
|
||||
return sorted(BASE_PACKAGES_SNAP)
|
||||
else:
|
||||
packages = set(services()).union(BASE_PACKAGES)
|
||||
if git_install_requested():
|
||||
packages |= set(BASE_GIT_PACKAGES)
|
||||
packages -= set(GIT_PACKAGE_BLACKLIST)
|
||||
if run_in_apache():
|
||||
packages.add('libapache2-mod-wsgi')
|
||||
return sorted(packages)
|
||||
|
||||
|
||||
def save_script_rc():
|
||||
|
@ -578,16 +678,28 @@ def do_openstack_upgrade(configs):
|
|||
new_os_rel = get_os_codename_install_source(new_src)
|
||||
log('Performing OpenStack upgrade to %s.' % (new_os_rel))
|
||||
|
||||
configure_installation_source(new_src)
|
||||
apt_update()
|
||||
|
||||
dpkg_opts = [
|
||||
'--option', 'Dpkg::Options::=--force-confnew',
|
||||
'--option', 'Dpkg::Options::=--force-confdef',
|
||||
]
|
||||
apt_upgrade(options=dpkg_opts, fatal=True, dist=True)
|
||||
reset_os_release()
|
||||
apt_install(packages=determine_packages(), options=dpkg_opts, fatal=True)
|
||||
if not snap_install_requested():
|
||||
configure_installation_source(new_src)
|
||||
apt_update()
|
||||
dpkg_opts = [
|
||||
'--option', 'Dpkg::Options::=--force-confnew',
|
||||
'--option', 'Dpkg::Options::=--force-confdef',
|
||||
]
|
||||
apt_upgrade(options=dpkg_opts, fatal=True, dist=True)
|
||||
reset_os_release()
|
||||
apt_install(packages=determine_packages(),
|
||||
options=dpkg_opts, fatal=True)
|
||||
else:
|
||||
# TODO: Add support for upgrade from deb->snap
|
||||
# NOTE(thedac): Setting devmode until LP#1719636 is fixed
|
||||
install_os_snaps(
|
||||
get_snaps_install_info_from_origin(
|
||||
['keystone'],
|
||||
new_src,
|
||||
mode='devmode'),
|
||||
refresh=True)
|
||||
post_snap_install()
|
||||
reset_os_release()
|
||||
|
||||
# set CONFIGS to load templates from new release and regenerate config
|
||||
configs.set_release(openstack_release=new_os_rel)
|
||||
|
@ -625,13 +737,26 @@ def keystone_service():
|
|||
def migrate_database():
|
||||
"""Runs keystone-manage to initialize a new database or migrate existing"""
|
||||
log('Migrating the keystone database.', level=INFO)
|
||||
service_stop(keystone_service())
|
||||
if snap_install_requested():
|
||||
service_stop('snap.keystone.*')
|
||||
else:
|
||||
service_stop(keystone_service())
|
||||
# NOTE(jamespage) > icehouse creates a log file as root so use
|
||||
# sudo to execute as keystone otherwise keystone won't start
|
||||
# afterwards.
|
||||
cmd = ['sudo', '-u', 'keystone', 'keystone-manage', 'db_sync']
|
||||
|
||||
# NOTE(coreycb): Can just use keystone-manage when snap has alias support.
|
||||
# Also can run as keystone once snap has drop privs support.
|
||||
if snap_install_requested():
|
||||
cmd = ['/snap/bin/keystone-manage', 'db_sync']
|
||||
else:
|
||||
cmd = ['sudo', '-u', 'keystone', 'keystone-manage', 'db_sync']
|
||||
subprocess.check_output(cmd)
|
||||
service_start(keystone_service())
|
||||
if snap_install_requested():
|
||||
service_start('snap.keystone.nginx')
|
||||
service_start('snap.keystone.uwsgi')
|
||||
else:
|
||||
service_start(keystone_service())
|
||||
time.sleep(10)
|
||||
peer_store('db-initialised', 'True')
|
||||
|
||||
|
@ -646,8 +771,10 @@ def get_local_endpoint(api_suffix=None):
|
|||
"""Returns the URL for the local end-point bypassing haproxy/ssl"""
|
||||
if not api_suffix:
|
||||
api_suffix = get_api_suffix()
|
||||
|
||||
keystone_port = determine_api_port(api_port('keystone-admin'),
|
||||
singlenode_mode=True)
|
||||
|
||||
if config('prefer-ipv6'):
|
||||
ipv6_addr = get_ipv6_addr(exc_list=[config('vip')])[0]
|
||||
local_endpoint = 'http://[{}]:{}/{}/'.format(
|
||||
|
@ -889,6 +1016,7 @@ def create_user(name, password, tenant=None, domain=None):
|
|||
|
||||
def get_manager(api_version=None):
|
||||
"""Return a keystonemanager for the correct API version"""
|
||||
set_python_path()
|
||||
from manager import get_keystone_manager
|
||||
return get_keystone_manager(get_local_endpoint(), get_admin_token(),
|
||||
api_version)
|
||||
|
@ -1013,10 +1141,23 @@ def get_api_version():
|
|||
return api_version
|
||||
|
||||
|
||||
def set_python_path():
|
||||
""" Set the Python path to include snap installed python libraries
|
||||
|
||||
The charm itself requires access to the python client. When installed as a
|
||||
snap the client libraries are in /snap/$SNAP/common/lib/python2.7. This
|
||||
function sets the python path to allow clients to be imported from snap
|
||||
installs.
|
||||
"""
|
||||
if snap_install_requested():
|
||||
sys.path.append(determine_python_path())
|
||||
|
||||
|
||||
def ensure_initial_admin(config):
|
||||
# Allow retry on fail since leader may not be ready yet.
|
||||
# NOTE(hopem): ks client may not be installed at module import time so we
|
||||
# use this wrapped approach instead.
|
||||
set_python_path()
|
||||
try:
|
||||
from keystoneclient.apiclient.exceptions import InternalServerError
|
||||
except:
|
||||
|
@ -1192,10 +1333,10 @@ def ensure_ssl_dirs():
|
|||
"""Ensure unison has access to these dirs."""
|
||||
for path in [SYNC_FLAGS_DIR, SYNC_DIR]:
|
||||
if not os.path.isdir(path):
|
||||
mkdir(path, SSH_USER, 'juju_keystone', 0o775)
|
||||
mkdir(path, SSH_USER, KEYSTONE_USER, 0o775)
|
||||
else:
|
||||
ensure_permissions(path, user=SSH_USER, group='keystone',
|
||||
perms=0o755)
|
||||
ensure_permissions(path, user=SSH_USER, group=KEYSTONE_USER,
|
||||
perms=0o775)
|
||||
|
||||
|
||||
def ensure_permissions(path, user=None, group=None, perms=None, recurse=False,
|
||||
|
@ -1293,7 +1434,7 @@ def create_peer_service_actions(action, services):
|
|||
(local_unit().replace('/', '-'),
|
||||
service.strip(), action))
|
||||
log("Creating action %s" % (flagfile), level=DEBUG)
|
||||
write_file(flagfile, content='', owner=SSH_USER, group='keystone',
|
||||
write_file(flagfile, content='', owner=SSH_USER, group=KEYSTONE_USER,
|
||||
perms=0o744)
|
||||
|
||||
|
||||
|
@ -1302,7 +1443,7 @@ def create_peer_actions(actions):
|
|||
action = "%s.%s" % (local_unit().replace('/', '-'), action)
|
||||
flagfile = os.path.join(SYNC_FLAGS_DIR, action)
|
||||
log("Creating action %s" % (flagfile), level=DEBUG)
|
||||
write_file(flagfile, content='', owner=SSH_USER, group='keystone',
|
||||
write_file(flagfile, content='', owner=SSH_USER, group=KEYSTONE_USER,
|
||||
perms=0o744)
|
||||
|
||||
|
||||
|
@ -1315,7 +1456,7 @@ def unison_sync(paths_to_sync):
|
|||
"""
|
||||
log('Synchronizing CA (%s) to all peers.' % (', '.join(paths_to_sync)),
|
||||
level=INFO)
|
||||
keystone_gid = grp.getgrnam('keystone').gr_gid
|
||||
keystone_gid = grp.getgrnam(KEYSTONE_USER).gr_gid
|
||||
|
||||
# NOTE(dosaboy): This will sync to all peers who have already provided
|
||||
# their ssh keys. If any existing peers have not provided their keys yet,
|
||||
|
@ -1462,8 +1603,8 @@ def stage_paths_for_sync(paths):
|
|||
log("Path '%s' does not exist - not adding to sync "
|
||||
"tarball" % (path), level=INFO)
|
||||
|
||||
ensure_permissions(SYNC_DIR, user=SSH_USER, group='keystone',
|
||||
perms=0o755, recurse=True)
|
||||
ensure_permissions(SYNC_DIR, user=SSH_USER, group=KEYSTONE_USER,
|
||||
perms=0o775, recurse=True)
|
||||
|
||||
|
||||
def is_pki_enabled():
|
||||
|
@ -1481,20 +1622,21 @@ def ensure_pki_cert_paths():
|
|||
if not os.path.exists(p)]
|
||||
if not_exists:
|
||||
log("Configuring token signing cert paths", level=DEBUG)
|
||||
perms = 0o755
|
||||
perms = 0o775
|
||||
for path in not_exists:
|
||||
if not os.path.isdir(path):
|
||||
mkdir(path=path, owner=SSH_USER, group='keystone', perms=perms)
|
||||
mkdir(path=path, owner=SSH_USER, group=KEYSTONE_USER,
|
||||
perms=perms)
|
||||
else:
|
||||
# Ensure accessible by ssh user and group (for sync).
|
||||
ensure_permissions(path, user=SSH_USER, group='keystone',
|
||||
ensure_permissions(path, user=SSH_USER, group=KEYSTONE_USER,
|
||||
perms=perms)
|
||||
|
||||
|
||||
def ensure_pki_dir_permissions():
|
||||
# Ensure accessible by unison user and group (for sync).
|
||||
ensure_permissions(PKI_CERTS_DIR, user=SSH_USER, group='keystone',
|
||||
perms=0o755, recurse=True)
|
||||
ensure_permissions(PKI_CERTS_DIR, user=SSH_USER, group=KEYSTONE_USER,
|
||||
perms=0o775, recurse=True)
|
||||
|
||||
|
||||
def update_certs_if_available(f):
|
||||
|
@ -1511,7 +1653,8 @@ def update_certs_if_available(f):
|
|||
fd.extractall(path='/')
|
||||
|
||||
for syncfile in files:
|
||||
ensure_permissions(syncfile, user='keystone', group='keystone',
|
||||
ensure_permissions(syncfile, user=KEYSTONE_USER,
|
||||
group=KEYSTONE_USER,
|
||||
perms=0o744, recurse=True)
|
||||
|
||||
# Mark as complete
|
||||
|
@ -1572,7 +1715,7 @@ def synchronize_ca(fatal=False):
|
|||
return {}
|
||||
|
||||
if not os.path.isdir(SYNC_FLAGS_DIR):
|
||||
mkdir(SYNC_FLAGS_DIR, SSH_USER, 'keystone', 0o775)
|
||||
mkdir(SYNC_FLAGS_DIR, SSH_USER, KEYSTONE_USER, 0o775)
|
||||
|
||||
for action, services in peer_service_actions.iteritems():
|
||||
create_peer_service_actions(action, set(services))
|
||||
|
@ -1710,15 +1853,17 @@ def force_ssl_sync():
|
|||
|
||||
def ensure_ssl_dir():
|
||||
"""Ensure juju ssl dir exists and is unsion read/writable."""
|
||||
perms = 0o755
|
||||
# NOTE(thedac) Snap service restarts will override permissions
|
||||
# in SNAP_LIB_DIR including SSL_DIR
|
||||
perms = 0o775
|
||||
if not os.path.isdir(SSL_DIR):
|
||||
mkdir(SSL_DIR, SSH_USER, 'keystone', perms)
|
||||
mkdir(SSL_DIR, SSH_USER, KEYSTONE_USER, perms)
|
||||
else:
|
||||
ensure_permissions(SSL_DIR, user=SSH_USER, group='keystone',
|
||||
ensure_permissions(SSL_DIR, user=SSH_USER, group=KEYSTONE_USER,
|
||||
perms=perms)
|
||||
|
||||
|
||||
def get_ca(user='keystone', group='keystone'):
|
||||
def get_ca(user=KEYSTONE_USER, group=KEYSTONE_USER):
|
||||
"""Initialize a new CA object if one hasn't already been loaded.
|
||||
|
||||
This will create a new CA or load an existing one.
|
||||
|
@ -2273,7 +2418,6 @@ def is_db_ready(use_current_context=False, db_rel=None):
|
|||
|
||||
def determine_usr_bin():
|
||||
"""Return the /usr/bin path for Apache2 vhost config.
|
||||
|
||||
The /usr/bin path will be located in the virtualenv if the charm
|
||||
is configured to deploy keystone from source.
|
||||
"""
|
||||
|
@ -2286,16 +2430,20 @@ def determine_usr_bin():
|
|||
|
||||
|
||||
def determine_python_path():
|
||||
"""Return the python-path for Apache2 vhost config.
|
||||
"""Return the python-path
|
||||
|
||||
Returns None unless the charm is configured to deploy keystone from source,
|
||||
in which case the path of the virtualenv's site-packages is returned.
|
||||
Determine if git or snap installed and return the appropriate python path.
|
||||
Returns None unless the charm if neither condition is true.
|
||||
|
||||
:returns: string python path or None
|
||||
"""
|
||||
if git_install_requested():
|
||||
_python_path = 'lib/python2.7/site-packages'
|
||||
if snap_install_requested():
|
||||
return os.path.join(SNAP_BASE_DIR, _python_path)
|
||||
elif git_install_requested():
|
||||
projects_yaml = config('openstack-origin-git')
|
||||
projects_yaml = git_default_repos(projects_yaml)
|
||||
return os.path.join(git_pip_venv_dir(projects_yaml),
|
||||
'lib/python2.7/site-packages')
|
||||
return os.path.join(git_pip_venv_dir(projects_yaml), _python_path)
|
||||
else:
|
||||
return None
|
||||
|
||||
|
@ -2327,10 +2475,12 @@ def git_pre_install():
|
|||
add_user_to_group('keystone', 'keystone')
|
||||
|
||||
for d in dirs:
|
||||
mkdir(d, owner='keystone', group='keystone', perms=0o755, force=False)
|
||||
mkdir(d, owner=KEYSTONE_USER, group=KEYSTONE_USER, perms=0o755,
|
||||
force=False)
|
||||
|
||||
for l in logs:
|
||||
write_file(l, '', owner='keystone', group='keystone', perms=0o600)
|
||||
write_file(l, '', owner=KEYSTONE_USER, group=KEYSTONE_USER,
|
||||
perms=0o600)
|
||||
|
||||
|
||||
def git_post_install(projects_yaml):
|
||||
|
@ -2379,9 +2529,9 @@ def git_post_install(projects_yaml):
|
|||
'process_name': 'keystone',
|
||||
'executable_name': os.path.join(bin_dir, 'keystone-all'),
|
||||
'config_files': ['/etc/keystone/keystone.conf'],
|
||||
'log_file': '/var/log/keystone/keystone.log',
|
||||
}
|
||||
|
||||
keystone_context['log_file'] = '/var/log/keystone/keystone.log'
|
||||
templates_dir = 'hooks/charmhelpers/contrib/openstack/templates'
|
||||
templates_dir = os.path.join(charm_dir(), templates_dir)
|
||||
render('git.upstart', '/etc/init/keystone.conf', keystone_context,
|
||||
|
@ -2509,3 +2659,16 @@ def _pause_resume_helper(f, configs):
|
|||
f(assess_status_func(configs),
|
||||
services=services(),
|
||||
ports=determine_ports())
|
||||
|
||||
|
||||
def post_snap_install():
|
||||
""" Specific steps post snap install for this charm
|
||||
|
||||
"""
|
||||
log("Perfoming post snap install tasks", INFO)
|
||||
PASTE_SRC = ('{}/etc/keystone/keystone-paste.ini'
|
||||
''.format(SNAP_BASE_DIR))
|
||||
PASTE_DST = '{}/keystone-paste.ini'.format(SNAP_COMMON_KEYSTONE_DIR)
|
||||
if os.path.exists(PASTE_SRC):
|
||||
log("Perfoming post snap install tasks", INFO)
|
||||
shutil.copy(PASTE_SRC, PASTE_DST)
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
server {
|
||||
listen {{ public_port }};
|
||||
access_log /var/snap/keystone/common/log/nginx-access.log;
|
||||
error_log /var/snap/keystone/common/log/nginx-error.log;
|
||||
location / {
|
||||
include /snap/keystone/current/usr/conf/uwsgi_params;
|
||||
uwsgi_param SCRIPT_NAME '';
|
||||
uwsgi_pass unix:///var/snap/keystone/common/run/public.sock;
|
||||
}
|
||||
}
|
||||
server {
|
||||
listen {{ admin_port }};
|
||||
access_log /var/snap/keystone/common/log/nginx-access.log;
|
||||
error_log /var/snap/keystone/common/log/nginx-error.log;
|
||||
location / {
|
||||
include /snap/keystone/current/usr/conf/uwsgi_params;
|
||||
uwsgi_param SCRIPT_NAME '';
|
||||
uwsgi_pass unix:///var/snap/keystone/common/run/admin.sock;
|
||||
}
|
||||
}
|
||||
{% if ssl -%}
|
||||
{% if endpoints -%}
|
||||
{% for ep in endpoints -%}
|
||||
server {
|
||||
listen {{ endpoints[ep]['ext'] }} {% if ssl -%}ssl{% endif -%};
|
||||
|
||||
{% if ssl -%}
|
||||
ssl on;
|
||||
ssl_certificate /var/snap/keystone/common/lib/juju_ssl/{{ namespace }}/cert_{{ endpoints[ep]['address'] }};
|
||||
ssl_certificate_key /var/snap/keystone/common/lib/juju_ssl/{{ namespace }}/key_{{ endpoints[ep]['address'] }};
|
||||
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
|
||||
ssl_ciphers HIGH:!RC4:!MD5:!aNULL:!eNULL:!EXP:!LOW:!MEDIUM;
|
||||
server_name {{ endpoints[ep]['address'] }};
|
||||
{% endif -%}
|
||||
|
||||
access_log /var/snap/keystone/common/log/nginx-access.log;
|
||||
error_log /var/snap/keystone/common/log/nginx-error.log;
|
||||
location / {
|
||||
include /snap/keystone/current/usr/conf/uwsgi_params;
|
||||
uwsgi_param SCRIPT_NAME '';
|
||||
uwsgi_pass unix:///var/snap/keystone/common/run/{{ endpoints[ep]['socket'] }}.sock;
|
||||
}
|
||||
}
|
||||
{% endfor -%}
|
||||
{% endif -%}
|
||||
{% endif -%}
|
|
@ -0,0 +1,117 @@
|
|||
# ocata
|
||||
###############################################################################
|
||||
# [ WARNING ]
|
||||
# Configuration file maintained by Juju. Local changes may be overwritten.
|
||||
###############################################################################
|
||||
[DEFAULT]
|
||||
admin_token = {{ token }}
|
||||
use_syslog = {{ use_syslog }}
|
||||
log_config_append = {{ log_config }}
|
||||
debug = {{ debug }}
|
||||
public_endpoint = {{ public_endpoint }}
|
||||
admin_endpoint = {{ admin_endpoint }}
|
||||
|
||||
[database]
|
||||
{% if database_host -%}
|
||||
connection = {{ database_type }}://{{ database_user }}:{{ database_password }}@{{ database_host }}/{{ database }}{% if database_ssl_ca %}?ssl_ca={{ database_ssl_ca }}{% if database_ssl_cert %}&ssl_cert={{ database_ssl_cert }}&ssl_key={{ database_ssl_key }}{% endif %}{% endif %}
|
||||
{% else -%}
|
||||
connection = sqlite:////var/lib/keystone/keystone.db
|
||||
{% endif -%}
|
||||
idle_timeout = 200
|
||||
|
||||
[identity]
|
||||
driver = {{ identity_backend }}
|
||||
{% if default_domain_id -%}
|
||||
default_domain_id = {{ default_domain_id }}
|
||||
{% endif -%}
|
||||
|
||||
{% if api_version == 3 -%}
|
||||
domain_specific_drivers_enabled = True
|
||||
domain_config_dir = {{ domain_config_dir }}
|
||||
{% endif -%}
|
||||
|
||||
[credential]
|
||||
driver = sql
|
||||
|
||||
[trust]
|
||||
driver = sql
|
||||
|
||||
[os_inherit]
|
||||
|
||||
[catalog]
|
||||
driver = sql
|
||||
|
||||
[endpoint_filter]
|
||||
|
||||
[token]
|
||||
driver = sql
|
||||
{% if token_provider == 'pki' -%}
|
||||
provider = keystone.token.providers.pki.Provider
|
||||
{% elif token_provider == 'pkiz' -%}
|
||||
provider = keystone.token.providers.pkiz.Provider
|
||||
{% else -%}
|
||||
provider = keystone.token.providers.uuid.Provider
|
||||
{% endif -%}
|
||||
expiration = {{ token_expiration }}
|
||||
|
||||
{% include "parts/section-signing" %}
|
||||
|
||||
[cache]
|
||||
|
||||
[policy]
|
||||
driver = sql
|
||||
|
||||
[assignment]
|
||||
driver = {{ assignment_backend }}
|
||||
|
||||
[oauth1]
|
||||
|
||||
[auth]
|
||||
methods = external,password,token,oauth1
|
||||
password = keystone.auth.plugins.password.Password
|
||||
token = keystone.auth.plugins.token.Token
|
||||
oauth1 = keystone.auth.plugins.oauth1.OAuth
|
||||
|
||||
[paste_deploy]
|
||||
config_file = {{ paste_config_file }}
|
||||
|
||||
[extra_headers]
|
||||
Distribution = Ubuntu
|
||||
|
||||
[ldap]
|
||||
{% if identity_backend == 'ldap' -%}
|
||||
url = {{ ldap_server }}
|
||||
user = {{ ldap_user }}
|
||||
password = {{ ldap_password }}
|
||||
suffix = {{ ldap_suffix }}
|
||||
|
||||
{% if ldap_config_flags -%}
|
||||
{% for key, value in ldap_config_flags.iteritems() -%}
|
||||
{{ key }} = {{ value }}
|
||||
{% endfor -%}
|
||||
{% endif -%}
|
||||
|
||||
{% if ldap_readonly -%}
|
||||
user_allow_create = False
|
||||
user_allow_update = False
|
||||
user_allow_delete = False
|
||||
|
||||
tenant_allow_create = False
|
||||
tenant_allow_update = False
|
||||
tenant_allow_delete = False
|
||||
|
||||
role_allow_create = False
|
||||
role_allow_update = False
|
||||
role_allow_delete = False
|
||||
|
||||
group_allow_create = False
|
||||
group_allow_update = False
|
||||
group_allow_delete = False
|
||||
{% endif -%}
|
||||
{% endif -%}
|
||||
|
||||
{% if api_version == 3 -%}
|
||||
[resource]
|
||||
admin_project_domain_name = {{ admin_domain_name }}
|
||||
admin_project_name = admin
|
||||
{% endif -%}
|
|
@ -0,0 +1,48 @@
|
|||
# ocata
|
||||
[loggers]
|
||||
keys=root
|
||||
|
||||
[formatters]
|
||||
keys=normal,normal_with_name,debug
|
||||
|
||||
[handlers]
|
||||
keys=production,file,devel
|
||||
|
||||
[logger_root]
|
||||
{% if root_level -%}
|
||||
level={{ root_level }}
|
||||
{% else -%}
|
||||
level=WARNING
|
||||
{% endif -%}
|
||||
handlers=file,production
|
||||
|
||||
[handler_production]
|
||||
class=handlers.SysLogHandler
|
||||
{% if log_level -%}
|
||||
level={{ log_level }}
|
||||
{% else -%}
|
||||
level=ERROR
|
||||
{% endif -%}
|
||||
formatter=normal_with_name
|
||||
args=(('/dev/log'), handlers.SysLogHandler.LOG_USER)
|
||||
|
||||
[handler_file]
|
||||
class=FileHandler
|
||||
level=DEBUG
|
||||
formatter=normal_with_name
|
||||
args=('{{ log_file }}', 'a')
|
||||
|
||||
[handler_devel]
|
||||
class=StreamHandler
|
||||
level=NOTSET
|
||||
formatter=debug
|
||||
args=(sys.stdout,)
|
||||
|
||||
[formatter_normal]
|
||||
format=%(asctime)s %(levelname)s %(message)s
|
||||
|
||||
[formatter_normal_with_name]
|
||||
format=(%(name)s): %(asctime)s %(levelname)s %(message)s
|
||||
|
||||
[formatter_debug]
|
||||
format=(%(name)s): %(asctime)s %(levelname)s %(module)s %(funcName)s %(message)s
|
|
@ -0,0 +1,39 @@
|
|||
user root root;
|
||||
worker_processes {{ workers }};
|
||||
pid /var/snap/keystone/common/run/nginx.pid;
|
||||
|
||||
events {
|
||||
worker_connections 768;
|
||||
}
|
||||
|
||||
http {
|
||||
##
|
||||
# Basic Settings
|
||||
##
|
||||
|
||||
sendfile on;
|
||||
tcp_nopush on;
|
||||
tcp_nodelay on;
|
||||
keepalive_timeout 65;
|
||||
types_hash_max_size 2048;
|
||||
|
||||
include /snap/keystone/current/usr/conf/mime.types;
|
||||
default_type application/octet-stream;
|
||||
|
||||
##
|
||||
# Logging Settings
|
||||
##
|
||||
|
||||
access_log /var/snap/keystone/common/log/nginx-access.log;
|
||||
error_log /var/snap/keystone/common/log/nginx-error.log;
|
||||
|
||||
##
|
||||
# Gzip Settings
|
||||
##
|
||||
|
||||
gzip on;
|
||||
gzip_disable "msie6";
|
||||
|
||||
include /var/snap/keystone/common/etc/nginx/conf.d/*.conf;
|
||||
include /var/snap/keystone/common/etc/nginx/sites-enabled/*;
|
||||
}
|
|
@ -9,6 +9,9 @@ charm-tools>=2.0.0
|
|||
requests==2.6.0
|
||||
# BEGIN: Amulet OpenStack Charm Helper Requirements
|
||||
# Liberty client lower constraints
|
||||
# The websocket-client issue should be resolved in the jujulib/theblues
|
||||
# Temporarily work around it
|
||||
websocket-client<=0.40.0
|
||||
amulet>=1.14.3,<2.0
|
||||
bundletester>=0.6.1,<1.0
|
||||
python-ceilometerclient>=1.5.0
|
||||
|
|
|
@ -45,13 +45,15 @@ class KeystoneBasicDeployment(OpenStackAmuletDeployment):
|
|||
DEFAULT_DOMAIN = 'default'
|
||||
|
||||
def __init__(self, series=None, openstack=None,
|
||||
source=None, git=False, stable=False):
|
||||
source=None, git=False, stable=False, snap_source=None):
|
||||
"""Deploy the entire test environment."""
|
||||
super(KeystoneBasicDeployment, self).__init__(series, openstack,
|
||||
source, stable)
|
||||
self.keystone_num_units = 3
|
||||
self.keystone_api_version = 2
|
||||
self.git = git
|
||||
|
||||
self._setup_test_object(snap_source)
|
||||
self._add_services()
|
||||
self._add_relations()
|
||||
self._configure_services()
|
||||
|
@ -64,14 +66,49 @@ class KeystoneBasicDeployment(OpenStackAmuletDeployment):
|
|||
self.d.sentry.wait()
|
||||
self._initialize_tests()
|
||||
|
||||
def _assert_services(self, should_run):
|
||||
if self.is_liberty_or_newer():
|
||||
services = ("apache2", "haproxy")
|
||||
def _setup_test_object(self, snap_source):
|
||||
self.snap_source = snap_source
|
||||
if self.snap_source:
|
||||
self.config_base = '/var/snap/keystone/common'
|
||||
self.keystone_conf = ('{}/etc/keystone/keystone.conf.d/'
|
||||
'keystone.conf'.format(self.config_base))
|
||||
self.process_services = ["haproxy", "nginx", "uwsgi"]
|
||||
self.init_services = ["snap.keystone.nginx",
|
||||
"snap.keystone.uwsgi"]
|
||||
self.no_origin = ['keystone']
|
||||
self.keystone_config = {'openstack-origin': self.snap_source}
|
||||
self.pymysql = '+pymysql'
|
||||
self.policy_json = ('{}/etc/keystone/keystone.conf.d/policy.json'
|
||||
''.format(self.config_base))
|
||||
self.logging_config = ('{}/etc/keystone/logging.conf'
|
||||
''.format(self.config_base))
|
||||
self.log_file = '{}/log/keystone.log'.format(self.config_base)
|
||||
self.services_to_configs = {'uwsgi': self.keystone_conf}
|
||||
else:
|
||||
services = ("keystone-all", "apache2", "haproxy")
|
||||
self.config_base = ''
|
||||
self.keystone_conf = '/etc/keystone/keystone.conf'
|
||||
self.no_origin = []
|
||||
self.keystone_config = {}
|
||||
self.pymysql = ''
|
||||
self.policy_json = ('{}/etc/keystone/policy.json'
|
||||
''.format(self.config_base))
|
||||
self.logging_config = ('{}/etc/keystone/logging.conf'
|
||||
''.format(self.config_base))
|
||||
self.log_file = '/var/log/keystone/keystone.log'
|
||||
|
||||
if self.is_liberty_or_newer():
|
||||
self.process_services = ["apache2", "haproxy"]
|
||||
self.init_services = ['apache2']
|
||||
self.services_to_configs = {'apache2': self.keystone_conf}
|
||||
else:
|
||||
self.process_services = ["keystone-all", "apache2", "haproxy"]
|
||||
self.init_services = ['keystone']
|
||||
self.services_to_configs = {'keystone-all': self.keystone_conf}
|
||||
|
||||
def _assert_services(self, should_run):
|
||||
for unit in self.keystone_sentries:
|
||||
u.get_unit_process_ids(
|
||||
{unit: services}, expect_success=should_run)
|
||||
{unit: self.process_services}, expect_success=should_run)
|
||||
|
||||
def _add_services(self):
|
||||
"""Add services
|
||||
|
@ -86,8 +123,8 @@ class KeystoneBasicDeployment(OpenStackAmuletDeployment):
|
|||
{'name': 'rabbitmq-server'}, # satisfy wrkload stat
|
||||
{'name': 'cinder'},
|
||||
]
|
||||
super(KeystoneBasicDeployment, self)._add_services(this_service,
|
||||
other_services)
|
||||
super(KeystoneBasicDeployment, self)._add_services(
|
||||
this_service, other_services, no_origin=self.no_origin)
|
||||
|
||||
def _add_relations(self):
|
||||
"""Add all of the relations for the services."""
|
||||
|
@ -99,11 +136,11 @@ class KeystoneBasicDeployment(OpenStackAmuletDeployment):
|
|||
|
||||
def _configure_services(self):
|
||||
"""Configure all of the services."""
|
||||
keystone_config = {
|
||||
self.keystone_config.update({
|
||||
'admin-password': 'openstack',
|
||||
'admin-token': 'ubuntutesting',
|
||||
'preferred-api-version': self.keystone_api_version,
|
||||
}
|
||||
})
|
||||
|
||||
if self.git:
|
||||
amulet_http_proxy = os.environ.get('AMULET_HTTP_PROXY')
|
||||
|
@ -129,7 +166,7 @@ class KeystoneBasicDeployment(OpenStackAmuletDeployment):
|
|||
'http_proxy': amulet_http_proxy,
|
||||
'https_proxy': amulet_http_proxy,
|
||||
}
|
||||
keystone_config['openstack-origin-git'] = \
|
||||
self.keystone_config['openstack-origin-git'] = \
|
||||
yaml.dump(openstack_origin_git)
|
||||
|
||||
pxc_config = {
|
||||
|
@ -143,7 +180,7 @@ class KeystoneBasicDeployment(OpenStackAmuletDeployment):
|
|||
'overwrite': 'true',
|
||||
'ephemeral-unmount': '/mnt'}
|
||||
configs = {
|
||||
'keystone': keystone_config,
|
||||
'keystone': self.keystone_config,
|
||||
'percona-cluster': pxc_config,
|
||||
'cinder': cinder_config,
|
||||
}
|
||||
|
@ -326,11 +363,8 @@ class KeystoneBasicDeployment(OpenStackAmuletDeployment):
|
|||
else:
|
||||
services.update({self.cinder_sentry: ['cinder-api']})
|
||||
|
||||
if self.is_liberty_or_newer():
|
||||
for i in range(0, self.keystone_num_units):
|
||||
services.update({self.keystone_sentries[i]: ['apache2']})
|
||||
else:
|
||||
services.update({self.keystone_sentries[0]: ['keystone']})
|
||||
for i in range(0, self.keystone_num_units):
|
||||
services.update({self.keystone_sentries[i]: self.init_services})
|
||||
|
||||
ret = u.validate_services_by_name(services)
|
||||
if ret:
|
||||
|
@ -703,22 +737,22 @@ class KeystoneBasicDeployment(OpenStackAmuletDeployment):
|
|||
"""Verify the data in the keystone config file,
|
||||
comparing some of the variables vs relation data."""
|
||||
u.log.debug('Checking keystone config file...')
|
||||
conf = '/etc/keystone/keystone.conf'
|
||||
ks_ci_rel = self.keystone_sentries[0].relation(
|
||||
'identity-service',
|
||||
'cinder:identity-service')
|
||||
my_ks_rel = self.pxc_sentry.relation('shared-db',
|
||||
'keystone:shared-db')
|
||||
db_uri = "mysql://{}:{}@{}/{}".format('keystone',
|
||||
my_ks_rel['password'],
|
||||
my_ks_rel['db_host'],
|
||||
'keystone')
|
||||
db_uri = "mysql{}://{}:{}@{}/{}".format(self.pymysql,
|
||||
'keystone',
|
||||
my_ks_rel['password'],
|
||||
my_ks_rel['db_host'],
|
||||
'keystone')
|
||||
expected = {
|
||||
'DEFAULT': {
|
||||
'debug': 'False',
|
||||
'admin_token': ks_ci_rel['admin_token'],
|
||||
'use_syslog': 'False',
|
||||
'log_config_append': '/etc/keystone/logging.conf',
|
||||
'log_config_append': (self.logging_config),
|
||||
'public_endpoint': u.valid_url, # get specific
|
||||
'admin_endpoint': u.valid_url, # get specific
|
||||
},
|
||||
|
@ -756,7 +790,8 @@ class KeystoneBasicDeployment(OpenStackAmuletDeployment):
|
|||
|
||||
for unit in self.keystone_sentries:
|
||||
for section, pairs in expected.iteritems():
|
||||
ret = u.validate_config_data(unit, conf, section, pairs)
|
||||
ret = u.validate_config_data(unit, self.keystone_conf, section,
|
||||
pairs)
|
||||
if ret:
|
||||
message = "keystone config error: {}".format(ret)
|
||||
amulet.raise_status(amulet.FAIL, msg=message)
|
||||
|
@ -768,7 +803,6 @@ class KeystoneBasicDeployment(OpenStackAmuletDeployment):
|
|||
return
|
||||
u.log.debug('Checking keystone v3 policy.json file')
|
||||
self.set_api_version(3)
|
||||
conf = '/etc/keystone/policy.json'
|
||||
ks_ci_rel = self.keystone_sentries[0].relation(
|
||||
'identity-service',
|
||||
'cinder:identity-service')
|
||||
|
@ -804,7 +838,7 @@ class KeystoneBasicDeployment(OpenStackAmuletDeployment):
|
|||
}
|
||||
|
||||
for unit in self.keystone_sentries:
|
||||
data = json.loads(unit.file_contents(conf))
|
||||
data = json.loads(unit.file_contents(self.policy_json))
|
||||
ret = u._validate_dict_data(expected, data)
|
||||
if ret:
|
||||
message = "keystone policy.json error: {}".format(ret)
|
||||
|
@ -815,7 +849,6 @@ class KeystoneBasicDeployment(OpenStackAmuletDeployment):
|
|||
def test_302_keystone_logging_config(self):
|
||||
"""Verify the data in the keystone logging config file"""
|
||||
u.log.debug('Checking keystone config file...')
|
||||
conf = '/etc/keystone/logging.conf'
|
||||
expected = {
|
||||
'logger_root': {
|
||||
'level': 'WARNING',
|
||||
|
@ -826,13 +859,14 @@ class KeystoneBasicDeployment(OpenStackAmuletDeployment):
|
|||
},
|
||||
'handler_file': {
|
||||
'level': 'DEBUG',
|
||||
'args': "('/var/log/keystone/keystone.log', 'a')"
|
||||
'args': "('{}', 'a')".format(self.log_file)
|
||||
}
|
||||
}
|
||||
|
||||
for unit in self.keystone_sentries:
|
||||
for section, pairs in expected.iteritems():
|
||||
ret = u.validate_config_data(unit, conf, section, pairs)
|
||||
ret = u.validate_config_data(unit, self.logging_config,
|
||||
section, pairs)
|
||||
if ret:
|
||||
message = "keystone logging config error: {}".format(ret)
|
||||
amulet.raise_status(amulet.FAIL, msg=message)
|
||||
|
@ -847,19 +881,13 @@ class KeystoneBasicDeployment(OpenStackAmuletDeployment):
|
|||
set_default = {'use-syslog': 'False'}
|
||||
set_alternate = {'use-syslog': 'True'}
|
||||
|
||||
# Services which are expected to restart upon config change,
|
||||
# and corresponding config files affected by the change
|
||||
if self.is_liberty_or_newer():
|
||||
services = {'apache2': '/etc/keystone/keystone.conf'}
|
||||
else:
|
||||
services = {'keystone-all': '/etc/keystone/keystone.conf'}
|
||||
# Make config change, check for service restarts
|
||||
u.log.debug('Making config change on {}...'.format(juju_service))
|
||||
mtime = u.get_sentry_time(sentry)
|
||||
self.d.configure(juju_service, set_alternate)
|
||||
|
||||
sleep_time = 30
|
||||
for s, conf_file in services.iteritems():
|
||||
for s, conf_file in self.services_to_configs.iteritems():
|
||||
u.log.debug("Checking that service restarted: {}".format(s))
|
||||
if not u.validate_service_config_changed(sentry, mtime, s,
|
||||
conf_file,
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright 2016 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.
|
||||
|
||||
"""Amulet tests on a basic keystone deployment on xenial-ocata."""
|
||||
|
||||
from basic_deployment import KeystoneBasicDeployment
|
||||
|
||||
if __name__ == '__main__':
|
||||
deployment = KeystoneBasicDeployment(series='xenial',
|
||||
openstack='cloud:xenial-ocata',
|
||||
snap_source='snap:ocata/edge',
|
||||
source='cloud:xenial-updates/ocata')
|
||||
deployment.run_tests()
|
|
@ -17,9 +17,12 @@ from mock import patch
|
|||
|
||||
from test_utils import CharmTestCase
|
||||
|
||||
with patch('actions.hooks.keystone_utils.register_configs') as configs:
|
||||
configs.return_value = 'test-config'
|
||||
import actions.actions
|
||||
with patch('actions.hooks.charmhelpers.contrib.openstack.utils.'
|
||||
'snap_install_requested') as snap_install_requested, \
|
||||
patch('actions.hooks.keystone_utils.register_configs') as configs:
|
||||
snap_install_requested.return_value = False
|
||||
configs.return_value = 'test-config'
|
||||
import actions.actions
|
||||
|
||||
|
||||
class PauseTestCase(CharmTestCase):
|
||||
|
|
|
@ -24,13 +24,17 @@ mock_apt.apt_pkg = MagicMock()
|
|||
|
||||
# NOTE(hopem): we have to mock hooks.charmhelpers (not charmhelpers)
|
||||
# otherwise the mock is not applied to action.hooks.*
|
||||
with patch('hooks.charmhelpers.contrib.hardening.harden.harden') as mock_dec:
|
||||
with patch('hooks.charmhelpers.contrib.hardening.harden.harden') as mock_dec, \
|
||||
patch('hooks.charmhelpers.contrib.openstack.utils.'
|
||||
'snap_install_requested') as snap_install_requested, \
|
||||
patch('hooks.keystone_utils.register_configs') as register_configs, \
|
||||
patch('hooks.keystone_utils.os_release') as os_release:
|
||||
|
||||
snap_install_requested.return_value = False
|
||||
mock_dec.side_effect = (lambda *dargs, **dkwargs: lambda f:
|
||||
lambda *args, **kwargs: f(*args, **kwargs))
|
||||
with patch('hooks.keystone_utils.register_configs') as register_configs:
|
||||
with patch('hooks.keystone_utils.os_release') as os_release:
|
||||
os_release.return_value = 'juno'
|
||||
import git_reinstall
|
||||
os_release.return_value = 'juno'
|
||||
import git_reinstall
|
||||
|
||||
from test_utils import (
|
||||
CharmTestCase
|
||||
|
|
|
@ -17,7 +17,10 @@ import os
|
|||
|
||||
os.environ['JUJU_UNIT_NAME'] = 'keystone'
|
||||
|
||||
import openstack_upgrade
|
||||
with patch('charmhelpers.contrib.openstack.utils'
|
||||
'.snap_install_requested') as snap_install_requested:
|
||||
snap_install_requested.return_value = False
|
||||
import openstack_upgrade
|
||||
|
||||
from test_utils import (
|
||||
CharmTestCase
|
||||
|
|
|
@ -14,8 +14,12 @@
|
|||
|
||||
import os
|
||||
|
||||
import keystone_context as context
|
||||
from mock import patch, MagicMock
|
||||
with patch('charmhelpers.contrib.openstack.'
|
||||
'utils.snap_install_requested') as snap_install_requested:
|
||||
snap_install_requested.return_value = False
|
||||
import keystone_utils # noqa
|
||||
import keystone_context as context
|
||||
|
||||
from test_utils import (
|
||||
CharmTestCase
|
||||
|
@ -166,7 +170,9 @@ class TestKeystoneContexts(CharmTestCase):
|
|||
ctxt = context.KeystoneLoggingContext()
|
||||
|
||||
mock_config.return_value = None
|
||||
self.assertEqual({'log_level': None}, ctxt())
|
||||
self.assertEqual({'log_level': None,
|
||||
'log_file': '/var/log/keystone/keystone.log'},
|
||||
ctxt())
|
||||
|
||||
@patch.object(context, 'is_elected_leader')
|
||||
def test_token_flush_context(self, mock_is_elected_leader):
|
||||
|
|
|
@ -25,7 +25,10 @@ from test_utils import CharmTestCase
|
|||
sys.modules['apt'] = MagicMock()
|
||||
|
||||
os.environ['JUJU_UNIT_NAME'] = 'keystone'
|
||||
with patch('charmhelpers.core.hookenv.config') as config:
|
||||
with patch('charmhelpers.core.hookenv.config') as config, \
|
||||
patch('charmhelpers.contrib.openstack.'
|
||||
'utils.snap_install_requested') as snap_install_requested:
|
||||
snap_install_requested.return_value = False
|
||||
config.return_value = 'keystone'
|
||||
import keystone_utils as utils
|
||||
|
||||
|
@ -69,6 +72,7 @@ TO_PATCH = [
|
|||
# charmhelpers.contrib.openstack.utils
|
||||
'configure_installation_source',
|
||||
'git_install_requested',
|
||||
'snap_install_requested',
|
||||
# charmhelpers.contrib.openstack.ip
|
||||
'resolve_address',
|
||||
# charmhelpers.contrib.openstack.ha.utils
|
||||
|
@ -120,6 +124,7 @@ class KeystoneRelationTests(CharmTestCase):
|
|||
super(KeystoneRelationTests, self).setUp(hooks, TO_PATCH)
|
||||
self.config.side_effect = self.test_config.get
|
||||
self.ssh_user = 'juju_keystone'
|
||||
self.snap_install_requested.return_value = False
|
||||
|
||||
@patch.object(utils, 'os_release')
|
||||
@patch.object(utils, 'git_install_requested')
|
||||
|
|
|
@ -19,7 +19,10 @@ from base64 import b64encode
|
|||
import subprocess
|
||||
|
||||
os.environ['JUJU_UNIT_NAME'] = 'keystone'
|
||||
with patch('charmhelpers.core.hookenv.config') as config:
|
||||
with patch('charmhelpers.core.hookenv.config') as config, \
|
||||
patch('charmhelpers.contrib.openstack.'
|
||||
'utils.snap_install_requested') as snap_install_requested:
|
||||
snap_install_requested.return_value = False
|
||||
import keystone_utils as utils
|
||||
|
||||
TO_PATCH = [
|
||||
|
@ -49,6 +52,7 @@ TO_PATCH = [
|
|||
'service_restart',
|
||||
'service_stop',
|
||||
'service_start',
|
||||
'snap_install_requested',
|
||||
'relation_get',
|
||||
'relation_set',
|
||||
'relation_ids',
|
||||
|
@ -86,6 +90,7 @@ class TestKeystoneUtils(CharmTestCase):
|
|||
def setUp(self):
|
||||
super(TestKeystoneUtils, self).setUp(utils, TO_PATCH)
|
||||
self.config.side_effect = self.test_config.get
|
||||
self.snap_install_requested.return_value = False
|
||||
|
||||
self.ctxt = MagicMock()
|
||||
self.rsc_map = {
|
||||
|
@ -138,6 +143,7 @@ class TestKeystoneUtils(CharmTestCase):
|
|||
@patch('charmhelpers.contrib.openstack.utils.config')
|
||||
def test_determine_packages(self, _config):
|
||||
self.os_release.return_value = 'havana'
|
||||
self.snap_install_requested.return_value = False
|
||||
_config.return_value = None
|
||||
result = utils.determine_packages()
|
||||
ex = utils.BASE_PACKAGES + ['keystone', 'python-keystoneclient']
|
||||
|
|
Loading…
Reference in New Issue