Hi,

I implemented selective block device handling, revised patch follows.

Apollon

---

Add bdev_list RPC call to query block devices about their size. The RPC 
call
accepts a list of block devices to query. If no list is given, then all block
devices under constants.BLOCKDEV_DIR are queried. By default
constants.BLOCKDEV_DIR is set to '/dev/disk', where persistent symlinks for
block devices are expected to reside, created by auxiliary means, such as udev
rules.

Signed-off-by: Apollon Oikonomopoulos <[email protected]>
---
 daemons/ganeti-noded |    9 +++++++++
 lib/backend.py       |   33 +++++++++++++++++++++++++++++++++
 lib/constants.py     |    1 +
 lib/rpc.py           |    9 +++++++++
 4 files changed, 52 insertions(+), 0 deletions(-)

diff --git a/daemons/ganeti-noded b/daemons/ganeti-noded
index 21227fa..939e61a 100755
--- a/daemons/ganeti-noded
+++ b/daemons/ganeti-noded
@@ -409,6 +409,15 @@ class NodeHttpServer(http.server.HttpServer):
     export = params[0]
     return backend.RemoveExport(export)
 
+  # block device ---------------------
+  @staticmethod
+  def perspective_bdev_list(params):
+    """Query the list of block devices
+
+    """
+    devices = params[0]
+    return backend.GetBlockdevList(devices)
+
   # volume  --------------------------
 
   @staticmethod
diff --git a/lib/backend.py b/lib/backend.py
index f37b0c4..e3d81c4 100644
--- a/lib/backend.py
+++ b/lib/backend.py
@@ -605,6 +605,39 @@ def VerifyNode(what, cluster_name):
   return result
 
 
+def GetBlockdevList(devices):
+  """Compute the list of block devices and their size
+
+  @rtype: dict
+  @return:
+    dictionary of all block devices under /dev/disk (key). The value is their
+    size in MiB.
+
+    {'/dev/disk/by-uuid/123456-12321231-312312-312': 124}
+
+  """
+  blockdevs = {}
+  if not devices:
+    for root, dirs, files in os.walk(constants.BLOCKDEV_DIR):
+      for dev in files:
+        devices.append(os.path.join(root,dev))
+
+  for device in devices:
+    if os.path.exists(device):
+      if stat.S_ISBLK(os.stat(device)[stat.ST_MODE]):
+        result = utils.RunCmd(["blockdev", "--getsize64", device])
+        if result.failed:
+          # We don't want to fail, just warn and do not list this device
+          # as available
+          logging.warn("Warning: unable to determine the size of %s: %s" %
+                       (device, result.stderr))
+          continue
+
+        size = int(result.stdout) / (1024 * 1024)
+        blockdevs[device] = size
+  return blockdevs
+
+
 def GetVolumeList(vg_name):
   """Compute list of logical volumes and their size.
 
diff --git a/lib/constants.py b/lib/constants.py
index 6b8802f..1f0b3aa 100644
--- a/lib/constants.py
+++ b/lib/constants.py
@@ -102,6 +102,7 @@ CRYPTO_KEYS_DIR = RUN_GANETI_DIR + "/crypto"
 CRYPTO_KEYS_DIR_MODE = SECURE_DIR_MODE
 IMPORT_EXPORT_DIR = RUN_GANETI_DIR + "/import-export"
 IMPORT_EXPORT_DIR_MODE = 0755
+BLOCKDEV_DIR = "/dev/disk"
 # keep RUN_GANETI_DIR first here, to make sure all get created when the node
 # daemon is started (this takes care of RUN_DIR being tmpfs)
 SUB_RUN_DIRS = [ RUN_GANETI_DIR, BDEV_CACHE_DIR, DISK_LINKS_DIR ]
diff --git a/lib/rpc.py b/lib/rpc.py
index 57dd960..e7c2386 100644
--- a/lib/rpc.py
+++ b/lib/rpc.py
@@ -492,6 +492,15 @@ class RpcRunner(object):
   # Begin RPC calls
   #
 
+  @_RpcTimeout(_TMO_NORMAL)
+  def call_bdev_list(self, node_list, devices=[]):
+    """Gets the list of block devices present on a node
+
+    This is a multi-node call.
+
+    """
+    return self._MultiNodeCall(node_list, "bdev_list", [devices])
+
   @_RpcTimeout(_TMO_URGENT)
   def call_lv_list(self, node_list, vg_name):
     """Gets the logical volumes present in a given volume group.
-- 
1.7.1

Reply via email to