diff --git a/os_brick/initiator/connectors/rbd.py b/os_brick/initiator/connectors/rbd.py index 7fd39f972..e4070975c 100644 --- a/os_brick/initiator/connectors/rbd.py +++ b/os_brick/initiator/connectors/rbd.py @@ -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: diff --git a/os_brick/tests/initiator/connectors/test_rbd.py b/os_brick/tests/initiator/connectors/test_rbd.py index 6a4ffdc06..1dc8c9e75 100644 --- a/os_brick/tests/initiator/connectors/test_rbd.py +++ b/os_brick/tests/initiator/connectors/test_rbd.py @@ -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)