rtslib-fb patches backported to SLE12 rtslib, obtained from:
http://permalink.gmane.org/gmane.comp.file-systems.ceph.devel/26263

Index: rtslib-2.2/rtslib/tcm.py
===================================================================
--- rtslib-2.2.orig/rtslib/tcm.py
+++ rtslib-2.2/rtslib/tcm.py
@@ -262,6 +262,41 @@ class IBlockBackstore(Backstore):
         return IBlockStorageObject(self, name=name, dev=dev,
                                    gen_wwn=gen_wwn)
 
+class RBDBackstore(Backstore):
+    '''
+    This is an interface to Ceph RBD backstore plugin objects in configFS.
+    An RBDBackstore object is identified by its backstore index.
+    '''
+
+    # RBDBackstore private stuff
+
+    def __init__(self, index, mode='any'):
+        '''
+        @param index: The backstore index.
+        @type index: int
+        @param mode: An optional string containing the object creation mode:
+            - I{'any'} the configFS object will be either lookupd or created.
+            - I{'lookup'} the object MUST already exist configFS.
+            - I{'create'} the object must NOT already exist in configFS.
+        @type mode:string
+        @return: An RBDBackstore object.
+        '''
+
+        super(RBDBackstore, self).__init__("rbd", RBDStorageObject,
+                                           index, mode)
+
+    # RBDBackstore public stuff
+
+    def storage_object(self, name, dev=None, wwn=None, readonly=False,
+                       write_back=False):
+        '''
+        Same as RBDStorageObject() without specifying the backstore
+        '''
+        self._check_self()
+        return RBDStorageObject(self, name=name, dev=dev, wwn=wwn,
+                                readonly=readonly, write_back=write_back)
+
+
 class StorageObject(CFSNode):
     '''
     This is an interface to storage objects in configFS. A StorageObject is
@@ -954,6 +989,110 @@ class IBlockStorageObject(StorageObject)
     minor = property(_get_minor,
             doc="Get the block device minor number")
 
+class RBDStorageObject(StorageObject):
+    '''
+    An interface to configFS storage objects for RBD backstore.
+    '''
+
+    # RBDStorageObject private stuff
+
+    def __init__(self, backstore, name, dev=None, wwn=None, readonly=False,
+                 write_back=False):
+        '''
+        A RBDIOStorageObject can be instantiated in two ways:
+            - B{Creation mode}: If I{dev} is specified, the underlying configFS
+              object will be created with that parameter.
+              No RBDIOStorageObject with the same I{name} can pre-exist in
+              the parent Backstore in that mode.
+            - B{Lookup mode}: If I{dev} is not set, then the
+              RBDIOStorageObject will be bound to the existing configFS
+              object in the parent Backstore having the specified
+              I{name}. The underlying configFS object must already exist in
+              that mode, or instantiation will fail.
+
+        @param name: The name of the RBDIOStorageObject.
+        @type name: string
+        @param dev: The path to the backend rbd device to be used.
+            - Example: I{dev="/dev/sda"}.
+            - The only device type that is accepted I{TYPE_DISK}.
+              For other device types, use pscsi.
+        @type dev: string
+        @param wwn: T10 WWN Unit Serial, will generate if None
+        @type wwn: string
+        @return: A RBDIOStorageObject object.
+        '''
+
+        if dev is not None:
+            super(RBDStorageObject, self).__init__(backstore,
+                                                   RBDBackstore,
+                                                   name,
+                                                   'create')
+            try:
+                self._configure(dev, wwn, readonly)
+            except:
+                self.delete()
+                raise
+        else:
+            super(RBDStorageObject, self).__init__(backstore,
+                                                   RBDBackstore,
+                                                   name,
+                                                   'lookup')
+
+    def _configure(self, dev, wwn, readonly):
+        self._check_self()
+        if get_block_type(dev) != 0:
+            raise RTSLibError("Device %s is not a TYPE_DISK rbd device" % dev)
+        if is_dev_in_use(dev):
+            raise RTSLibError("Cannot configure StorageObject because "
+                              + "device %s is already in use." % dev)
+        self._set_udev_path(dev)
+        self._control("udev_path=%s" % dev)
+        self._control("readonly=%d" % readonly)
+        self._enable()
+        if wwn:
+            self.wwn = wwn
+        else:
+            self.wwn = generate_wwn('unit_serial')
+
+    def _get_major(self):
+        self._check_self()
+        return int(self._parse_info('Major'))
+
+    def _get_minor(self):
+        self._check_self()
+        return int(self._parse_info('Minor'))
+
+    def _get_wb_enabled(self):
+        self._check_self()
+        return bool(int(self.get_attribute("emulate_write_cache")))
+
+    def _get_readonly(self):
+        self._check_self()
+        # 'readonly' not present before kernel 3.6
+        try:
+            return bool(int(self._parse_info('readonly')))
+        except AttributeError:
+            return False
+
+    # RBDStorageObject public stuff
+
+    major = property(_get_major,
+            doc="Get the block device major number")
+    minor = property(_get_minor,
+            doc="Get the block device minor number")
+    write_back = property(_get_wb_enabled,
+            doc="True if write-back, False if write-through (write cache disabled)")
+    readonly = property(_get_readonly,
+            doc="True if the device is read-only, False if read/write")
+
+    def dump(self):
+        d = super(RBDStorageObject, self).dump()
+        d['write_back'] = self.write_back
+        d['readonly'] = self.readonly
+        d['wwn'] = self.wwn
+        d['dev'] = self.udev_path
+        return d
+
 def _test():
     import doctest
     doctest.testmod()
Index: rtslib-2.2/rtslib/__init__.py
===================================================================
--- rtslib-2.2.orig/rtslib/__init__.py
+++ rtslib-2.2/rtslib/__init__.py
@@ -27,6 +27,7 @@ from tcm import FileIOBackstore, IBlockB
 from tcm import FileIOStorageObject, IBlockStorageObject
 from tcm import PSCSIBackstore, RDMCPBackstore
 from tcm import PSCSIStorageObject, RDMCPStorageObject
+from tcm import RBDBackstore, RBDStorageObject
 
 from config_filters import *
 from config import Config, ConfigError
Index: rtslib-2.2/rtslib/root.py
===================================================================
--- rtslib-2.2.orig/rtslib/root.py
+++ rtslib-2.2/rtslib/root.py
@@ -25,6 +25,7 @@ from node import CFSNode
 from target import Target, FabricModule
 from tcm import FileIOBackstore, IBlockBackstore
 from tcm import PSCSIBackstore, RDMCPBackstore
+from tcm import RBDBackstore
 from utils import RTSLibError, RTSLibBrokenLink, modprobe, mount_configfs
 
 class RTSRoot(CFSNode):
@@ -91,6 +92,8 @@ class RTSRoot(CFSNode):
                         yield IBlockBackstore(int(regex.group(3)), 'lookup')
                     elif regex.group(1) == "rd_mcp":
                         yield RDMCPBackstore(int(regex.group(3)), 'lookup')
+                    elif regex.group(1) == "rbd":
+                        yield RBDBackstore(int(regex.group(3)), 'lookup')
 
     def _list_storage_objects(self):
         self._check_self()
Index: rtslib-2.2/rtslib/config_live.py
===================================================================
--- rtslib-2.2.orig/rtslib/config_live.py
+++ rtslib-2.2/rtslib/config_live.py
@@ -32,7 +32,8 @@ from rtslib import (RTSRoot, Target, Fab
                     FileIOStorageObject, IBlockBackstore,
                     IBlockStorageObject, PSCSIBackstore,
                     PSCSIStorageObject, RDMCPBackstore,
-                    RDMCPStorageObject, RTSLibError)
+                    RDMCPStorageObject, RBDBackstore,
+                    RBDStorageObject, RTSLibError)
 
 # TODO There seems to be a bug in LIO, affecting both this API and rtslib:
 # when a tpg does not contain any objects, it cannot be removed.
@@ -96,7 +97,7 @@ def dump_live_storage():
         dump.append("storage %s disk %s {"
                     % (so.backstore.plugin, so.name))
         attrs = []
-        if so.backstore.plugin in ['fileio', 'pscsi', 'iblock']:
+        if so.backstore.plugin in ['fileio', 'pscsi', 'iblock', 'rbd']:
             attrs.append("%spath %s" % (_indent, so.udev_path))
         if so.backstore.plugin in ['fileio', 'rd_mcp']:
             attrs.append("%ssize %s" % (_indent, _b2h(so.size)))
@@ -509,6 +510,12 @@ def apply_create_obj(obj):
             nullio = obj_attr(obj, "nullio")
             lio_so = lio_bs.storage_object(name, size, True, nullio)
             apply_group_attrs(obj, lio_so)
+        elif plugin == 'rbd':
+            # TODO Add policy for rbd
+            lio_bs = RBDBackstore(idx)
+            dev = obj_attr(obj, "path")
+            lio_so = lio_bs.storage_object(name, dev)
+            apply_group_attrs(obj, lio_so)
         else:
             raise ConfigError("Unknown backend '%s' for backstore '%s'"
                               % (plugin, obj))
Index: rtslib-2.2/policy/backstore_rbd.lio
===================================================================
--- /dev/null
+++ rtslib-2.2/policy/backstore_rbd.lio
@@ -0,0 +1,28 @@
+storage rbd disk %str {
+    path %str
+    attribute {
+        block_size %int(512)
+        emulate_3pc %bool(yes)
+        emulate_caw %bool(yes)
+        emulate_dpo %bool(no)
+        emulate_fua_read %bool(no)
+        emulate_fua_write %bool(yes)
+        emulate_model_alias %bool(no)
+        emulate_rest_reord %bool(no)
+        emulate_tas %bool(yes)
+        emulate_tpu %bool(no)
+        emulate_tpws %bool(no)
+        emulate_ua_intlck_ctrl %bool(no)
+        emulate_write_cache %bool(no)
+        enforce_pr_isids %bool(yes)
+        fabric_max_sectors %int(8192)
+        is_nonrot %bool(yes)
+        max_unmap_block_desc_count %int(0)
+        max_unmap_lba_count %int(0)
+        max_write_same_len %int(65535)
+        optimal_sectors %int(8192)
+        queue_depth %int(128)
+        unmap_granularity %int(0)
+        unmap_granularity_alignment %int(0)
+    }
+}
