Include identity information in rbd commands

This allows us to support multiple client keys
on compute nodes rather than requiring all compute
nodes to have ceph admin keys

Change-Id: I92ab4f0b5f550996fee0ea0b0ffa171501932206
This commit is contained in:
Chris MacNaughton 2017-04-04 11:10:01 +02:00
parent c454d1c63a
commit f1738d0748
2 changed files with 58 additions and 4 deletions

View File

@ -119,6 +119,25 @@ class RBDConnector(base.BaseLinuxConnector):
return rbd_handle
def _get_rbd_args(self, connection_properties):
try:
user = connection_properties['auth_username']
monitor_ips = connection_properties.get('hosts')
monitor_ports = connection_properties.get('ports')
except KeyError:
msg = _("Connect volume failed, malformed connection properties")
raise exception.BrickException(msg=msg)
args = ['--id', user]
if monitor_ips and monitor_ports:
monitors = ["%s:%s" % (ip, port) for ip, port in
zip(
self._sanitize_mon_hosts(monitor_ips),
monitor_ports)]
for monitor in monitors:
args += ['--mon_host', monitor]
return args
@staticmethod
def get_rbd_device_name(pool, volume):
"""Return device name which will be generated by RBD kernel module.
@ -156,6 +175,7 @@ class RBDConnector(base.BaseLinuxConnector):
# via the rbd kernel module.
pool, volume = connection_properties['name'].split('/')
cmd = ['rbd', 'map', volume, '--pool', pool]
cmd += self._get_rbd_args(connection_properties)
self._execute(*cmd, root_helper=self._root_helper,
run_as_root=True)
@ -181,6 +201,7 @@ class RBDConnector(base.BaseLinuxConnector):
pool, volume = connection_properties['name'].split('/')
dev_name = RBDConnector.get_rbd_device_name(pool, volume)
cmd = ['rbd', 'unmap', dev_name]
cmd += self._get_rbd_args(connection_properties)
self._execute(*cmd, root_helper=self._root_helper,
run_as_root=True)
else:

View File

@ -14,6 +14,7 @@
import ddt
import mock
from os_brick import exception
from os_brick.initiator.connectors import rbd
from os_brick.initiator import linuxrbd
from os_brick.privileged import rootwrap as priv_rootwrap
@ -144,16 +145,44 @@ class RBDConnectorTestCase(test_connector.ConnectorTestCase):
@mock.patch.object(priv_rootwrap, 'execute', return_value=None)
def test_connect_local_volume(self, mock_execute):
rbd_connector = rbd.RBDConnector(None, do_local_attach=True)
conn = {'name': 'pool/image'}
conn = {'name': 'pool/image',
'auth_username': 'fake_user',
'hosts': ['192.168.10.2'],
'ports': ['6789']}
device_info = rbd_connector.connect_volume(conn)
execute_call1 = mock.call('which', 'rbd')
cmd = ['rbd', 'map', 'image', '--pool', 'pool']
cmd = ['rbd', 'map', 'image', '--pool', 'pool', '--id', 'fake_user',
'--mon_host', '192.168.10.2:6789']
execute_call2 = mock.call(*cmd, root_helper=None, run_as_root=True)
mock_execute.assert_has_calls([execute_call1, execute_call2])
expected_info = {'path': '/dev/rbd/pool/image',
'type': 'block'}
self.assertEqual(expected_info, device_info)
@mock.patch.object(priv_rootwrap, 'execute', return_value=None)
def test_connect_local_volume_without_mons(self, mock_execute):
rbd_connector = rbd.RBDConnector(None, do_local_attach=True)
conn = {'name': 'pool/image',
'auth_username': 'fake_user'}
device_info = rbd_connector.connect_volume(conn)
execute_call1 = mock.call('which', 'rbd')
cmd = ['rbd', 'map', 'image', '--pool', 'pool', '--id', 'fake_user']
execute_call2 = mock.call(*cmd, root_helper=None, run_as_root=True)
mock_execute.assert_has_calls([execute_call1, execute_call2])
expected_info = {'path': '/dev/rbd/pool/image',
'type': 'block'}
self.assertEqual(expected_info, device_info)
@mock.patch.object(priv_rootwrap, 'execute', return_value=None)
def test_connect_local_volume_without_auth(self, mock_execute):
rbd_connector = rbd.RBDConnector(None, do_local_attach=True)
conn = {'name': 'pool/image',
'hosts': ['192.168.10.2'],
'ports': ['6789']}
self.assertRaises(exception.BrickException,
rbd_connector.connect_volume,
conn)
@mock.patch('os_brick.initiator.linuxrbd.rbd')
@mock.patch('os_brick.initiator.linuxrbd.rados')
@mock.patch.object(linuxrbd.RBDVolumeIOWrapper, 'close')
@ -169,11 +198,15 @@ class RBDConnectorTestCase(test_connector.ConnectorTestCase):
@mock.patch.object(priv_rootwrap, 'execute', return_value=None)
def test_disconnect_local_volume(self, mock_execute):
rbd_connector = rbd.RBDConnector(None, do_local_attach=True)
conn = {'name': 'pool/image'}
conn = {'name': 'pool/image',
'auth_username': 'fake_user',
'hosts': ['192.168.10.2'],
'ports': ['6789']}
rbd_connector.disconnect_volume(conn, None)
dev_name = '/dev/rbd/pool/image'
cmd = ['rbd', 'unmap', dev_name]
cmd = ['rbd', 'unmap', dev_name, '--id', 'fake_user',
'--mon_host', '192.168.10.2:6789']
mock_execute.assert_called_once_with(*cmd, root_helper=None,
run_as_root=True)