ext_storage: Add 'snapshot' and 'setinfo' actions
[archipelago] / xseg / tools / ext_scripts / vlmc_wrapper.py
index 6c564ac..24ef39b 100755 (executable)
@@ -1,6 +1,6 @@
 #!/usr/bin/env python
 #
-# Copyright (C) 2011 Greek Research and Technology Network
+# Copyright (C) 2012-2013 Greek Research and Technology Network
 #
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
@@ -39,228 +39,149 @@ Returns O after successfull completion, 1 on failure
 import os
 import sys
 
-from ganeti import utils
+from archipelago.common import Error, DEVICE_PREFIX, loadrc
+from archipelago import vlmc as vlmc
 
 
 def ReadEnv():
-  """Read the enviromental variables
-  """
+    """Read the enviromental variables"""
+    name = os.getenv("VOL_NAME")
+    if name is None:
+        sys.stderr.write('The environment variable VOL_NAME is missing.\n')
+        return None
 
-  name = os.getenv("VOL_NAME")
-  if name is None:
-    sys.stderr.write('The environment variable VOL_NAME is missing.\n')
-    return None
+    return {"name": name,
+            "size": os.getenv("VOL_SIZE"),
+            "origin": os.getenv("EXTP_ORIGIN"),
+            "snapshot_name": os.getenv("VOL_SNAPSHOT_NAME"),
+            }
 
-  size = os.getenv("VOL_SIZE")
-#  if size is None:
-#    sys.stderr.write('The environment variable VOL_SIZE is missing.\n')
-#    return None
-
-  origin = os.getenv("EXTP_ORIGIN")
-
-  return (name, size, origin)
 
 def create(env):
