bdev: Allow userspace-only disk templates
authorDimitris Aragiorgis <dimitris.aragiorgis@gmail.com>
Thu, 30 Jul 2015 19:56:49 +0000 (22:56 +0300)
committerHrvoje Ribicic <riba@google.com>
Mon, 17 Aug 2015 15:12:08 +0000 (15:12 +0000)
Until now all implementations at the bdev level require a local
block device on the primary node. Since there are storage
technologies that allow userspace access only without the need of
a block device, (e.g. QEMU + RADOS), this patch makes the
corresponding changes to support this kind of functionality.
Note that for this to work you need corresponding support in the
OS definition.

This patch changes the backend logic so that it can handle the
absence of local block devices.

Finally, it extends the ExtStorage interface to support the above
functionality. Until now the 'attach' script returned the block
device in the first line. With this patch, if this line is empty,
it denotes that a local block device is not available.

An example could be a RADOS provider where the volume does not get
mapped locally (i.e., no /dev/rbdX device) and the attach script
returns two lines: an empty line denoting that no local block device
exists and a second line with the appropriate KVM userspace URI
(i.e. kvm:rbd:<pool>/<volume name>).

Adjust OpInstanceActivateDisks so that a None dev_path is handled
correctly as a return value.

Signed-off-by: Dimitris Aragiorgis <dimitris.aragiorgis@gmail.com>
Reviewed-by: Hrvoje Ribicic <riba@google.com>

doc/design-shared-storage.rst
lib/backend.py
lib/storage/extstorage.py
man/ganeti-extstorage-interface.rst
src/Ganeti/OpCodes.hs

index d389e03..0390264 100644 (file)
@@ -329,7 +329,9 @@ with the hypervisor it corresponds to (e.g. kvm:<uri>). The prefix will
 be case insensitive. If the 'attach' script doesn't return any extra
 lines, we assume that the ExtStorage provider doesn't support userspace
 access (this way we maintain backward compatibility with the existing
-'attach' scripts).
+'attach' scripts). In case the provider supports *only* userspace
+access and thus a local block device is not available, then the first
+line should be an empty line.
 
 The 'GetUserspaceAccessUri' method of the 'ExtStorageDevice' class will
 parse the output of the 'attach' script and if the provider supports
index 140c3cc..4674002 100644 (file)
@@ -2538,6 +2538,10 @@ def _SymlinkBlockDev(instance_name, device_path, idx):
   @return: absolute path to the disk's symlink
 
   """
+  # In case we have only a userspace access URI, device_path is None
+  if not device_path:
+    return None
+
   link_name = _GetBlockDevSymlinkPath(instance_name, idx)
   try:
     os.symlink(device_path, link_name)
@@ -4045,9 +4049,10 @@ def OSEnvironment(instance, inst_os, debug=0):
   for idx, disk in enumerate(instance.disks_info):
     real_disk = _OpenRealBD(disk)
     uri = _CalculateDeviceURI(instance, disk, real_disk)
-    result["DISK_%d_PATH" % idx] = real_disk.dev_path
     result["DISK_%d_ACCESS" % idx] = disk.mode
     result["DISK_%d_UUID" % idx] = disk.uuid
+    if real_disk.dev_path:
+      result["DISK_%d_PATH" % idx] = real_disk.dev_path
     if uri:
       result["DISK_%d_URI" % idx] = uri
     if disk.name:
index 10d766b..311662f 100644 (file)
@@ -142,6 +142,16 @@ class ExtStorageDevice(base.BlockDev):
     self.dev_path = result[0]
     self.uris = result[1:]
 
+    if not self.dev_path:
+      logging.info("A local block device is not available")
+      self.dev_path = None
+      if not self.uris:
+        logging.error("Neither a block device nor a userspace URI is available")
+        return False
+
+      self.attached = True
+      return True
+
     # Verify that dev_path exists and is a block device
     try:
       st = os.stat(self.dev_path)
index 75ca639..49631b0 100644 (file)
@@ -129,6 +129,23 @@ The attach script should be idempotent if the volume is already mapped.
 If the requested volume is already mapped, then the script should just
 return to its stdout the path which is already mapped to.
 
+In case the storage technology supports userspace access to volumes as
+well, e.g. the QEMU Hypervisor can see an RBD volume using its embedded
+driver for the RBD protocol, then the provider can return extra lines
+denoting the available userspace access URIs per hypervisor. The URI
+should be in the following format: <hypervisor>:<uri>. For example, a
+RADOS provider should return kvm:rbd:<pool>/<volume name> in the second
+line of stdout after the local block device path (e.g. /dev/rbd1).
+
+So, if the ``access`` disk parameter is ``userspace`` for the ext disk
+template, then the QEMU command will end up having file=<URI> in
+the ``-drive`` option.
+
+In case the storage technology supports *only* userspace access to
+volumes, then the first line of stdout should be an empty line, denoting
+that a local block device is not available. If neither a block device
+nor a URI is returned, then Ganeti will complain.
+
 detach
 ~~~~~~
 
index a071a8c..37b645e 100644 (file)
@@ -631,7 +631,7 @@ $(genOpCode "OpCode"
      ],
      "instance_name")
   , ("OpInstanceActivateDisks",
-     [t| [(NonEmptyString, NonEmptyString, NonEmptyString)] |],
+     [t| [(NonEmptyString, NonEmptyString, Maybe NonEmptyString)] |],
      OpDoc.opInstanceActivateDisks,
      [ pInstanceName
      , pInstanceUuid