Add support for CephFS.
Extend ceph-proxy to implement ceph-mds interface, this allows the ceph-fs to be related. The testing is made reusing the CephFSTests testing class. Usage example: juju add-relation ceph-proxy:mds ceph-fs:ceph-mds Co-Authored-By: Felipe Reyes <felipe.reyes@canonical.com> Closes-Bug: #1922195 Func-Test-PR: https://github.com/openstack-charmers/zaza-openstack-tests/pull/558 Change-Id: I437dbac9fe018eb2d0ffb87052d61a08aa014473
This commit is contained in:
parent
5ce3787fdb
commit
4686195e53
10
README.md
10
README.md
@ -7,6 +7,10 @@ The ceph-proxy charm deploys a proxy that acts as a [ceph-mon][ceph-mon-charm]
|
||||
application for an external Ceph cluster. It joins a non-charmed Ceph cluster
|
||||
to a Juju model.
|
||||
|
||||
The charm works with traditional Ceph charm clients (e.g. cinder, glance,
|
||||
nova-compute) but it also supports the [ceph-radosgw][ceph-radosgw-charm] and
|
||||
[ceph-fs][ceph-fs-charm] charms.
|
||||
|
||||
# Usage
|
||||
|
||||
## Configuration
|
||||
@ -66,7 +70,9 @@ For general charm questions refer to the [OpenStack Charm Guide][cg].
|
||||
|
||||
[ceph-upstream]: https://ceph.io
|
||||
[cg]: https://docs.openstack.org/charm-guide
|
||||
[ceph-mon-charm]: https://jaas.ai/ceph-mon
|
||||
[juju-docs-actions]: https://jaas.ai/docs/actions
|
||||
[ceph-mon-charm]: https://charmhub.io/ceph-mon
|
||||
[ceph-fs-charm]: https://charmbui.io/ceph-fs
|
||||
[ceph-radosgw-charm]: https://charmbui.io/ceph-radosgw
|
||||
[juju-docs-actions]: https://charmbui.io/docs/actions
|
||||
[juju-docs-config-apps]: https://juju.is/docs/configuring-applications
|
||||
[lp-bugs-charm-ceph-proxy]: https://bugs.launchpad.net/charm-ceph-proxy/+filebug
|
||||
|
@ -351,6 +351,12 @@ def get_radosgw_key(name='radosgw.gateway'):
|
||||
return get_named_key(name, _radosgw_caps)
|
||||
|
||||
|
||||
def get_mds_key(name):
|
||||
return get_named_entity_key(entity='mds',
|
||||
name=name,
|
||||
caps=mds_caps)
|
||||
|
||||
|
||||
_default_caps = collections.OrderedDict([
|
||||
('mon', ['allow r',
|
||||
'allow command "osd blacklist"']),
|
||||
@ -363,6 +369,12 @@ admin_caps = {
|
||||
'osd': ['allow *']
|
||||
}
|
||||
|
||||
mds_caps = collections.OrderedDict([
|
||||
('osd', ['allow *']),
|
||||
('mds', ['allow']),
|
||||
('mon', ['allow rwx']),
|
||||
])
|
||||
|
||||
osd_upgrade_caps = {
|
||||
'mon': ['allow command "config-key"',
|
||||
'allow command "osd tree"',
|
||||
@ -390,15 +402,17 @@ def _config_user_key(name):
|
||||
return k
|
||||
|
||||
|
||||
def get_named_key(name, caps=None, pool_list=None):
|
||||
def get_named_entity_key(name, caps=None, pool_list=None,
|
||||
entity='client'):
|
||||
"""Retrieve a specific named cephx key.
|
||||
|
||||
:param name: String Name of key to get.
|
||||
:param pool_list: The list of pools to give access to
|
||||
:param name: String Name of key to get. EXACT MATCH
|
||||
:param caps: dict of cephx capabilities
|
||||
:param pool_list: The list of pools to give access to
|
||||
:param entity: String Name of type to get.
|
||||
:returns: Returns a cephx key
|
||||
"""
|
||||
key_name = 'client.{}'.format(name)
|
||||
key_name = '{}.{}'.format(entity, name)
|
||||
try:
|
||||
# Does the key already exist?
|
||||
output = str(subprocess.check_output(
|
||||
@ -424,7 +438,8 @@ def get_named_key(name, caps=None, pool_list=None):
|
||||
return parse_key(output)
|
||||
except subprocess.CalledProcessError:
|
||||
# Couldn't get the key, time to create it!
|
||||
log("Creating new key for {}".format(name), level=DEBUG)
|
||||
log("Creating new key for {}".format(key_name), level=DEBUG)
|
||||
|
||||
caps = caps or _default_caps
|
||||
cmd = [
|
||||
"sudo",
|
||||
@ -455,6 +470,17 @@ def get_named_key(name, caps=None, pool_list=None):
|
||||
.strip()) # IGNORE:E1103
|
||||
|
||||
|
||||
def get_named_key(name, caps=None, pool_list=None):
|
||||
"""Retrieve a specific named cephx key.
|
||||
|
||||
:param name: String Name of key to get.
|
||||
:param caps: dict of cephx capabilities
|
||||
:param pool_list: The list of pools to give access to
|
||||
:returns: Returns a cephx key
|
||||
"""
|
||||
return get_named_entity_key(name, caps, pool_list, entity='client')
|
||||
|
||||
|
||||
def upgrade_key_caps(key, caps, pool_list=None):
|
||||
""" Upgrade key to have capabilities caps """
|
||||
if not is_leader():
|
||||
|
@ -31,6 +31,7 @@ import ceph
|
||||
from charmhelpers.core.hookenv import (
|
||||
log,
|
||||
DEBUG,
|
||||
INFO,
|
||||
config,
|
||||
is_leader,
|
||||
relation_ids,
|
||||
@ -137,6 +138,7 @@ def emit_cephconf():
|
||||
|
||||
notify_radosgws()
|
||||
notify_client()
|
||||
notify_cephfs_mds()
|
||||
|
||||
|
||||
@hooks.hook('config-changed')
|
||||
@ -160,6 +162,12 @@ def notify_client():
|
||||
client_relation_joined(relid=relid, unit=unit)
|
||||
|
||||
|
||||
def notify_cephfs_mds():
|
||||
for relid in relation_ids('mds'):
|
||||
for unit in related_units(relid):
|
||||
mds_relation_joined(relid=relid, unit=unit)
|
||||
|
||||
|
||||
@hooks.hook('radosgw-relation-changed')
|
||||
@hooks.hook('radosgw-relation-joined')
|
||||
def radosgw_relation(relid=None, unit=None):
|
||||
@ -203,6 +211,41 @@ def radosgw_relation(relid=None, unit=None):
|
||||
log('FSID or admin key not provided, please configure them')
|
||||
|
||||
|
||||
@hooks.hook('mds-relation-joined')
|
||||
@hooks.hook('mds-relation-changed')
|
||||
def mds_relation_joined(relid=None, unit=None):
|
||||
if not ready():
|
||||
log('MDS: FSID or admin key not provided, please configure them',
|
||||
level=INFO)
|
||||
return
|
||||
|
||||
log('ceph-proxy config ok - providing mds client with keys')
|
||||
if not unit:
|
||||
unit = remote_unit()
|
||||
|
||||
mds_name = relation_get(attribute='mds-name',
|
||||
rid=relid, unit=unit)
|
||||
ceph_addrs = config('monitor-hosts')
|
||||
data = {
|
||||
'fsid': config('fsid'),
|
||||
'auth': config('auth-supported'),
|
||||
'ceph-public-address': ceph_addrs,
|
||||
}
|
||||
if mds_name:
|
||||
data['{}_mds_key'.format(mds_name)] = (
|
||||
ceph.get_mds_key(name=mds_name)
|
||||
)
|
||||
|
||||
settings = relation_get(rid=relid, unit=unit) or {}
|
||||
if 'broker_req' in settings:
|
||||
rsp = process_requests(settings['broker_req'])
|
||||
unit_id = unit.replace('/', '-')
|
||||
unit_response_key = 'broker-rsp-' + unit_id
|
||||
data[unit_response_key] = rsp
|
||||
log('MDS: relation_set (%s): %s' % (relid, str(data)), level=DEBUG)
|
||||
relation_set(relation_id=relid, relation_settings=data)
|
||||
|
||||
|
||||
@hooks.hook('client-relation-joined')
|
||||
def client_relation_joined(relid=None, unit=None):
|
||||
if ready():
|
||||
|
1
hooks/mds-relation-changed
Symbolic link
1
hooks/mds-relation-changed
Symbolic link
@ -0,0 +1 @@
|
||||
ceph_hooks.py
|
1
hooks/mds-relation-joined
Symbolic link
1
hooks/mds-relation-joined
Symbolic link
@ -0,0 +1 @@
|
||||
ceph_hooks.py
|
@ -21,3 +21,5 @@ provides:
|
||||
interface: ceph-client
|
||||
radosgw:
|
||||
interface: ceph-radosgw
|
||||
mds:
|
||||
interface: ceph-mds
|
||||
|
@ -25,6 +25,8 @@ machines:
|
||||
'13':
|
||||
'14':
|
||||
'15':
|
||||
'16':
|
||||
'17':
|
||||
|
||||
applications:
|
||||
|
||||
@ -150,6 +152,12 @@ applications:
|
||||
- '15'
|
||||
channel: latest/edge
|
||||
|
||||
ubuntu: # used to test mounts
|
||||
charm: ch:ubuntu
|
||||
num_units: 2
|
||||
to:
|
||||
- '16'
|
||||
- '17'
|
||||
|
||||
relations:
|
||||
|
||||
|
@ -25,6 +25,8 @@ machines:
|
||||
'13':
|
||||
'14':
|
||||
'15':
|
||||
'16':
|
||||
'17':
|
||||
|
||||
applications:
|
||||
|
||||
@ -150,6 +152,12 @@ applications:
|
||||
- '15'
|
||||
channel: latest/edge
|
||||
|
||||
ubuntu: # used to test mounts
|
||||
charm: ch:ubuntu
|
||||
num_units: 2
|
||||
to:
|
||||
- '16'
|
||||
- '17'
|
||||
|
||||
relations:
|
||||
|
||||
|
@ -25,6 +25,8 @@ machines:
|
||||
'13':
|
||||
'14':
|
||||
'15':
|
||||
'16':
|
||||
'17':
|
||||
|
||||
applications:
|
||||
|
||||
@ -150,6 +152,12 @@ applications:
|
||||
- '15'
|
||||
channel: latest/edge
|
||||
|
||||
ubuntu: # used to test mounts
|
||||
charm: ch:ubuntu
|
||||
num_units: 2
|
||||
to:
|
||||
- '16'
|
||||
- '17'
|
||||
|
||||
relations:
|
||||
|
||||
|
@ -25,6 +25,8 @@ machines:
|
||||
'13':
|
||||
'14':
|
||||
'15':
|
||||
'16':
|
||||
'17':
|
||||
|
||||
applications:
|
||||
|
||||
@ -150,6 +152,12 @@ applications:
|
||||
- '15'
|
||||
channel: latest/edge
|
||||
|
||||
ubuntu: # used to test mounts
|
||||
charm: ch:ubuntu
|
||||
num_units: 2
|
||||
to:
|
||||
- '16'
|
||||
- '17'
|
||||
|
||||
relations:
|
||||
|
||||
|
@ -25,6 +25,8 @@ machines:
|
||||
'13':
|
||||
'14':
|
||||
'15':
|
||||
'16':
|
||||
'17':
|
||||
|
||||
applications:
|
||||
|
||||
@ -150,6 +152,12 @@ applications:
|
||||
- '15'
|
||||
channel: latest/edge
|
||||
|
||||
ubuntu: # used to test mounts
|
||||
charm: ch:ubuntu
|
||||
num_units: 2
|
||||
to:
|
||||
- '16'
|
||||
- '17'
|
||||
|
||||
relations:
|
||||
|
||||
|
@ -7,6 +7,7 @@ configure:
|
||||
|
||||
tests:
|
||||
- zaza.openstack.charm_tests.ceph.tests.CephProxyTest
|
||||
- zaza.openstack.charm_tests.ceph.fs.tests.CephFSWithCephProxyTests
|
||||
- erasure-coded:
|
||||
- zaza.openstack.charm_tests.ceph.tests.CephProxyTest
|
||||
- zaza.openstack.charm_tests.ceph.tests.CheckPoolTypes
|
||||
@ -33,22 +34,28 @@ smoke_bundles:
|
||||
target_deploy_status:
|
||||
ceph-proxy:
|
||||
workload-status: blocked
|
||||
workload-status-message: Ensure FSID and admin-key are set
|
||||
workload-status-message-prefix: "Ensure FSID and admin-key are set"
|
||||
ceph-radosgw:
|
||||
workload-status: waiting
|
||||
workload-status-message: "Incomplete relations: mon"
|
||||
workload-status-message-prefix: "Incomplete relations: mon"
|
||||
keystone:
|
||||
workload-status: active
|
||||
workload-status-message: "Unit is ready"
|
||||
nova-compute:
|
||||
workload-status: waiting
|
||||
workload-status-message: "Incomplete relations: storage-backend"
|
||||
workload-status-message-prefix: "Unit is ready"
|
||||
cinder-ceph:
|
||||
workload-status: waiting
|
||||
workload-status-message: "Ceph broker request incomplete"
|
||||
workload-status-message-prefix: "Ceph broker request incomplete"
|
||||
ceph-fs:
|
||||
workload-status: blocked
|
||||
workload-status-message-prefix: "'ceph-mds' missing"
|
||||
nova-compute:
|
||||
workload-status: waiting
|
||||
workload-status-message-prefix: "Incomplete relations: storage-backend"
|
||||
glance:
|
||||
workload-status: waiting
|
||||
workload-status-message: "Incomplete relations: storage-backend"
|
||||
workload-status-message-prefix: "Incomplete relations: storage-backend"
|
||||
ubuntu:
|
||||
workload-status: active
|
||||
workload-status-message-prefix: ''
|
||||
|
||||
tests_options:
|
||||
force_deploy:
|
||||
|
@ -74,10 +74,11 @@ class TestHooks(test_utils.CharmTestCase):
|
||||
mock_apt_install.assert_called_with(packages=[])
|
||||
|
||||
@mock.patch('ceph.ceph_user')
|
||||
@mock.patch.object(hooks, 'mds_relation_joined', autospec=True)
|
||||
@mock.patch.object(hooks, 'radosgw_relation')
|
||||
@mock.patch.object(hooks, 'client_relation_joined')
|
||||
def test_emit_cephconf(self, mock_client_rel, mock_rgw_rel,
|
||||
mock_ceph_user):
|
||||
mock_mds_rel, mock_ceph_user):
|
||||
mock_ceph_user.return_value = 'ceph-user'
|
||||
self.test_config.set('monitor-hosts', '127.0.0.1:1234')
|
||||
self.test_config.set('fsid', 'abc123')
|
||||
@ -89,6 +90,8 @@ class TestHooks(test_utils.CharmTestCase):
|
||||
'client': ['client:1'],
|
||||
'rados:1': ['rados/1'],
|
||||
'client:1': ['client/1'],
|
||||
'mds': ['mds:2'],
|
||||
'mds:2': ['mds/3'],
|
||||
}
|
||||
return x[k]
|
||||
|
||||
@ -127,6 +130,7 @@ class TestHooks(test_utils.CharmTestCase):
|
||||
|
||||
mock_rgw_rel.assert_called_with(relid='rados:1', unit='rados/1')
|
||||
mock_client_rel.assert_called_with(relid='client:1', unit='client/1')
|
||||
mock_mds_rel.assert_called_with(relid='mds:2', unit='mds/3')
|
||||
|
||||
@mock.patch.object(hooks.ceph, 'ceph_user')
|
||||
@mock.patch('subprocess.check_output')
|
||||
@ -162,6 +166,56 @@ class TestHooks(test_utils.CharmTestCase):
|
||||
mock_package_install.assert_not_called()
|
||||
mock_emit_cephconf.assert_any_call()
|
||||
|
||||
@mock.patch('subprocess.check_output', autospec=True)
|
||||
@mock.patch('ceph.config', autospec=True)
|
||||
@mock.patch('ceph.get_mds_key', autospec=True)
|
||||
@mock.patch('ceph.ceph_user', autospec=True)
|
||||
def test_mds_relation_joined(self, ceph_user, get_mds_key, ceph_config,
|
||||
check_output):
|
||||
my_mds_key = '1234-key'
|
||||
mds_name = 'adjusted-mayfly'
|
||||
rid = 'mds:1'
|
||||
ceph_user.return_value = 'ceph'
|
||||
get_mds_key.return_value = my_mds_key
|
||||
ceph_config.side_effect = self.test_config.get
|
||||
|
||||
settings = {'ceph-public-address': '127.0.0.1:1234 [::1]:4321',
|
||||
'auth': 'cephx',
|
||||
'fsid': 'some-fsid'}
|
||||
|
||||
rel_data_get = {'broker_req': 'my-uuid',
|
||||
'mds-name': mds_name}
|
||||
rel_data_set = {'broker-rsp-client-0': 'foobar',
|
||||
'%s_mds_key' % mds_name: my_mds_key}
|
||||
rel_data_set.update(settings)
|
||||
|
||||
def fake_relation_get(attribute=None, rid=None, unit=None):
|
||||
if attribute:
|
||||
return rel_data_get[attribute]
|
||||
else:
|
||||
return rel_data_get
|
||||
|
||||
self.relation_get.side_effect = fake_relation_get
|
||||
|
||||
# unconfigured ceph-proxy
|
||||
with mock.patch.object(hooks, 'log') as log:
|
||||
hooks.mds_relation_joined()
|
||||
log.assert_called_with(
|
||||
'MDS: FSID or admin key not provided, please configure them',
|
||||
level='INFO')
|
||||
|
||||
# Configure ceph-proxy with the ceph details.
|
||||
self.test_config.set('monitor-hosts', settings['ceph-public-address'])
|
||||
self.test_config.set('fsid', settings['fsid'])
|
||||
self.test_config.set('admin-key', 'some-admin-key')
|
||||
|
||||
with mock.patch.object(hooks, 'process_requests') as process_requests:
|
||||
process_requests.return_value = 'foobar'
|
||||
hooks.mds_relation_joined(relid=rid)
|
||||
process_requests.assert_called_with('my-uuid')
|
||||
self.relation_set.assert_called_with(
|
||||
relation_id=rid, relation_settings=rel_data_set)
|
||||
|
||||
@mock.patch('ceph_hooks.emit_cephconf')
|
||||
@mock.patch('ceph_hooks.package_install')
|
||||
def test_update_apt_source(self, mock_package_install, mock_emit_cephconf):
|
||||
|
Loading…
Reference in New Issue
Block a user