Sandro Bonazzola has uploaded a new change for review.

Change subject: WIP: use VDSM for creating volumes
......................................................................

WIP: use VDSM for creating volumes

Change-Id: Iaeae8bfbe931aa47b7afa36207f712f1335c2bd7
Signed-off-by: Sandro Bonazzola <sbona...@redhat.com>
---
M ovirt_hosted_engine_ha/lib/storage_backends.py
1 file changed, 126 insertions(+), 6 deletions(-)


  git pull ssh://gerrit.ovirt.org:29418/ovirt-hosted-engine-ha 
refs/changes/37/28237/1

diff --git a/ovirt_hosted_engine_ha/lib/storage_backends.py 
b/ovirt_hosted_engine_ha/lib/storage_backends.py
index b3b562a..78f4e55 100644
--- a/ovirt_hosted_engine_ha/lib/storage_backends.py
+++ b/ovirt_hosted_engine_ha/lib/storage_backends.py
@@ -12,8 +12,18 @@
 from io import BytesIO
 from operator import itemgetter
 import math
+import time
+
+import vdsm.vdscli
 
 logger = logging.getLogger(__name__)
+
+
+# VDSM storage constants
+RAW_FORMAT = 5
+PREALLOCATED_VOL = 1
+DATA_DISK_TYPE = 2
+TASK_WAIT = 1
 
 
 class BlockBackendCorruptedException(Exception):
@@ -22,6 +32,17 @@
     structure reports a corrupted data (CRC mismatch).
     """
     pass
+
+
+class BlockDevice(object):
+    """
+    Block device configuration for VDSM usage.
+    """
+    def __init__(self, imgUUID, volUUID, size):
+        super(BlockDevice, self).__init__()
+        self.imgUUID = imgUUID
+        self.volUUID = volUUID
+        self.size = size
 
 
 class StorageBackend(object):
@@ -93,9 +114,10 @@
 
     LVSCAN_RE = re.compile("LSize ([0-9]*)B")
 
-    def __init__(self, sd_uuid, dom_type):
+    def __init__(self, sd_uuid, dom_type, sp_uuid=None):
         super(FilesystemBackend, self).__init__()
         self._sd_uuid = sd_uuid
+        self._sp_uuid = sp_uuid
         self._dom_type = dom_type
         self._lv_based = False
         self._storage_path = None
@@ -263,7 +285,100 @@
                             service_path)
                 return False
 
+    def create_volume(self, service, device):
+        """
+        service: a string identifying the service
+        device: a BlockDevice object
+        Returns True if the volume has been created, False otherwise.
+        Raise RuntimeError if something goes wrong.
+        """
+        if self._sp_uuid is None:
+            raise RuntimeError(
+                "Storage Pool must be defined for creating volumes"
+            )
+        logger.debug("Connecting to VDSM")
+        connection = vdsm.vdscli.connect(
+            hostPort=vdsm.vdscli.cannonizeHostPort(
+                hostPort="localhost",
+            ),
+        )
+        response =  connection.getVolumePath(
+            self._sd_uuid,
+            self._sp_uuid,
+            self.device.imgUUID,
+            self.device.volUUID
+        )
+        logger.debug("getVolumePath: %s" % str(response))
+        if response["status"]["code"] == 0:
+            logger.info(
+                "Image for {service} already exists".format(
+                service=service,
+            )
+            path = response['path']
+            return False, path
+        if response["status"]["code"] != 100:
+            # 100 is returned when the volume doesn't exists
+            raise RuntimeError(response["status"]["message"])
+
+        logger.info(
+            "Creating Image for {service}".format(
+                service=service,
+        )
+        create_response =  connection.createVolume(
+            self._sd_uuid,
+            self._sp_uuid,
+            self.device.imgUUID,
+            float(self.device.size)/float(pow(2,30)),
+            RAW_FORMAT,
+            PREALLOCATED_VOL,
+            DATA_DISK_TYPE,
+            self.device.volUUID,
+            service
+        )
+        logger.debug("createVolume: %s" % str(create_response))
+        if create_response["status"]["code"] != 0:
+            raise RuntimeError(create_response["status"]["message"])
+        task = create_response["uuid"]
+        finished = False
+        while not finished:
+            task_status =  connection.getTaskStatus(task)
+            logger.debug("getTaskStatus: %s" % str(task_status))
+            if task_status["status"]["code"] != 0:
+                raise RuntimeError(task_status["status"]["message"])
+            if task_status["taskStatus"]["taskState"] == "finished":
+                if task_status["taskStatus"]["taskResult"] != "success":
+                    raise RuntimeError(task_status["taskStatus"]["message"])
+                finished = True
+            else:
+                time.sleep(TASK_WAIT)
+        response = connection.clearTask(task)
+        logger.debug("clearTask: %s" % str(response))
+        logger.info(
+            "Image for {service} created successfully".format(
+                service=service,
+        )
+        response =  connection.getVolumePath(
+            self._sd_uuid,
+            self._sp_uuid,
+            self.device.imgUUID,
+            self.device.volUUID
+        )
+        logger.debug("getVolumePath: %s" % str(response))
+        if response["status"]["code"] != 0:
+            raise RuntimeError(response["status"]["message"])
+        path = response['path']
+        return True, path
+
+
     def create(self, service_map, force_new=False):
+        """
+        service_map: looks like:
+        >>> {
+        >>>     lockspace + '.lockspace': BlockDevice(...),
+        >>>     lockspace + '.metadata': BlockDevice(...)
+        >>> }
+        """
+
         base_path, self._lv_based = self.get_domain_path(self._sd_uuid,
                                                          self._dom_type)
         self._storage_path = os.path.join(base_path,
@@ -272,12 +387,17 @@
         util.mkdir_recursive(self._storage_path)
 
         new_set = set()
-        for service, size in service_map.iteritems():
+        for service, device in service_map.iteritems():
             service_path = os.path.join(self._storage_path, service)
-            if self._lv_based:
-                isnew = self._create_block(service, size, force_new)
-            else:
-                isnew = self._create_file(service_path, size, force_new)
+            isnew, path = self.create_volume(service, device)
+            # TODO: create symlinks
+
+            #if self._lv_based:
+                #isnew = self._create_block(service, device.size, force_new)
+            #else:
+                #isnew = self._create_file(
+                    #service_path, device.size, force_new
+                #)
 
             # record all new services
             if isnew:


-- 
To view, visit http://gerrit.ovirt.org/28237
To unsubscribe, visit http://gerrit.ovirt.org/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: Iaeae8bfbe931aa47b7afa36207f712f1335c2bd7
Gerrit-PatchSet: 1
Gerrit-Project: ovirt-hosted-engine-ha
Gerrit-Branch: master
Gerrit-Owner: Sandro Bonazzola <sbona...@redhat.com>
_______________________________________________
Engine-patches mailing list
Engine-patches@ovirt.org
http://lists.ovirt.org/mailman/listinfo/engine-patches

Reply via email to