162 lines
5.5 KiB
Python
162 lines
5.5 KiB
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.
|
|
|
|
from charmhelpers.core.hookenv import (
|
|
config,
|
|
service_name,
|
|
is_relation_made,
|
|
leader_get,
|
|
log,
|
|
relation_get,
|
|
relation_ids,
|
|
related_units,
|
|
DEBUG,
|
|
)
|
|
|
|
from charmhelpers.contrib.openstack.context import (
|
|
CephContext,
|
|
OSContextGenerator,
|
|
)
|
|
|
|
from charmhelpers.contrib.openstack.utils import (
|
|
get_os_codename_package,
|
|
CompareOpenStackReleases,
|
|
)
|
|
|
|
from charmhelpers.contrib.network.ip import (
|
|
format_ipv6_addr,
|
|
)
|
|
|
|
CHARM_CEPH_CONF = '/var/lib/charm/{}/ceph.conf'
|
|
|
|
|
|
def ceph_config_file():
|
|
return CHARM_CEPH_CONF.format(service_name())
|
|
|
|
|
|
class CephAccessContext(OSContextGenerator):
|
|
interfaces = ['ceph-access']
|
|
|
|
def __call__(self):
|
|
"""Simple check to validate that compute units are present"""
|
|
for r_id in relation_ids(self.interfaces[0]):
|
|
if related_units(r_id):
|
|
return {'complete': True}
|
|
return {}
|
|
|
|
|
|
class CephSubordinateContext(OSContextGenerator):
|
|
interfaces = ['ceph-cinder']
|
|
|
|
def __call__(self):
|
|
"""
|
|
Used to generate template context to be added to cinder.conf in the
|
|
presence of a ceph relation.
|
|
"""
|
|
if not is_relation_made('ceph', 'key'):
|
|
return {}
|
|
service = service_name()
|
|
os_codename = get_os_codename_package('cinder-common')
|
|
if CompareOpenStackReleases(os_codename) >= "icehouse":
|
|
volume_driver = 'cinder.volume.drivers.rbd.RBDDriver'
|
|
else:
|
|
volume_driver = 'cinder.volume.driver.RBDDriver'
|
|
|
|
if config('volume-backend-name'):
|
|
volume_backend_name = config('volume-backend-name')
|
|
else:
|
|
volume_backend_name = service
|
|
|
|
if config('pool-type') == 'erasure-coded':
|
|
pool_name = (
|
|
config('ec-rbd-metadata-pool') or
|
|
"{}-metadata".format(config('rbd-pool-name') or
|
|
service)
|
|
)
|
|
else:
|
|
pool_name = config('rbd-pool-name') or service
|
|
section = {service: [('volume_backend_name', volume_backend_name),
|
|
('volume_driver', volume_driver),
|
|
('rbd_pool', pool_name),
|
|
('rbd_user', service),
|
|
('rbd_secret_uuid', leader_get('secret-uuid')),
|
|
('rbd_ceph_conf', ceph_config_file())]}
|
|
|
|
if CompareOpenStackReleases(os_codename) >= "mitaka":
|
|
section[service].append(('report_discard_supported', True))
|
|
|
|
if CompareOpenStackReleases(os_codename) >= "ocata":
|
|
section[service].append(('rbd_exclusive_cinder_pool', True))
|
|
|
|
if CompareOpenStackReleases(os_codename) >= "pike" \
|
|
and config('backend-availability-zone'):
|
|
section[service].append(
|
|
('backend_availability_zone',
|
|
config('backend-availability-zone')))
|
|
|
|
if CompareOpenStackReleases(os_codename) >= "queens":
|
|
section[service].append(
|
|
('rbd_flatten_volume_from_snapshot',
|
|
config('rbd-flatten-volume-from-snapshot')))
|
|
|
|
return {'cinder': {'/etc/cinder/cinder.conf': {'sections': section}}}
|
|
|
|
|
|
class CephReplicationDeviceContext(CephContext):
|
|
"""Generates context for /etc/ceph/ceph.conf templates."""
|
|
|
|
interfaces = ['ceph-replication-device']
|
|
|
|
def __call__(self):
|
|
if not relation_ids('ceph-replication-device'):
|
|
return {}
|
|
log('Generating template context for ceph-replication-device',
|
|
level=DEBUG)
|
|
mon_hosts = []
|
|
ctxt = {
|
|
'use_syslog': str(config('use-syslog')).lower()
|
|
}
|
|
for rid in relation_ids('ceph-replication-device'):
|
|
for unit in related_units(rid):
|
|
if not ctxt.get('auth'):
|
|
ctxt['auth'] = relation_get('auth', rid=rid, unit=unit)
|
|
if not ctxt.get('key'):
|
|
ctxt['key'] = relation_get('key', rid=rid, unit=unit)
|
|
ceph_addrs = relation_get('ceph-public-address', rid=rid,
|
|
unit=unit)
|
|
if ceph_addrs:
|
|
for addr in ceph_addrs.split(' '):
|
|
mon_hosts.append(format_ipv6_addr(addr) or addr)
|
|
else:
|
|
priv_addr = relation_get('private-address', rid=rid,
|
|
unit=unit)
|
|
mon_hosts.append(format_ipv6_addr(priv_addr) or priv_addr)
|
|
|
|
ctxt['mon_hosts'] = ' '.join(sorted(mon_hosts))
|
|
if not self.context_complete(ctxt):
|
|
return {}
|
|
|
|
return ctxt
|
|
|
|
|
|
class CinderCephContext(CephContext):
|
|
|
|
def __call__(self):
|
|
ctxt = super(CinderCephContext, self).__call__()
|
|
# NOTE: If "rbd-mirroring-mode" is set to "image" we are going
|
|
# to ignore default 'rbd_features' that are set in the context
|
|
if config('rbd-mirror-mode') == "image":
|
|
ctxt.pop('rbd_features', None)
|
|
return ctxt
|