Skip to content

Commit

Permalink
rbd: send ceph monitor addresses with connection info
Browse files Browse the repository at this point in the history
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
  • Loading branch information
jdurgin committed May 28, 2013
1 parent b782597 commit 483b84e
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 0 deletions.
56 changes: 56 additions & 0 deletions cinder/tests/test_rbd.py
Expand Up @@ -35,6 +35,34 @@
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
Expand Down Expand Up @@ -190,6 +218,34 @@ def fake_safe_get(*args):
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"
Expand Down
20 changes: 20 additions & 0 deletions cinder/volume/drivers/rbd.py
Expand Up @@ -65,6 +65,23 @@ def check_for_setup_error(self):
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,
Expand Down Expand Up @@ -199,11 +216,14 @@ def remove_export(self, context, volume):
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,
Expand Down

0 comments on commit 483b84e

Please sign in to comment.