rbd: send ceph monitor addresses with connection info
Previously we relied on a ceph configuration file on the compute host for this information. Sending the info directly from cinder makes more complex setups with multiple ceph clusters talking to the same compute hosts possible. Refresh the monitor addresses for each initialize_connection() call, since monitors may be added or removed while cinder-volume is running. Fixes: bug 1077817 Signed-off-by: Josh Durgin <josh.durgin@inktank.com> Change-Id: I34a1fa16ce1f4524ba25832faf3129303e755100
This commit is contained in:
@@ -35,6 +35,34 @@ from cinder.volume.drivers.rbd import VERSION as DRIVER_VERSION
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
CEPH_MON_DUMP = """dumped monmap epoch 1
|
||||
{ "epoch": 1,
|
||||
"fsid": "33630410-6d93-4d66-8e42-3b953cf194aa",
|
||||
"modified": "2013-05-22 17:44:56.343618",
|
||||
"created": "2013-05-22 17:44:56.343618",
|
||||
"mons": [
|
||||
{ "rank": 0,
|
||||
"name": "a",
|
||||
"addr": "[::1]:6789\/0"},
|
||||
{ "rank": 1,
|
||||
"name": "b",
|
||||
"addr": "[::1]:6790\/0"},
|
||||
{ "rank": 2,
|
||||
"name": "c",
|
||||
"addr": "[::1]:6791\/0"},
|
||||
{ "rank": 3,
|
||||
"name": "d",
|
||||
"addr": "127.0.0.1:6792\/0"},
|
||||
{ "rank": 4,
|
||||
"name": "e",
|
||||
"addr": "example.com:6791\/0"}],
|
||||
"quorum": [
|
||||
0,
|
||||
1,
|
||||
2]}
|
||||
"""
|
||||
|
||||
|
||||
class FakeImageService:
|
||||
def download(self, context, image_id, path):
|
||||
pass
|
||||
@@ -190,6 +218,34 @@ class RBDTestCase(test.TestCase):
|
||||
actual = self.driver.get_volume_stats(True)
|
||||
self.assertDictMatch(expected, actual)
|
||||
|
||||
def test_get_mon_addrs(self):
|
||||
self.stubs.Set(self.driver, '_execute',
|
||||
lambda *a: (CEPH_MON_DUMP, ''))
|
||||
hosts = ['::1', '::1', '::1', '127.0.0.1', 'example.com']
|
||||
ports = ['6789', '6790', '6791', '6792', '6791']
|
||||
self.assertEqual((hosts, ports), self.driver._get_mon_addrs())
|
||||
|
||||
def test_initialize_connection(self):
|
||||
name = 'volume-00000001'
|
||||
hosts = ['::1', '::1', '::1', '127.0.0.1', 'example.com']
|
||||
ports = ['6789', '6790', '6791', '6792', '6791']
|
||||
self.stubs.Set(self.driver, '_get_mon_addrs', lambda: (hosts, ports))
|
||||
expected = {
|
||||
'driver_volume_type': 'rbd',
|
||||
'data': {
|
||||
'name': '%s/%s' % (self.configuration.rbd_pool,
|
||||
name),
|
||||
'hosts': hosts,
|
||||
'ports': ports,
|
||||
'auth_enabled': False,
|
||||
'auth_username': None,
|
||||
'secret_type': 'ceph',
|
||||
'secret_uuid': None,
|
||||
}
|
||||
}
|
||||
actual = self.driver.initialize_connection(dict(name=name), None)
|
||||
self.assertDictMatch(expected, actual)
|
||||
|
||||
|
||||
class ManagedRBDTestCase(DriverTestCase):
|
||||
driver_name = "cinder.volume.drivers.rbd.RBDDriver"
|
||||
|
||||
@@ -65,6 +65,23 @@ class RBDDriver(driver.VolumeDriver):
|
||||
self.configuration.rbd_pool)
|
||||
raise exception.VolumeBackendAPIException(data=exception_message)
|
||||
|
||||
def _get_mon_addrs(self):
|
||||
args = ['ceph', 'mon', 'dump', '--format=json']
|
||||
out, _ = self._execute(*args)
|
||||
lines = out.split('\n')
|
||||
if lines[0].startswith('dumped monmap epoch'):
|
||||
lines = lines[1:]
|
||||
monmap = json.loads('\n'.join(lines))
|
||||
addrs = [mon['addr'] for mon in monmap['mons']]
|
||||
hosts = []
|
||||
ports = []
|
||||
for addr in addrs:
|
||||
host_port = addr[:addr.rindex('/')]
|
||||
host, port = host_port.rsplit(':', 1)
|
||||
hosts.append(host.strip('[]'))
|
||||
ports.append(port)
|
||||
return hosts, ports
|
||||
|
||||
def _update_volume_stats(self):
|
||||
stats = {'vendor_name': 'Open Source',
|
||||
'driver_version': VERSION,
|
||||
@@ -199,11 +216,14 @@ class RBDDriver(driver.VolumeDriver):
|
||||
pass
|
||||
|
||||
def initialize_connection(self, volume, connector):
|
||||
hosts, ports = self._get_mon_addrs()
|
||||
return {
|
||||
'driver_volume_type': 'rbd',
|
||||
'data': {
|
||||
'name': '%s/%s' % (self.configuration.rbd_pool,
|
||||
volume['name']),
|
||||
'hosts': hosts,
|
||||
'ports': ports,
|
||||
'auth_enabled': (self.configuration.rbd_secret_uuid
|
||||
is not None),
|
||||
'auth_username': self.configuration.rbd_user,
|
||||
|
||||
Reference in New Issue
Block a user