-  """Create a new vlmc Image
-  """
-  sys.stderr.write('Creation started...\n')
-
-  name, size, origin = env
-
-  cmd = ["vlmc", "create", "%s" % name, "--size", "%s" % size]
-  if origin:
-     cmd.extend(["--snap", origin])
-
-  sys.stderr.write('Before RunCmd')
-  result = utils.RunCmd(cmd)
-  sys.stderr.write('After RunCmd')
-
-  if result.failed:
-    sys.stderr.write('vlmc creation failed (%s): %s\n' %
-                     (result.fail_reason, result.output))
-    return 1 
-
-  return 0
-
-def _ParseVlmcShowmappedOutput(output, volume_name):
-  """Parse the output of `vlmc showmapped'.
-
-  This method parses the output of `vlmc showmapped' and returns
-  the vlmc block device path (e.g. /dev/xsegbd0) that matches the
-  given vlmc volume.
-
-  """
-  allfields = 5
-  volumefield = 2
-  devicefield = 4
-
-  field_sep = "\t"
-
-  lines = output.splitlines()
-  splitted_lines = map(lambda l: l.split(field_sep), lines)
-
-  # Check empty output.
-  if not splitted_lines:
-    sys.stderr.write("vlmc showmapped returned empty output")
-    sys.exit(1)
-
-  # Check showmapped header line, to determine number of fields.
-  field_cnt = len(splitted_lines[0])
-  if field_cnt != allfields:
-    sys.stderr.write("Cannot parse vlmc showmapped output because its format"
-                " seems to have changed; expected %s fields, found %s" % 
-               (allfields, field_cnt)
-    sys.exit(1)
-
-  matched_lines = \
-    filter(lambda l: len(l) == allfields and l[volumefield] == volume_name,
-           splitted_lines)
+    """Create a new vlmc Image."""
+    name = env.get("name")
+    size = env.get("size")
+    origin = env.get("origin")
+
+    sys.stderr.write("Creating volume '%s' of size '%s' from '%s'\n"
+                     % (name, size, origin))
+    vlmc.create(name=name, size=int(size), snap=origin)
+    return 0
 
-  if len(matched_lines) > 1:
-    sys.stderr.write("The vlmc volume %s is mapped more than once."
-                " This shouldn't happen, try to unmap the extra"
-                " devices manually." % volume_name)
-    sys.exit(1) 
 
-  if matched_lines:
-    # vlmc block device found. Return it.
-    dev = matched_lines[0][devicefield]
-    return dev
+def snapshot(env):
+    """Create a snapshot of an existing vlmc Image."""
+    name = env.get("name")
+    snapshot_name = env.get("snapshot_name")
+    sys.stderr.write("Creating snapshot '%s' from '%s'\n" %
+                     (snapshot_name, name))
+    vlmc.snapshot(name=name, snap_name=snapshot_name)
+    return 0
 
-  # The given volume is not mapped.
-  return None
 
 def attach(env):
-  """Map an existing vlmc Image to a block device
-
-  This function maps an existing vlmc Image to a block device
-  e.g. /dev/xsegbd{X} and returns the device path. If the mapping
-  already exists, it returns the corresponding device path.
-  """
-
-  name, _, _ = env
-
-  # Check if the mapping already exists
-  cmd = ["vlmc", "showmapped"]
-  result = utils.RunCmd(cmd)
-  if result.failed:
-    sys.stderr.write("vlmc showmapped failed (%s): %s" %
-                     (result.fail_reason, result.output))
-    return 1
-
-  dev = _ParseVlmcShowmappedOutput(result.output, name)
-  if dev:
-    # The mapping exists. Return it.
-    sys.stdout.write("%s" % str(dev))
+    """Map an existing vlmc Image to a block device
+
+    This function maps an existing vlmc Image to a block device
+    e.g. /dev/xsegbd{X} and returns the device path. If the mapping
+    already exists, it returns the corresponding device path.
+
+    """
+
+    name = env.get("name")
+
+    # Check if the mapping already exists
+    d_id = vlmc.is_mapped(name)
+    if d_id:
+      # The mapping exists. Return it.
+        sys.stdout.write("%s" % str(DEVICE_PREFIX + str(d_id)))
+        return 0
+    # The mapping doesn't exist. Create it.
+    d_id = vlmc.map_volume(name=name)
+    # The device was successfully mapped. Return it.
+    #maybe assert (d_id == vlmc.is_mapped(name)
+    sys.stdout.write("%s" % str(DEVICE_PREFIX + str(d_id)))
     return 0
 
-  # The mapping doesn't exist. Create it.
-  map_cmd = ["vlmc", "map", name]
-  result = utils.RunCmd(map_cmd)
-  if result.failed:
-    sys.stderr.write("vlmc map failed (%s): %s" %
-                (result.fail_reason, result.output))
-    return 1
-
-  # Find the corresponding vlmc device.
-  showmap_cmd = ["vlmc", "showmapped"]
-  result = utils.RunCmd(showmap_cmd)
-  if result.failed:
-    sys.stderr.write("vlmc map succeeded, but showmapped failed (%s): %s" %
-                (result.fail_reason, result.output))
-    return 1
-
-  dev = _ParseVlmcShowmappedOutput(result.output, name)
-
-  if not dev:
-    sys.stderr.write("vlmc map succeeded, but could not find the vlmc block"
-                " device in output of showmapped, for volume: %s" % name)
-
-  # The device was successfully mapped. Return it.
-  sys.stdout.write("%s" % str(dev))
-  return 0
 
 def detach(env):
-  """Unmap a vlmc device from the Image it is mapped to
-
-  This function unmaps an vlmc device from the Image it is mapped to.
-  It is idempotent if the mapping doesn't exist at all.
-  """
-  name, _, _ = env
+    """Unmap a vlmc device from the Image it is mapped to
 
-  # Check if the mapping already exists
-  cmd = ["vlmc", "showmapped"]
-  result = utils.RunCmd(cmd)
-  if result.failed:
-    sys.stderr.write("vlmc showmapped failed (%s): %s" %
-                     (result.fail_reason, result.output))
-    return 1
+    This function unmaps an vlmc device from the Image it is mapped to.
+    It is idempotent if the mapping doesn't exist at all.
 
-  dev = _ParseVlmcShowmappedOutput(result.output, name)
+    """
+    name = env.get("name")
 
-  if dev:
-    # The mapping exists. Unmap the vlmc device.
-    unmap_cmd = ["vlmc", "unmap", "%s" % dev]
-    result = utils.RunCmd(unmap_cmd)
-    if result.failed:
-      sys.stderr.write("vlmc unmap failed (%s): %s",
-                  result.fail_reason, result.output)
+    #try:
+    # Check if the mapping already exists
+    d_id = vlmc.is_mapped(name)
+    if d_id:
+        # The mapping exists. Unmap the vlmc device.
+        vlmc.unmap_volume(name=str(DEVICE_PREFIX + str(d_id)))
+    #assert(vlmc.is_mapped(name) == None)
+    return 0
+    #except Error as e:
+    #  sys.stderr.write(str(e)+'\n')
+    #  return -1
 
-  return 0
 
 def grow(env):
-  """Grow an existing vlmc Image
-  """
-  name, size, _ = env
-
-  cmd = ["vlmc", "resize", "%s" % name, "--size", "%s" % size]
+    """Grow an existing vlmc Image"""
+    name = env.get("name")
+    size = env.get("size")
 
-  result = utils.RunCmd(cmd)
-  if result.failed:
-    sys.stderr.write('vlmc resize failed (%s): %s\n' %
-                     (result.fail_reason, result.output))
-    return 1
+    sys.stderr.write("Resizing '%s'. New size '%s'\n" % (name, size))
+    vlmc.resize(name=name, size=int(size))
+    return 0
 
-  return 0
 
 def remove(env):
-  """ Delete a vlmc Image
-  """
+    """Delete a vlmc Image"""
+    name = env.get("name")
 
-  name, _, _ = env
+    sys.stderr.write("Deleting '%s'\n" % name)
+    vlmc.remove(name=name)
+    return 0
 
-  cmd = ["vlmc", "rm", "%s" % name]
 
-  result = utils.RunCmd(cmd)
-  if result.failed:
-    sys.stderr.write("Can't remove Image %s from cluster with vlmc rm: "
-                     "%s - %s" % 
-                     (name, result.fail_reason, result.output))
-    return 1
+def verify(env):
+    return 0
 
-  return 0
 
-def verify(env):
-  return 0
+def setinfo(env):
+    return 0
+
 
 def main():
-  env = ReadEnv()
-  if env is None:
-    sys.stderr.write("Wrong environment. Aborting...\n")
-    return 1
-
-  try:
-    return {
-      'attach': attach,
-      'create': create,
-      'detach': detach,
-      'grow'  : grow,
-      'remove': remove,
-      'verify': verify
-    }[os.path.basename(sys.argv[0])](env)
-  except:
-    sys.stderr.write("Op not supported")
-    return 1
+    env = ReadEnv()
+    if env is None:
+        sys.stderr.write("Wrong environment. Aborting...\n")
+        return 1
+
+    loadrc(None)
+
+    actions = {
+        'create': create,
+        'snapshot': snapshot,
+        'attach': attach,
+        'detach': detach,
+        'grow': grow,
+        'remove': remove,
+        'verify': verify,
+        'setinfo': setinfo,
+    }
+
+    try:
+        action_name = os.path.basename(sys.argv[0])
+        action = actions[action_name]
+        return action(env)
+    except KeyError:
+        sys.stderr.write("Action '%s' not supported\n" % action_name)
+        return 1
+    except Error as e:
+        sys.stderr.write("Archipelago error: %s\n" % e)
+        return 1
 
 if __name__ == "__main__":
     sys.exit(main())