RBD: consider a custom keyring in connection info

If a 'keyring' key is found in the connection info passed to
connect_volume() use its value as the path to the keyring instead of the
default location (/etc/ceph/<cluster>.client.<user>.keyring).

This allows services such as cinder's RBD and Ceph backup drivers to
make use of a custom keyring path that an admin has defined.

Change-Id: Ib1230d3e40f56371567e1aead40db59667bad295
Closes-bug: #1668304
This commit is contained in:
Jon Bernard 2017-03-17 13:25:03 -04:00 committed by Eric Harney
parent 57f6eb74e7
commit 7b9a6686bc
3 changed files with 31 additions and 5 deletions

View File

@ -70,14 +70,19 @@ class RBDConnector(base.BaseLinuxConnector):
return list(map(_sanitize_host, hosts))
def _create_ceph_conf(self, monitor_ips, monitor_ports,
cluster_name, user):
cluster_name, user, keyring_path):
monitors = ["%s:%s" % (ip, port) for ip, port in
zip(self._sanitize_mon_hosts(monitor_ips), monitor_ports)]
mon_hosts = "mon_host = %s" % (','.join(monitors))
client_section = "[client.%s]" % user
keyring = ("keyring = /etc/ceph/%s.client.%s.keyring" %
(cluster_name, user))
if keyring_path is None:
keyring = ("keyring = /etc/ceph/%s.client.%s.keyring" %
(cluster_name, user))
else:
keyring = "keyring = %s" % keyring_path
try:
fd, ceph_conf_path = tempfile.mkstemp(prefix="brickrbd_")
with os.fdopen(fd, 'w') as conf_file:
@ -95,12 +100,14 @@ class RBDConnector(base.BaseLinuxConnector):
cluster_name = connection_properties.get('cluster_name')
monitor_ips = connection_properties.get('hosts')
monitor_ports = connection_properties.get('ports')
keyring_path = connection_properties.get('keyring')
except IndexError:
msg = _("Connect volume failed, malformed connection properties")
raise exception.BrickException(msg=msg)
conf = self._create_ceph_conf(monitor_ips, monitor_ports,
str(cluster_name), user)
str(cluster_name), user,
keyring_path)
try:
rbd_client = linuxrbd.RBDClient(user, pool, conffile=conf,
rbd_cluster_name=str(cluster_name))

View File

@ -94,6 +94,21 @@ class RBDConnectorTestCase(test_connector.ConnectorTestCase):
self.assertIsInstance(device_info['path'],
linuxrbd.RBDVolumeIOWrapper)
@mock.patch('os_brick.initiator.linuxrbd.rbd')
@mock.patch('os_brick.initiator.linuxrbd.rados')
@mock.patch.object(rbd.RBDConnector, '_create_ceph_conf')
@mock.patch('os.path.exists')
def test_custom_keyring(self, mock_path, mock_conf, mock_rados, mock_rbd):
conn = rbd.RBDConnector(None)
mock_path.return_value = False
mock_conf.return_value = "/tmp/fake_dir/fake_ceph.conf"
custom_keyring_path = "/foo/bar/baz"
self.connection_properties['keyring'] = custom_keyring_path
conn.connect_volume(self.connection_properties)
mock_conf.assert_called_once_with(self.hosts, self.ports,
self.clustername, self.user,
custom_keyring_path)
@ddt.data((['192.168.1.1', '192.168.1.2'],
['192.168.1.1', '192.168.1.2']),
(['3ffe:1900:4545:3:200:f8ff:fe21:67cf',
@ -122,7 +137,7 @@ class RBDConnectorTestCase(test_connector.ConnectorTestCase):
with mock.patch('os.fdopen', mockopen, create=True):
rbd_connector = rbd.RBDConnector(None)
conf_path = rbd_connector._create_ceph_conf(
self.hosts, self.ports, self.clustername, self.user)
self.hosts, self.ports, self.clustername, self.user, None)
self.assertEqual(conf_path, tmpfile)
mock_mkstemp.assert_called_once_with(prefix='brickrbd_')

View File

@ -0,0 +1,4 @@
---
fixes:
- Add support to use custom Ceph keyring files (previously os-brick
hardcoded using /etc/ceph/<cluster>.client.<user>.keyring file).