File nova-rbd-use-local-devices.patch of Package openstack-nova

From e9c36242bc3a5addad26cd622f35706d55a3f6c5 Mon Sep 17 00:00:00 2001
From: Ralf Haferkamp <rhafer@suse.de>
Date: Tue, 3 Jul 2012 17:42:06 +0200
Subject: [PATCH] Use local rbd devices (/dev/rbd*) for rbd volumes

This adds a new LibirtVolumeDriver to nova-compute that will take care to
map/unmap local block devices for rbd volumes. The original approach for rbd
volumes required rbd-enabled libvirt and kvm/qemu. Which we currently don't
have on SLES-11-SP2.

Change-Id: I62e7664200bc83b948e19a65a3cbda81ebb0470e
---
 nova/rootwrap/compute.py        |    3 ++
 nova/virt/libvirt/connection.py |    2 +-
 nova/virt/libvirt/volume.py     |   58 +++++++++++++++++++++++++++++++++++++++
 nova/volume/driver.py           |    6 ++++
 4 files changed, 68 insertions(+), 1 deletions(-)

Index: nova-2012.2+git.1349813491.b7e509a/nova/virt/libvirt/volume.py
===================================================================
--- nova-2012.2+git.1349813491.b7e509a.orig/nova/virt/libvirt/volume.py
+++ nova-2012.2+git.1349813491.b7e509a/nova/virt/libvirt/volume.py
@@ -30,6 +30,8 @@ from nova.virt.libvirt import utils as v
 LOG = logging.getLogger(__name__)
 FLAGS = flags.FLAGS
 flags.DECLARE('num_iscsi_scan_tries', 'nova.volume.driver')
+flags.DECLARE('rbd_secret_file', 'nova.volume.driver')
+flags.DECLARE('rbd_user', 'nova.volume.driver')
 
 
 class LibvirtVolumeDriver(object):
@@ -71,6 +73,62 @@ class LibvirtFakeVolumeDriver(LibvirtVol
         conf.serial = connection_info.get('serial')
         return conf
 
+class LibvirtRbdVolumeDriver(LibvirtVolumeDriver):
+    """Driver to attach RBD volumes to libvirt."""
+
+    def _rbd_get_mapped_device(self, pool, image):
+        (out, err) = utils.execute('rbd', 'showmapped')
+        lines = out.split('\n')
+        del(lines[0])
+        device_path=""
+        for line in lines:
+            elements = line.split('\t')
+            # elements is now [ id, pool, image, snap, device ]
+            if len(elements) == 5 and elements[1] == pool and elements[2] == image:
+                device_path = elements[4]
+                break
+        LOG.debug("device path: %s" % ( device_path))
+        if len(device_path) == 0:
+            LOG.info("No host device found for rbd image %s/%s" % (pool, image))
+        return device_path
+
+    def _rbd_map_volume(self, connection_info):
+        pool = connection_info['data']['pool']
+        image = connection_info['data']['image']
+        (out, err) = utils.execute('rbd', 'map', '-p', pool, image,
+                                   '--secret', FLAGS.rbd_secret_file,
+                                   '--user', FLAGS.rbd_user,
+                                   run_as_root=True)
+        LOG.debug("rbd map: stdout=%s stderr=%s" % ( out, err))
+        return self._rbd_get_mapped_device(pool, image)
+
+    def _rbd_unmap_volume(self, connection_info):
+        pool = connection_info['data']['pool']
+        image = connection_info['data']['image']
+        host_device = self._rbd_get_mapped_device(pool, image)
+        if len(host_device) > 0:
+           (out, err) = utils.execute('rbd', 'unmap', host_device,
+                                   '--secret', FLAGS.rbd_secret_file,
+                                   '--user', FLAGS.rbd_user,
+                                   run_as_root=True)
+           LOG.debug("rbd unmap: stdout=%s stderr=%s" % ( out, err))
+
+
+    def connect_volume(self, connection_info, mount_device):
+        """Connect the volume. Returns xml for libvirt."""
+        driver = self._pick_volume_driver()
+        host_device = self._rbd_map_volume(connection_info)
+
+        connection_info['data']['device_path'] = host_device
+        sup = super(LibvirtRbdVolumeDriver, self)
+        return sup.connect_volume(connection_info, mount_device)
+
+    def disconnect_volume(self, connection_info, mount_device):
+        """Detach the volume from instance_name"""
+        sup = super(LibvirtRbdVolumeDriver, self)
+        sup.disconnect_volume(connection_info, mount_device)
+        self._rbd_unmap_volume(connection_info)
+
 
 class LibvirtNetVolumeDriver(LibvirtVolumeDriver):
     """Driver to attach Network volumes to libvirt."""
Index: nova-2012.2+git.1349813491.b7e509a/nova/volume/driver.py
===================================================================
--- nova-2012.2+git.1349813491.b7e509a.orig/nova/volume/driver.py
+++ nova-2012.2+git.1349813491.b7e509a/nova/volume/driver.py
@@ -67,6 +67,10 @@ volume_opts = [
                default=None,
                help='the libvirt uuid of the secret for the rbd_user'
                     'volumes'),
+    cfg.StrOpt('rbd_secret_file',
+               default=None,
+               help='path the file containing the secret for the rbd_user'
+                    'volumes'),
     cfg.StrOpt('volume_tmp_dir',
                default=None,
                help='where to store temporary image files if the volume '
@@ -724,6 +728,8 @@ class RBDDriver(VolumeDriver):
             'driver_volume_type': 'rbd',
             'data': {
                 'name': '%s/%s' % (FLAGS.rbd_pool, volume['name']),
+                'pool': FLAGS.rbd_pool,
+                'image' : volume['name'],
                 'auth_enabled': FLAGS.rbd_secret_uuid is not None,
                 'auth_username': FLAGS.rbd_user,
                 'secret_type': 'ceph',
Index: nova-2012.2+git.1349813491.b7e509a/etc/nova/rootwrap.d/compute.filters
===================================================================
--- nova-2012.2+git.1349813491.b7e509a.orig/etc/nova/rootwrap.d/compute.filters
+++ nova-2012.2+git.1349813491.b7e509a/etc/nova/rootwrap.d/compute.filters
@@ -101,6 +101,9 @@ ovs-ofctl: CommandFilter, /usr/bin/ovs-o
 # nova/virt/libvirt/connection.py: 'dd', if=%s % virsh_output, ...
 dd: CommandFilter, /bin/dd, root
 
+# nova/virt/libvirt/volume.py: 'rbd', "map/showmapped", ...
+rbd: CommandFilter, /usr/bin/rbd, root
+
 # nova/virt/xenapi/volume_utils.py: 'iscsiadm', '-m', ...
 iscsiadm: CommandFilter, /sbin/iscsiadm, root
 iscsiadm_usr: CommandFilter, /usr/bin/iscsiadm, root
openSUSE Build Service is sponsored by