Improve size handling during volume add/resize
This commit is contained in:
		@@ -73,6 +73,11 @@ byte_unit_matrix = {
 | 
				
			|||||||
    "G": 1024 * 1024 * 1024,
 | 
					    "G": 1024 * 1024 * 1024,
 | 
				
			||||||
    "T": 1024 * 1024 * 1024 * 1024,
 | 
					    "T": 1024 * 1024 * 1024 * 1024,
 | 
				
			||||||
    "P": 1024 * 1024 * 1024 * 1024 * 1024,
 | 
					    "P": 1024 * 1024 * 1024 * 1024 * 1024,
 | 
				
			||||||
 | 
					    "E": 1024 * 1024 * 1024 * 1024 * 1024 * 1024,
 | 
				
			||||||
 | 
					    "Z": 1024 * 1024 * 1024 * 1024 * 1024 * 1024 * 1024,
 | 
				
			||||||
 | 
					    "Y": 1024 * 1024 * 1024 * 1024 * 1024 * 1024 * 1024 * 1024,
 | 
				
			||||||
 | 
					    "R": 1024 * 1024 * 1024 * 1024 * 1024 * 1024 * 1024 * 1024 * 1024,
 | 
				
			||||||
 | 
					    "Q": 1024 * 1024 * 1024 * 1024 * 1024 * 1024 * 1024 * 1024 * 1024 * 1024,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Matrix of human-to-metric values
 | 
					# Matrix of human-to-metric values
 | 
				
			||||||
@@ -83,6 +88,11 @@ ops_unit_matrix = {
 | 
				
			|||||||
    "G": 1000 * 1000 * 1000,
 | 
					    "G": 1000 * 1000 * 1000,
 | 
				
			||||||
    "T": 1000 * 1000 * 1000 * 1000,
 | 
					    "T": 1000 * 1000 * 1000 * 1000,
 | 
				
			||||||
    "P": 1000 * 1000 * 1000 * 1000 * 1000,
 | 
					    "P": 1000 * 1000 * 1000 * 1000 * 1000,
 | 
				
			||||||
 | 
					    "E": 1000 * 1000 * 1000 * 1000 * 1000 * 1000,
 | 
				
			||||||
 | 
					    "Z": 1000 * 1000 * 1000 * 1000 * 1000 * 1000 * 1000,
 | 
				
			||||||
 | 
					    "Y": 1000 * 1000 * 1000 * 1000 * 1000 * 1000 * 1000 * 1000,
 | 
				
			||||||
 | 
					    "R": 1000 * 1000 * 1000 * 1000 * 1000 * 1000 * 1000 * 1000 * 1000,
 | 
				
			||||||
 | 
					    "Q": 1000 * 1000 * 1000 * 1000 * 1000 * 1000 * 1000 * 1000 * 1000 * 1000,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -103,14 +113,18 @@ def format_bytes_tohuman(databytes):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def format_bytes_fromhuman(datahuman):
 | 
					def format_bytes_fromhuman(datahuman):
 | 
				
			||||||
    # Trim off human-readable character
 | 
					    if not re.search(r"[A-Za-z]+", datahuman):
 | 
				
			||||||
    dataunit = str(datahuman)[-1]
 | 
					 | 
				
			||||||
    datasize = int(str(datahuman)[:-1])
 | 
					 | 
				
			||||||
    if not re.match(r"[A-Z]", dataunit):
 | 
					 | 
				
			||||||
        dataunit = "B"
 | 
					        dataunit = "B"
 | 
				
			||||||
        datasize = int(datahuman)
 | 
					        datasize = int(datahuman)
 | 
				
			||||||
 | 
					    else:
 | 
				
			||||||
 | 
					        dataunit = str(re.match(r"[0-9]+([A-Za-z])[iBb]*", datahuman).group(1))
 | 
				
			||||||
 | 
					        datasize = int(re.match(r"([0-9]+)[A-Za-z]+", datahuman).group(1))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if byte_unit_matrix.get(dataunit):
 | 
				
			||||||
        databytes = datasize * byte_unit_matrix[dataunit]
 | 
					        databytes = datasize * byte_unit_matrix[dataunit]
 | 
				
			||||||
        return databytes
 | 
					        return databytes
 | 
				
			||||||
 | 
					    else:
 | 
				
			||||||
 | 
					        return None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Format ops sizes to/from human-readable units
 | 
					# Format ops sizes to/from human-readable units
 | 
				
			||||||
@@ -731,22 +745,26 @@ def getVolumeInformation(zkhandler, pool, volume):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def add_volume(zkhandler, pool, name, size):
 | 
					def add_volume(zkhandler, pool, name, size):
 | 
				
			||||||
    # Add 'B' if the volume is in bytes
 | 
					 | 
				
			||||||
    if re.match(r"^[0-9]+$", size):
 | 
					 | 
				
			||||||
        size = "{}B".format(size)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    # 1. Verify the size of the volume
 | 
					    # 1. Verify the size of the volume
 | 
				
			||||||
    pool_information = getPoolInformation(zkhandler, pool)
 | 
					    pool_information = getPoolInformation(zkhandler, pool)
 | 
				
			||||||
    size_bytes = format_bytes_fromhuman(size)
 | 
					    size_bytes = format_bytes_fromhuman(size)
 | 
				
			||||||
 | 
					    if size_bytes is None:
 | 
				
			||||||
 | 
					        return (
 | 
				
			||||||
 | 
					            False,
 | 
				
			||||||
 | 
					            f"ERROR: Requested volume size '{size}' does not have a valid SI unit",
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if size_bytes >= int(pool_information["stats"]["free_bytes"]):
 | 
					    if size_bytes >= int(pool_information["stats"]["free_bytes"]):
 | 
				
			||||||
        return (
 | 
					        return (
 | 
				
			||||||
            False,
 | 
					            False,
 | 
				
			||||||
            "ERROR: Requested volume size is greater than the available free space in the pool",
 | 
					            f"ERROR: Requested volume size '{format_bytes_tohuman(size_bytes)}' is greater than the available free space in the pool ('{format_bytes_tohuman(pool_information['stats']['free_bytes'])}')",
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # 2. Create the volume
 | 
					    # 2. Create the volume
 | 
				
			||||||
    retcode, stdout, stderr = common.run_os_command(
 | 
					    retcode, stdout, stderr = common.run_os_command(
 | 
				
			||||||
        "rbd create --size {} {}/{}".format(size, pool, name)
 | 
					        "rbd create --size {} {}/{}".format(
 | 
				
			||||||
 | 
					            format_bytes_tohuman(size_bytes), pool, name
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    if retcode:
 | 
					    if retcode:
 | 
				
			||||||
        return False, 'ERROR: Failed to create RBD volume "{}": {}'.format(name, stderr)
 | 
					        return False, 'ERROR: Failed to create RBD volume "{}": {}'.format(name, stderr)
 | 
				
			||||||
@@ -766,7 +784,9 @@ def add_volume(zkhandler, pool, name, size):
 | 
				
			|||||||
        ]
 | 
					        ]
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return True, 'Created RBD volume "{}/{}" ({}).'.format(pool, name, size)
 | 
					    return True, 'Created RBD volume "{}" of size "{}" in pool "{}".'.format(
 | 
				
			||||||
 | 
					        name, format_bytes_tohuman(size_bytes), pool
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def clone_volume(zkhandler, pool, name_src, name_new):
 | 
					def clone_volume(zkhandler, pool, name_src, name_new):
 | 
				
			||||||
@@ -813,28 +833,32 @@ def resize_volume(zkhandler, pool, name, size):
 | 
				
			|||||||
            name, pool
 | 
					            name, pool
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # Add 'B' if the volume is in bytes
 | 
					 | 
				
			||||||
    if re.match(r"^[0-9]+$", size):
 | 
					 | 
				
			||||||
        size = "{}B".format(size)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    # 1. Verify the size of the volume
 | 
					    # 1. Verify the size of the volume
 | 
				
			||||||
    pool_information = getPoolInformation(zkhandler, pool)
 | 
					    pool_information = getPoolInformation(zkhandler, pool)
 | 
				
			||||||
    size_bytes = format_bytes_fromhuman(size)
 | 
					    size_bytes = format_bytes_fromhuman(size)
 | 
				
			||||||
 | 
					    if size_bytes is None:
 | 
				
			||||||
 | 
					        return (
 | 
				
			||||||
 | 
					            False,
 | 
				
			||||||
 | 
					            f"ERROR: Requested volume size '{size}' does not have a valid SI unit",
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if size_bytes >= int(pool_information["stats"]["free_bytes"]):
 | 
					    if size_bytes >= int(pool_information["stats"]["free_bytes"]):
 | 
				
			||||||
        return (
 | 
					        return (
 | 
				
			||||||
            False,
 | 
					            False,
 | 
				
			||||||
            "ERROR: Requested volume size is greater than the available free space in the pool",
 | 
					            f"ERROR: Requested volume size '{format_bytes_tohuman(size_bytes)}' is greater than the available free space in the pool ('{format_bytes_tohuman(pool_information['stats']['free_bytes'])}')",
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # 2. Resize the volume
 | 
					    # 2. Resize the volume
 | 
				
			||||||
    retcode, stdout, stderr = common.run_os_command(
 | 
					    retcode, stdout, stderr = common.run_os_command(
 | 
				
			||||||
        "rbd resize --size {} {}/{}".format(size, pool, name)
 | 
					        "rbd resize --size {} {}/{}".format(
 | 
				
			||||||
 | 
					            format_bytes_tohuman(size_bytes), pool, name
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    if retcode:
 | 
					    if retcode:
 | 
				
			||||||
        return (
 | 
					        return (
 | 
				
			||||||
            False,
 | 
					            False,
 | 
				
			||||||
            'ERROR: Failed to resize RBD volume "{}" to size "{}" in pool "{}": {}'.format(
 | 
					            'ERROR: Failed to resize RBD volume "{}" to size "{}" in pool "{}": {}'.format(
 | 
				
			||||||
                name, size, pool, stderr
 | 
					                name, format_bytes_tohuman(size_bytes), pool, stderr
 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -860,7 +884,7 @@ def resize_volume(zkhandler, pool, name, size):
 | 
				
			|||||||
            if target_vm_conn:
 | 
					            if target_vm_conn:
 | 
				
			||||||
                target_vm_conn.blockResize(
 | 
					                target_vm_conn.blockResize(
 | 
				
			||||||
                    volume_id,
 | 
					                    volume_id,
 | 
				
			||||||
                    format_bytes_fromhuman(size),
 | 
					                    size_bytes,
 | 
				
			||||||
                    libvirt.VIR_DOMAIN_BLOCK_RESIZE_BYTES,
 | 
					                    libvirt.VIR_DOMAIN_BLOCK_RESIZE_BYTES,
 | 
				
			||||||
                )
 | 
					                )
 | 
				
			||||||
            target_lv_conn.close()
 | 
					            target_lv_conn.close()
 | 
				
			||||||
@@ -883,7 +907,7 @@ def resize_volume(zkhandler, pool, name, size):
 | 
				
			|||||||
    )
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return True, 'Resized RBD volume "{}" to size "{}" in pool "{}".'.format(
 | 
					    return True, 'Resized RBD volume "{}" to size "{}" in pool "{}".'.format(
 | 
				
			||||||
        name, size, pool
 | 
					        name, format_bytes_tohuman(size_bytes), pool
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user