Prevent rbd map again if it's already mapped

`rbd map` maps rbd volume regardless if it's already mapped or not.[1]
This patch is to prevent duplicated rbd map in connect_volume.

[1]
```
root@compute-0:~# rbd -p rbd_ssd map foo
/dev/rbd1
root@compute-0:~# rbd -p rbd_ssd map foo
/dev/rbd2
```

Change-Id: I13ef77edf31bffaecd671385cbca564931214a7e
This commit is contained in:
cheng li 2017-05-04 14:37:24 +08:00
parent 90d0b43ee3
commit a760c549b3
2 changed files with 38 additions and 5 deletions

View File

@ -180,12 +180,20 @@ class RBDConnector(base.BaseLinuxConnector):
# NOTE(e0ne): map volume to a block device
# 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)
rbd_dev_path = RBDConnector.get_rbd_device_name(pool, volume)
if (not os.path.islink(rbd_dev_path) or
not os.path.exists(os.path.realpath(rbd_dev_path))):
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)
else:
LOG.debug('volume %(vol)s is already mapped to local'
' device %(dev)s',
{'vol': volume,
'dev': os.path.realpath(rbd_dev_path)})
return {'path': RBDConnector.get_rbd_device_name(pool, volume),
return {'path': rbd_dev_path,
'type': 'block'}
rbd_handle = self._get_rbd_handle(connection_properties)

View File

@ -186,6 +186,31 @@ class RBDConnectorTestCase(test_connector.ConnectorTestCase):
'type': 'block'}
self.assertEqual(expected_info, device_info)
@mock.patch.object(priv_rootwrap, 'execute', return_value=None)
@mock.patch('os.path.exists')
@mock.patch('os.path.islink')
@mock.patch('os.path.realpath')
def test_connect_local_volume_dev_exist(self, mock_realpath, mock_islink,
mock_exists, mock_execute):
rbd_connector = rbd.RBDConnector(None, do_local_attach=True)
conn = {'name': 'pool/image',
'auth_username': 'fake_user',
'hosts': ['192.168.10.2'],
'ports': ['6789']}
mock_realpath.return_value = '/dev/rbd0'
mock_islink.return_value = True
mock_exists.return_value = True
device_info = rbd_connector.connect_volume(conn)
execute_call1 = mock.call('which', 'rbd')
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])
self.assertFalse(execute_call2 in mock_execute.mock_calls)
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)