]> review.fuel-infra Code Review - openstack-build/cinder-build.git/commitdiff
rbd: send ceph monitor addresses with connection info
authorJosh Durgin <josh.durgin@inktank.com>
Sat, 25 May 2013 01:18:30 +0000 (18:18 -0700)
committerJosh Durgin <josh.durgin@inktank.com>
Tue, 28 May 2013 23:07:54 +0000 (16:07 -0700)
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

cinder/tests/test_rbd.py
cinder/volume/drivers/rbd.py

index 54b6ffffa463c90742146c3f277b9c66c97e8cd6..4942d02417c02fa1bf0e6fe8e60938b686bce9b9 100644 (file)
@@ -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"
index f31c4cdaeb078da743ee0375feafdcd6f7234d32..1a06961ad23aff1a4ae0cfea6b55d75f803d06be 100644 (file)
@@ -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,