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