Add support for OpenStack Queens.
Update charm to support Ceilometer@Queens; specifically: - Removal of Ceilometer API service - Removal of ceilometer-collector service Most of this change is related to dropping of these services; In addition its now possible to complete a ceilometer-upgrade without mongodb being configured. As this charm no longer provides any endpoints to keystone, for Queens the identity-credentials relation is required instead of the identity-service relation. Change-Id: I3cefc24ffc9a0e60f446fbbdff603dfad37f7baa
This commit is contained in:
parent
a34db0aa8e
commit
4c450fed8c
15
README.md
15
README.md
|
@ -17,18 +17,31 @@ default install Ceilometer and its dependencies from the Cloud Archive.
|
|||
Usage
|
||||
-----
|
||||
|
||||
In order to deploy Ceilometer service, the MongoDB service is required:
|
||||
In order to deploy Ceilometer service (prior to Queens), the MongoDB
|
||||
service is required:
|
||||
|
||||
juju deploy mongodb
|
||||
juju deploy ceilometer
|
||||
juju add-relation ceilometer mongodb
|
||||
|
||||
For OpenStack Queens or later, Gnocchi should be used instead of MongoDB
|
||||
for resource, metrics and measure storage:
|
||||
|
||||
juju add-relation ceilometer gnocchi
|
||||
|
||||
then Keystone and Rabbit relationships need to be established:
|
||||
|
||||
juju add-relation ceilometer rabbitmq
|
||||
juju add-relation ceilometer keystone:identity-service
|
||||
juju add-relation ceilometer keystone:identity-notifications
|
||||
|
||||
For OpenStack Queens, the identity-service relation must be replaced
|
||||
with the identity-credentials relation:
|
||||
|
||||
juju add-relation ceilometer keystone:identity-credentials
|
||||
|
||||
Ceilometer@Queens does not provide an API service.
|
||||
|
||||
In order to capture the calculations, a Ceilometer compute agent needs to be
|
||||
installed in each nova node, and be related with Ceilometer service:
|
||||
|
||||
|
|
|
@ -334,10 +334,7 @@ class IdentityServiceContext(OSContextGenerator):
|
|||
self.rel_name = rel_name
|
||||
self.interfaces = [self.rel_name]
|
||||
|
||||
def __call__(self):
|
||||
log('Generating template context for ' + self.rel_name, level=DEBUG)
|
||||
ctxt = {}
|
||||
|
||||
def _setup_pki_cache(self):
|
||||
if self.service and self.service_user:
|
||||
# This is required for pki token signing if we don't want /tmp to
|
||||
# be used.
|
||||
|
@ -347,6 +344,15 @@ class IdentityServiceContext(OSContextGenerator):
|
|||
mkdir(path=cachedir, owner=self.service_user,
|
||||
group=self.service_user, perms=0o700)
|
||||
|
||||
return cachedir
|
||||
return None
|
||||
|
||||
def __call__(self):
|
||||
log('Generating template context for ' + self.rel_name, level=DEBUG)
|
||||
ctxt = {}
|
||||
|
||||
cachedir = self._setup_pki_cache()
|
||||
if cachedir:
|
||||
ctxt['signing_dir'] = cachedir
|
||||
|
||||
for rid in relation_ids(self.rel_name):
|
||||
|
@ -385,6 +391,62 @@ class IdentityServiceContext(OSContextGenerator):
|
|||
return {}
|
||||
|
||||
|
||||
class IdentityCredentialsContext(IdentityServiceContext):
|
||||
'''Context for identity-credentials interface type'''
|
||||
|
||||
def __init__(self,
|
||||
service=None,
|
||||
service_user=None,
|
||||
rel_name='identity-credentials'):
|
||||
super(IdentityCredentialsContext, self).__init__(service,
|
||||
service_user,
|
||||
rel_name)
|
||||
|
||||
def __call__(self):
|
||||
log('Generating template context for ' + self.rel_name, level=DEBUG)
|
||||
ctxt = {}
|
||||
|
||||
cachedir = self._setup_pki_cache()
|
||||
if cachedir:
|
||||
ctxt['signing_dir'] = cachedir
|
||||
|
||||
for rid in relation_ids(self.rel_name):
|
||||
self.related = True
|
||||
for unit in related_units(rid):
|
||||
rdata = relation_get(rid=rid, unit=unit)
|
||||
credentials_host = rdata.get('credentials_host')
|
||||
credentials_host = (
|
||||
format_ipv6_addr(credentials_host) or credentials_host
|
||||
)
|
||||
auth_host = rdata.get('auth_host')
|
||||
auth_host = format_ipv6_addr(auth_host) or auth_host
|
||||
svc_protocol = rdata.get('credentials_protocol') or 'http'
|
||||
auth_protocol = rdata.get('auth_protocol') or 'http'
|
||||
api_version = rdata.get('api_version') or '2.0'
|
||||
ctxt.update({
|
||||
'service_port': rdata.get('credentials_port'),
|
||||
'service_host': credentials_host,
|
||||
'auth_host': auth_host,
|
||||
'auth_port': rdata.get('auth_port'),
|
||||
'admin_tenant_name': rdata.get('credentials_project'),
|
||||
'admin_tenant_id': rdata.get('credentials_project_id'),
|
||||
'admin_user': rdata.get('credentials_username'),
|
||||
'admin_password': rdata.get('credentials_password'),
|
||||
'service_protocol': svc_protocol,
|
||||
'auth_protocol': auth_protocol,
|
||||
'api_version': api_version
|
||||
})
|
||||
|
||||
if float(api_version) > 2:
|
||||
ctxt.update({'admin_domain_name':
|
||||
rdata.get('domain')})
|
||||
|
||||
if self.context_complete(ctxt):
|
||||
return ctxt
|
||||
|
||||
return {}
|
||||
|
||||
|
||||
class AMQPContext(OSContextGenerator):
|
||||
|
||||
def __init__(self, ssl_dir=None, rel_name='amqp', relation_prefix=None):
|
||||
|
|
|
@ -2045,14 +2045,25 @@ def token_cache_pkgs(source=None, release=None):
|
|||
|
||||
def update_json_file(filename, items):
|
||||
"""Updates the json `filename` with a given dict.
|
||||
:param filename: json filename (i.e.: /etc/glance/policy.json)
|
||||
:param filename: path to json file (e.g. /etc/glance/policy.json)
|
||||
:param items: dict of items to update
|
||||
"""
|
||||
if not items:
|
||||
return
|
||||
|
||||
with open(filename) as fd:
|
||||
policy = json.load(fd)
|
||||
|
||||
# Compare before and after and if nothing has changed don't write the file
|
||||
# since that could cause unnecessary service restarts.
|
||||
before = json.dumps(policy, indent=4, sort_keys=True)
|
||||
policy.update(items)
|
||||
after = json.dumps(policy, indent=4, sort_keys=True)
|
||||
if before == after:
|
||||
return
|
||||
|
||||
with open(filename, "w") as fd:
|
||||
fd.write(json.dumps(policy, indent=4))
|
||||
fd.write(after)
|
||||
|
||||
|
||||
@cached
|
||||
|
|
|
@ -621,16 +621,24 @@ def create_erasure_profile(service, profile_name, erasure_plugin_name='jerasure'
|
|||
:param durability_estimator: int
|
||||
:return: None. Can raise CalledProcessError
|
||||
"""
|
||||
version = ceph_version()
|
||||
|
||||
# Ensure this failure_domain is allowed by Ceph
|
||||
validator(failure_domain, six.string_types,
|
||||
['chassis', 'datacenter', 'host', 'osd', 'pdu', 'pod', 'rack', 'region', 'room', 'root', 'row'])
|
||||
|
||||
cmd = ['ceph', '--id', service, 'osd', 'erasure-code-profile', 'set', profile_name,
|
||||
'plugin=' + erasure_plugin_name, 'k=' + str(data_chunks), 'm=' + str(coding_chunks),
|
||||
'ruleset_failure_domain=' + failure_domain]
|
||||
'plugin=' + erasure_plugin_name, 'k=' + str(data_chunks), 'm=' + str(coding_chunks)
|
||||
]
|
||||
if locality is not None and durability_estimator is not None:
|
||||
raise ValueError("create_erasure_profile should be called with k, m and one of l or c but not both.")
|
||||
|
||||
# failure_domain changed in luminous
|
||||
if version and version >= '12.0.0':
|
||||
cmd.append('crush-failure-domain=' + failure_domain)
|
||||
else:
|
||||
cmd.append('ruleset-failure-domain=' + failure_domain)
|
||||
|
||||
# Add plugin specific information
|
||||
if locality is not None:
|
||||
# For local erasure codes
|
||||
|
@ -1064,14 +1072,24 @@ class CephBrokerRq(object):
|
|||
self.ops = []
|
||||
|
||||
def add_op_request_access_to_group(self, name, namespace=None,
|
||||
permission=None, key_name=None):
|
||||
permission=None, key_name=None,
|
||||
object_prefix_permissions=None):
|
||||
"""
|
||||
Adds the requested permissions to the current service's Ceph key,
|
||||
allowing the key to access only the specified pools
|
||||
allowing the key to access only the specified pools or
|
||||
object prefixes. object_prefix_permissions should be a dictionary
|
||||
keyed on the permission with the corresponding value being a list
|
||||
of prefixes to apply that permission to.
|
||||
{
|
||||
'rwx': ['prefix1', 'prefix2'],
|
||||
'class-read': ['prefix3']}
|
||||
"""
|
||||
self.ops.append({'op': 'add-permissions-to-key', 'group': name,
|
||||
'namespace': namespace, 'name': key_name or service_name(),
|
||||
'group-permission': permission})
|
||||
self.ops.append({
|
||||
'op': 'add-permissions-to-key', 'group': name,
|
||||
'namespace': namespace,
|
||||
'name': key_name or service_name(),
|
||||
'group-permission': permission,
|
||||
'object-prefix-permissions': object_prefix_permissions})
|
||||
|
||||
def add_op_create_pool(self, name, replica_count=3, pg_num=None,
|
||||
weight=None, group=None, namespace=None):
|
||||
|
@ -1107,7 +1125,10 @@ class CephBrokerRq(object):
|
|||
def _ops_equal(self, other):
|
||||
if len(self.ops) == len(other.ops):
|
||||
for req_no in range(0, len(self.ops)):
|
||||
for key in ['replicas', 'name', 'op', 'pg_num', 'weight']:
|
||||
for key in [
|
||||
'replicas', 'name', 'op', 'pg_num', 'weight',
|
||||
'group', 'group-namespace', 'group-permission',
|
||||
'object-prefix-permissions']:
|
||||
if self.ops[req_no].get(key) != other.ops[req_no].get(key):
|
||||
return False
|
||||
else:
|
||||
|
|
|
@ -26,6 +26,7 @@ from charmhelpers.fetch import (
|
|||
)
|
||||
from charmhelpers.core.hookenv import (
|
||||
open_port,
|
||||
close_port,
|
||||
relation_get,
|
||||
relation_set,
|
||||
relation_ids,
|
||||
|
@ -48,6 +49,8 @@ from charmhelpers.contrib.openstack.utils import (
|
|||
openstack_upgrade_available,
|
||||
pausable_restart_on_change as restart_on_change,
|
||||
is_unit_paused_set,
|
||||
get_os_codename_install_source,
|
||||
CompareOpenStackReleases,
|
||||
)
|
||||
from charmhelpers.contrib.openstack.ha.utils import (
|
||||
update_dns_ha_resource_params,
|
||||
|
@ -112,7 +115,6 @@ def install():
|
|||
status_set('maintenance', 'Installing packages')
|
||||
apt_update(fatal=True)
|
||||
apt_install(packages, fatal=True)
|
||||
open_port(CEILOMETER_PORT)
|
||||
if init_is_systemd():
|
||||
# NOTE(jamespage): ensure systemd override folder exists prior to
|
||||
# attempting to write override.conf
|
||||
|
@ -146,6 +148,8 @@ def metric_service_joined():
|
|||
"shared-db-relation-departed",
|
||||
"identity-service-relation-changed",
|
||||
"identity-service-relation-departed",
|
||||
"identity-credentials-relation-changed",
|
||||
"identity-credentials-relation-departed",
|
||||
"metric-service-relation-changed",
|
||||
"metric-service-relation-departed")
|
||||
@restart_on_change(restart_map())
|
||||
|
@ -159,8 +163,13 @@ def any_changed():
|
|||
# and mongodb to be configured to successfully
|
||||
# upgrade the underlying data stores.
|
||||
if ('metric-service' in CONFIGS.complete_contexts() and
|
||||
'identity-service' in CONFIGS.complete_contexts() and
|
||||
'mongodb' in CONFIGS.complete_contexts()):
|
||||
'identity-service' in CONFIGS.complete_contexts()):
|
||||
cmp_codename = CompareOpenStackReleases(
|
||||
get_os_codename_install_source(config('openstack-origin')))
|
||||
# NOTE(jamespage): however at queens, this limitation has gone!
|
||||
if (cmp_codename < 'queens' and
|
||||
'mongodb' not in CONFIGS.complete_contexts()):
|
||||
return
|
||||
ceilometer_upgrade()
|
||||
|
||||
|
||||
|
@ -168,6 +177,10 @@ def configure_https():
|
|||
"""Enables SSL API Apache config if appropriate."""
|
||||
# need to write all to ensure changes to the entire request pipeline
|
||||
# propagate (c-api, haprxy, apache)
|
||||
cmp_codename = CompareOpenStackReleases(
|
||||
get_os_codename_install_source(config('openstack-origin')))
|
||||
if cmp_codename >= 'queens':
|
||||
return
|
||||
CONFIGS.write_all()
|
||||
if 'https' in CONFIGS.complete_contexts():
|
||||
cmd = ['a2ensite', 'openstack_https_frontend']
|
||||
|
@ -200,9 +213,23 @@ def config_changed():
|
|||
# reload ensures port override is set correctly
|
||||
reload_systemd()
|
||||
ceilometer_joined()
|
||||
|
||||
cmp_codename = CompareOpenStackReleases(
|
||||
get_os_codename_install_source(config('openstack-origin')))
|
||||
if cmp_codename < 'queens':
|
||||
open_port(CEILOMETER_PORT)
|
||||
else:
|
||||
close_port(CEILOMETER_PORT)
|
||||
|
||||
configure_https()
|
||||
|
||||
# NOTE(jamespage): Iterate identity-{service,credentials} relations
|
||||
# to pickup any required databag changes on these
|
||||
# relations.
|
||||
for rid in relation_ids('identity-service'):
|
||||
keystone_joined(relid=rid)
|
||||
for rid in relation_ids('identity-credentials'):
|
||||
keystone_credentials_joined(relid=rid)
|
||||
|
||||
# Define the new ocf resource and use the key delete_resources to delete
|
||||
# legacy resource for >= Liberty since the ceilometer-agent-central moved
|
||||
|
@ -350,8 +377,21 @@ def ha_changed():
|
|||
keystone_joined(relid=rid)
|
||||
|
||||
|
||||
@hooks.hook("identity-credentials-relation-joined")
|
||||
def keystone_credentials_joined(relid=None):
|
||||
relation_set(relation_id=relid,
|
||||
username=CEILOMETER_SERVICE,
|
||||
requested_roles=CEILOMETER_ROLE)
|
||||
|
||||
|
||||
@hooks.hook("identity-service-relation-joined")
|
||||
def keystone_joined(relid=None):
|
||||
cmp_codename = CompareOpenStackReleases(
|
||||
get_os_codename_install_source(config('openstack-origin')))
|
||||
if cmp_codename >= 'queens':
|
||||
log('Skipping endpoint registration for >= Queens', level=DEBUG)
|
||||
return
|
||||
|
||||
if config('vip') and not is_clustered():
|
||||
log('Defering registration until clustered', level=DEBUG)
|
||||
return
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
ceilometer_hooks.py
|
|
@ -0,0 +1 @@
|
|||
ceilometer_hooks.py
|
|
@ -0,0 +1 @@
|
|||
ceilometer_hooks.py
|
|
@ -0,0 +1 @@
|
|||
ceilometer_hooks.py
|
|
@ -16,7 +16,7 @@ from charmhelpers.core.hookenv import (
|
|||
relation_ids,
|
||||
relation_get,
|
||||
related_units,
|
||||
config
|
||||
config,
|
||||
)
|
||||
|
||||
from charmhelpers.contrib.openstack.utils import (
|
||||
|
|
|
@ -69,6 +69,11 @@ CEILOMETER_BASE_SERVICES = [
|
|||
'ceilometer-api',
|
||||
]
|
||||
|
||||
QUEENS_SERVICES = [
|
||||
'ceilometer-agent-central',
|
||||
'ceilometer-agent-notification'
|
||||
]
|
||||
|
||||
ICEHOUSE_SERVICES = [
|
||||
'ceilometer-alarm-notifier',
|
||||
'ceilometer-alarm-evaluator',
|
||||
|
@ -101,6 +106,11 @@ MITAKA_PACKAGES = [
|
|||
'ceilometer-agent-notification'
|
||||
]
|
||||
|
||||
QUEENS_PACKAGES = [
|
||||
'ceilometer-agent-central',
|
||||
'ceilometer-agent-notification'
|
||||
]
|
||||
|
||||
REQUIRED_INTERFACES = {
|
||||
'database': ['mongodb'],
|
||||
'messaging': ['amqp'],
|
||||
|
@ -112,6 +122,23 @@ SVC = 'ceilometer'
|
|||
WSGI_CEILOMETER_API_CONF = '/etc/apache2/sites-enabled/wsgi-openstack-api.conf'
|
||||
PACKAGE_CEILOMETER_API_CONF = '/etc/apache2/sites-enabled/ceilometer-api.conf'
|
||||
|
||||
QUEENS_CONFIG_FILES = OrderedDict([
|
||||
(CEILOMETER_CONF, {
|
||||
'hook_contexts': [
|
||||
context.IdentityCredentialsContext(service=SVC,
|
||||
service_user=SVC),
|
||||
context.AMQPContext(ssl_dir=CEILOMETER_CONF_DIR),
|
||||
LoggingConfigContext(),
|
||||
MongoDBContext(),
|
||||
CeilometerContext(),
|
||||
context.SyslogContext(),
|
||||
context.MemcacheContext(),
|
||||
MetricServiceContext(),
|
||||
context.WorkerConfigContext()],
|
||||
'services': QUEENS_SERVICES
|
||||
}),
|
||||
])
|
||||
|
||||
CONFIG_FILES = OrderedDict([
|
||||
(CEILOMETER_CONF, {
|
||||
'hook_contexts': [context.IdentityServiceContext(service=SVC,
|
||||
|
@ -124,7 +151,8 @@ CONFIG_FILES = OrderedDict([
|
|||
context.SyslogContext(),
|
||||
HAProxyContext(),
|
||||
context.MemcacheContext(),
|
||||
MetricServiceContext()],
|
||||
MetricServiceContext(),
|
||||
context.WorkerConfigContext()],
|
||||
'services': CEILOMETER_BASE_SERVICES
|
||||
}),
|
||||
(CEILOMETER_API_SYSTEMD_CONF, {
|
||||
|
@ -165,36 +193,46 @@ def register_configs():
|
|||
# if called without anything installed (eg during install hook)
|
||||
# just default to earliest supported release. configs dont get touched
|
||||
# till post-install, anyway.
|
||||
|
||||
release = (get_os_codename_package('ceilometer-common', fatal=False) or
|
||||
'grizzly')
|
||||
configs = templating.OSConfigRenderer(templates_dir=TEMPLATES,
|
||||
openstack_release=release)
|
||||
|
||||
for conf in (CEILOMETER_CONF, HAPROXY_CONF):
|
||||
configs.register(conf, CONFIG_FILES[conf]['hook_contexts'])
|
||||
|
||||
if init_is_systemd():
|
||||
configs.register(
|
||||
CEILOMETER_API_SYSTEMD_CONF,
|
||||
CONFIG_FILES[CEILOMETER_API_SYSTEMD_CONF]['hook_contexts']
|
||||
)
|
||||
|
||||
if os.path.exists('/etc/apache2/conf-available'):
|
||||
configs.register(HTTPS_APACHE_24_CONF,
|
||||
CONFIG_FILES[HTTPS_APACHE_24_CONF]['hook_contexts'])
|
||||
if CompareOpenStackReleases(release) >= 'queens':
|
||||
for conf in QUEENS_CONFIG_FILES:
|
||||
configs.register(conf, QUEENS_CONFIG_FILES[conf]['hook_contexts'])
|
||||
else:
|
||||
configs.register(HTTPS_APACHE_CONF,
|
||||
CONFIG_FILES[HTTPS_APACHE_CONF]['hook_contexts'])
|
||||
if enable_memcache(release=release):
|
||||
configs.register(MEMCACHED_CONF, [context.MemcacheContext()])
|
||||
for conf in (CEILOMETER_CONF, HAPROXY_CONF):
|
||||
configs.register(conf, CONFIG_FILES[conf]['hook_contexts'])
|
||||
|
||||
if run_in_apache():
|
||||
wsgi_script = "/usr/share/ceilometer/app.wsgi"
|
||||
configs.register(WSGI_CEILOMETER_API_CONF,
|
||||
[context.WSGIWorkerConfigContext(name="ceilometer",
|
||||
script=wsgi_script),
|
||||
CeilometerContext(),
|
||||
HAProxyContext()])
|
||||
if init_is_systemd():
|
||||
configs.register(
|
||||
CEILOMETER_API_SYSTEMD_CONF,
|
||||
CONFIG_FILES[CEILOMETER_API_SYSTEMD_CONF]['hook_contexts']
|
||||
)
|
||||
|
||||
if os.path.exists('/etc/apache2/conf-available'):
|
||||
configs.register(
|
||||
HTTPS_APACHE_24_CONF,
|
||||
CONFIG_FILES[HTTPS_APACHE_24_CONF]['hook_contexts']
|
||||
)
|
||||
else:
|
||||
configs.register(
|
||||
HTTPS_APACHE_CONF,
|
||||
CONFIG_FILES[HTTPS_APACHE_CONF]['hook_contexts']
|
||||
)
|
||||
if enable_memcache(release=release):
|
||||
configs.register(MEMCACHED_CONF, [context.MemcacheContext()])
|
||||
|
||||
if run_in_apache():
|
||||
wsgi_script = "/usr/share/ceilometer/app.wsgi"
|
||||
configs.register(
|
||||
WSGI_CEILOMETER_API_CONF,
|
||||
[context.WSGIWorkerConfigContext(name="ceilometer",
|
||||
script=wsgi_script),
|
||||
CeilometerContext(),
|
||||
HAProxyContext()]
|
||||
)
|
||||
return configs
|
||||
|
||||
|
||||
|
@ -206,8 +244,14 @@ def restart_map():
|
|||
:returns: dict: A dictionary mapping config file to lists of services
|
||||
that should be restarted when file changes.
|
||||
"""
|
||||
cmp_codename = CompareOpenStackReleases(
|
||||
get_os_codename_install_source(config('openstack-origin')))
|
||||
if cmp_codename >= 'queens':
|
||||
_config_files = QUEENS_CONFIG_FILES
|
||||
else:
|
||||
_config_files = CONFIG_FILES
|
||||
_map = {}
|
||||
for f, ctxt in CONFIG_FILES.iteritems():
|
||||
for f, ctxt in _config_files.items():
|
||||
svcs = []
|
||||
for svc in ctxt['services']:
|
||||
svcs.append(svc)
|
||||
|
@ -217,10 +261,11 @@ def restart_map():
|
|||
if svcs:
|
||||
_map[f] = svcs
|
||||
|
||||
if enable_memcache(source=config('openstack-origin')):
|
||||
if (cmp_codename < 'queens' and
|
||||
enable_memcache(source=config('openstack-origin'))):
|
||||
_map[MEMCACHED_CONF] = ['memcached']
|
||||
|
||||
if run_in_apache():
|
||||
if cmp_codename < 'queens' and run_in_apache():
|
||||
for cfile in _map:
|
||||
svcs = _map[cfile]
|
||||
if 'ceilometer-api' in svcs:
|
||||
|
@ -254,14 +299,24 @@ def determine_ports():
|
|||
"""
|
||||
# TODO(ajkavanagh) - determine what other ports the service listens on
|
||||
# apart from the main CEILOMETER port
|
||||
ports = [CEILOMETER_PORT]
|
||||
return ports
|
||||
cmp_codename = CompareOpenStackReleases(
|
||||
get_os_codename_install_source(config('openstack-origin')))
|
||||
if cmp_codename >= 'queens':
|
||||
# NOTE(jamespage): No API service for queens or later
|
||||
return []
|
||||
return [CEILOMETER_PORT]
|
||||
|
||||
|
||||
def get_ceilometer_context():
|
||||
""" Retrieve a map of all current relation data for agent configuration """
|
||||
cmp_codename = CompareOpenStackReleases(
|
||||
get_os_codename_install_source(config('openstack-origin')))
|
||||
if cmp_codename >= 'queens':
|
||||
_config_files = QUEENS_CONFIG_FILES
|
||||
else:
|
||||
_config_files = CONFIG_FILES
|
||||
ctxt = {}
|
||||
for hcontext in CONFIG_FILES[CEILOMETER_CONF]['hook_contexts']:
|
||||
for hcontext in _config_files[CEILOMETER_CONF]['hook_contexts']:
|
||||
ctxt.update(hcontext())
|
||||
return ctxt
|
||||
|
||||
|
@ -301,9 +356,9 @@ def do_openstack_upgrade(configs):
|
|||
def ceilometer_release_services():
|
||||
cmp_codename = CompareOpenStackReleases(
|
||||
get_os_codename_install_source(config('openstack-origin')))
|
||||
if cmp_codename >= 'mitaka':
|
||||
if cmp_codename >= 'mitaka' and cmp_codename < 'queens':
|
||||
return MITAKA_SERVICES
|
||||
elif cmp_codename >= 'icehouse':
|
||||
elif cmp_codename >= 'icehouse' and cmp_codename < 'mitaka':
|
||||
return ICEHOUSE_SERVICES
|
||||
else:
|
||||
return []
|
||||
|
@ -312,7 +367,7 @@ def ceilometer_release_services():
|
|||
def ceilometer_release_packages():
|
||||
cmp_codename = CompareOpenStackReleases(
|
||||
get_os_codename_install_source(config('openstack-origin')))
|
||||
if cmp_codename >= 'mitaka':
|
||||
if cmp_codename >= 'mitaka' and cmp_codename < 'queens':
|
||||
return MITAKA_PACKAGES
|
||||
elif cmp_codename >= 'icehouse':
|
||||
return ICEHOUSE_PACKAGES
|
||||
|
@ -321,6 +376,14 @@ def ceilometer_release_packages():
|
|||
|
||||
|
||||
def get_packages():
|
||||
cmp_codename = CompareOpenStackReleases(
|
||||
get_os_codename_install_source(config('openstack-origin')))
|
||||
|
||||
# NOTE(jamespage): @queens ceilometer has no API service, so
|
||||
# no requirement for token caching.
|
||||
if cmp_codename >= 'queens':
|
||||
return deepcopy(QUEENS_PACKAGES)
|
||||
|
||||
packages = (deepcopy(CEILOMETER_BASE_PACKAGES) +
|
||||
ceilometer_release_packages())
|
||||
packages.extend(token_cache_pkgs(source=config('openstack-origin')))
|
||||
|
@ -378,6 +441,9 @@ def resolve_required_interfaces():
|
|||
required_ints = deepcopy(REQUIRED_INTERFACES)
|
||||
if CompareOpenStackReleases(os_release('ceilometer-common')) >= 'mitaka':
|
||||
required_ints['database'].append('metric-service')
|
||||
if CompareOpenStackReleases(os_release('ceilometer-common')) >= 'queens':
|
||||
required_ints['database'].remove('mongodb')
|
||||
required_ints['identity'] = ['identity-credentials']
|
||||
return required_ints
|
||||
|
||||
|
||||
|
@ -446,7 +512,8 @@ def run_in_apache():
|
|||
"""Return true if ceilometer API is run under apache2 with mod_wsgi in
|
||||
this release.
|
||||
"""
|
||||
return CompareOpenStackReleases(os_release('ceilometer-common')) >= 'ocata'
|
||||
os_cmp = CompareOpenStackReleases(os_release('ceilometer-common'))
|
||||
return (os_cmp >= 'ocata' and os_cmp < 'queens')
|
||||
|
||||
|
||||
def disable_package_apache_site():
|
||||
|
|
|
@ -36,6 +36,8 @@ requires:
|
|||
interface: keystone
|
||||
identity-notifications:
|
||||
interface: keystone-notifications
|
||||
identity-credentials:
|
||||
interface: keystone-credentials
|
||||
ha:
|
||||
interface: hacluster
|
||||
scope: container
|
||||
|
|
|
@ -17,10 +17,17 @@ event_dispatchers = gnocchi
|
|||
meter_dispatchers = database
|
||||
{%- endif %}
|
||||
|
||||
{% if transport_url -%}
|
||||
transport_url = {{ transport_url }}
|
||||
{%- endif %}
|
||||
|
||||
[api]
|
||||
port = {{ port }}
|
||||
workers = {{ api_workers }}
|
||||
|
||||
[notification]
|
||||
workers = {{ workers }}
|
||||
|
||||
{% if service_host -%}
|
||||
[service_credentials]
|
||||
auth_url = {{ service_protocol }}://{{ service_host }}:{{ service_port }}
|
||||
|
|
|
@ -48,6 +48,7 @@ TO_PATCH = [
|
|||
'apt_install',
|
||||
'apt_update',
|
||||
'open_port',
|
||||
'close_port',
|
||||
'config',
|
||||
'log',
|
||||
'relation_ids',
|
||||
|
@ -69,6 +70,7 @@ TO_PATCH = [
|
|||
'init_is_systemd',
|
||||
'get_relation_ip',
|
||||
'is_clustered',
|
||||
'get_os_codename_install_source',
|
||||
]
|
||||
|
||||
|
||||
|
@ -82,6 +84,7 @@ class CeilometerHooksTest(CharmTestCase):
|
|||
self.filter_installed_packages.return_value = \
|
||||
ceilometer_utils.CEILOMETER_BASE_PACKAGES
|
||||
self.lsb_release.return_value = {'DISTRIB_CODENAME': 'precise'}
|
||||
self.get_os_codename_install_source.return_value = 'mitaka'
|
||||
|
||||
@patch('charmhelpers.payload.execd.default_execd_dir',
|
||||
return_value=os.path.join(os.getcwd(), 'exec.d'))
|
||||
|
@ -99,7 +102,6 @@ class CeilometerHooksTest(CharmTestCase):
|
|||
hooks.hooks.execute(['hooks/install.real'])
|
||||
self.configure_installation_source.\
|
||||
assert_called_with('cloud:precise-grizzly')
|
||||
self.open_port.assert_called_with(hooks.CEILOMETER_PORT)
|
||||
self.apt_update.assert_called_with(fatal=True)
|
||||
self.apt_install.assert_called_with(
|
||||
ceilometer_utils.CEILOMETER_BASE_PACKAGES,
|
||||
|
@ -114,7 +116,6 @@ class CeilometerHooksTest(CharmTestCase):
|
|||
hooks.hooks.execute(['hooks/install.real'])
|
||||
self.configure_installation_source.\
|
||||
assert_called_with('distro')
|
||||
self.open_port.assert_called_with(hooks.CEILOMETER_PORT)
|
||||
self.apt_update.assert_called_with(fatal=True)
|
||||
self.apt_install.assert_called_with(
|
||||
ceilometer_utils.CEILOMETER_BASE_PACKAGES,
|
||||
|
@ -201,6 +202,25 @@ class CeilometerHooksTest(CharmTestCase):
|
|||
self.assertTrue(self.CONFIGS.write_all.called)
|
||||
self.assertTrue(joined.called)
|
||||
self.assertTrue(self.reload_systemd.called)
|
||||
self.open_port.assert_called_with(hooks.CEILOMETER_PORT)
|
||||
|
||||
@patch.object(hooks, 'install_event_pipeline_setting')
|
||||
@patch('charmhelpers.core.hookenv.config')
|
||||
@patch.object(hooks, 'ceilometer_joined')
|
||||
def test_config_changed_queens(self,
|
||||
joined, mock_config, event_pipe):
|
||||
self.openstack_upgrade_available.return_value = False
|
||||
self.get_os_codename_install_source.return_value = 'queens'
|
||||
hooks.hooks.execute(['hooks/config-changed'])
|
||||
self.openstack_upgrade_available.\
|
||||
assert_called_with('ceilometer-common')
|
||||
self.assertFalse(self.do_openstack_upgrade.called)
|
||||
self.assertTrue(event_pipe.called)
|
||||
self.assertTrue(self.CONFIGS.write_all.called)
|
||||
self.assertTrue(joined.called)
|
||||
self.assertTrue(self.reload_systemd.called)
|
||||
self.close_port.assert_called_with(hooks.CEILOMETER_PORT)
|
||||
self.open_port.assert_not_called()
|
||||
|
||||
@patch.object(hooks, 'install_event_pipeline_setting')
|
||||
@patch('charmhelpers.core.hookenv.config')
|
||||
|
@ -216,6 +236,7 @@ class CeilometerHooksTest(CharmTestCase):
|
|||
self.assertTrue(self.CONFIGS.write_all.called)
|
||||
self.assertTrue(joined.called)
|
||||
self.assertTrue(self.reload_systemd.called)
|
||||
self.open_port.assert_called_with(hooks.CEILOMETER_PORT)
|
||||
|
||||
@patch.object(hooks, 'install_event_pipeline_setting')
|
||||
def test_config_changed_with_openstack_upgrade_action(self,
|
||||
|
@ -227,6 +248,14 @@ class CeilometerHooksTest(CharmTestCase):
|
|||
|
||||
self.assertFalse(self.do_openstack_upgrade.called)
|
||||
self.assertTrue(event_pipe.called)
|
||||
self.open_port.assert_called_with(hooks.CEILOMETER_PORT)
|
||||
|
||||
def test_keystone_credentials_joined(self):
|
||||
hooks.hooks.execute(['hooks/identity-credentials-relation-joined'])
|
||||
self.relation_set.assert_called_with(
|
||||
username=hooks.CEILOMETER_SERVICE,
|
||||
requested_roles=hooks.CEILOMETER_ROLE,
|
||||
relation_id=None)
|
||||
|
||||
@patch.object(hooks, 'canonical_url')
|
||||
@patch('charmhelpers.core.hookenv.config')
|
||||
|
|
|
@ -47,6 +47,7 @@ class CeilometerUtilsTest(CharmTestCase):
|
|||
def setUp(self):
|
||||
super(CeilometerUtilsTest, self).setUp(utils, TO_PATCH)
|
||||
self.config.side_effect = self.test_config.get
|
||||
self.get_os_codename_install_source.return_value = 'icehouse'
|
||||
|
||||
def tearDown(self):
|
||||
super(CeilometerUtilsTest, self).tearDown()
|
||||
|
@ -55,6 +56,7 @@ class CeilometerUtilsTest(CharmTestCase):
|
|||
self.os.path.exists.return_value = True
|
||||
self.init_is_systemd.return_value = False
|
||||
self.os_release.return_value = 'havana'
|
||||
self.get_os_codename_package.return_value = 'havana'
|
||||
configs = utils.register_configs()
|
||||
calls = []
|
||||
for conf in (utils.CEILOMETER_CONF, utils.HAPROXY_CONF,
|
||||
|
@ -67,6 +69,7 @@ class CeilometerUtilsTest(CharmTestCase):
|
|||
self.os.path.exists.return_value = False
|
||||
self.init_is_systemd.return_value = False
|
||||
self.os_release.return_value = 'havana'
|
||||
self.get_os_codename_package.return_value = 'havana'
|
||||
configs = utils.register_configs()
|
||||
calls = []
|
||||
for conf in (utils.CEILOMETER_CONF, utils.HAPROXY_CONF,
|
||||
|
@ -79,6 +82,7 @@ class CeilometerUtilsTest(CharmTestCase):
|
|||
self.os.path.exists.return_value = True
|
||||
self.init_is_systemd.return_value = True
|
||||
self.os_release.return_value = 'havana'
|
||||
self.get_os_codename_package.return_value = 'havana'
|
||||
configs = utils.register_configs()
|
||||
calls = []
|
||||
for conf in (utils.CEILOMETER_CONF, utils.HAPROXY_CONF,
|
||||
|
@ -101,6 +105,12 @@ class CeilometerUtilsTest(CharmTestCase):
|
|||
self.assertEqual(['ceilometer-agent-notification'],
|
||||
utils.ceilometer_release_services())
|
||||
|
||||
def test_ceilometer_release_services_queens(self):
|
||||
"""Ensure that queens specific services are identified"""
|
||||
self.get_os_codename_install_source.return_value = 'queens'
|
||||
self.assertEqual([],
|
||||
utils.ceilometer_release_services())
|
||||
|
||||
def test_restart_map(self):
|
||||
"""Ensure that alarming services are present for < OpenStack Mitaka"""
|
||||
self.get_os_codename_install_source.return_value = 'icehouse'
|
||||
|
@ -150,6 +160,20 @@ class CeilometerUtilsTest(CharmTestCase):
|
|||
}
|
||||
)
|
||||
|
||||
def test_restart_map_queens(self):
|
||||
"""Ensure that alarming services are missing for OpenStack Queens"""
|
||||
self.get_os_codename_install_source.return_value = 'queens'
|
||||
self.os_release.return_value = 'queens'
|
||||
self.maxDiff = None
|
||||
restart_map = utils.restart_map()
|
||||
self.assertEqual(
|
||||
restart_map,
|
||||
{'/etc/ceilometer/ceilometer.conf': [
|
||||
'ceilometer-agent-central',
|
||||
'ceilometer-agent-notification'],
|
||||
}
|
||||
)
|
||||
|
||||
def test_get_ceilometer_conf(self):
|
||||
class TestContext():
|
||||
|
||||
|
@ -272,6 +296,18 @@ class CeilometerUtilsTest(CharmTestCase):
|
|||
}
|
||||
)
|
||||
|
||||
def test_resolve_required_interfaces_queens(self):
|
||||
self.os_release.side_effect = None
|
||||
self.os_release.return_value = 'queens'
|
||||
self.assertEqual(
|
||||
utils.resolve_required_interfaces(),
|
||||
{
|
||||
'database': ['metric-service'],
|
||||
'messaging': ['amqp'],
|
||||
'identity': ['identity-credentials'],
|
||||
}
|
||||
)
|
||||
|
||||
@patch.object(utils, 'subprocess')
|
||||
def test_ceilometer_upgrade(self, mock_subprocess):
|
||||
self.is_leader.return_value = True
|
||||
|
|
Loading…
Reference in New Issue