From 1a7b29ab7200dd4a4ac1e587404495f74498fd4d Mon Sep 17 00:00:00 2001 From: Srikanth Aithal Date: Fri, 5 Jul 2019 12:54:02 +0530 Subject: [PATCH] Move disk related APIs into utils_disk This commit moves disk specific apis to utils_disk. Signed-off-by: Srikanth Aithal --- virttest/storage.py | 5 +- virttest/utils_disk.py | 390 ++++++++++++++++++++++++++++++ virttest/utils_misc.py | 405 -------------------------------- virttest/utils_test/__init__.py | 3 +- 4 files changed, 395 insertions(+), 408 deletions(-) diff --git a/virttest/storage.py b/virttest/storage.py index 5d5c2d65e4..fa98ea8d3e 100644 --- a/virttest/storage.py +++ b/virttest/storage.py @@ -17,6 +17,7 @@ from virttest import iscsi from virttest import utils_misc +from virttest import utils_disk from virttest import virt_vm from virttest import gluster from virttest import lvm @@ -259,7 +260,7 @@ def copy_nfs_image(params, image_name, root_dir): base_dir = params.get("images_base_dir", data_dir.get_data_dir()) dst = get_image_filename(params, base_dir) if(not os.path.isfile(dst) or - utils_misc.get_image_info(dst)['lcounts'].lower() == "true"): + utils_disk.get_image_info(dst)['lcounts'].lower() == "true"): source = os.path.join(root_dir, "images", image_name) if image_format not in source: source = "%s.%s" % (source, image_format) @@ -267,7 +268,7 @@ def copy_nfs_image(params, image_name, root_dir): "path - %s", source) # check for image availability in images data directory if(os.path.isfile(source) and not - utils_misc.get_image_info(source)['lcounts'].lower() == "true"): + utils_disk.get_image_info(source)['lcounts'].lower() == "true"): logging.debug("Copying guest image from %s to %s", source, dst) shutil.copy(source, dst) diff --git a/virttest/utils_disk.py b/virttest/utils_disk.py index c1848bd640..da4a7f3d00 100644 --- a/virttest/utils_disk.py +++ b/virttest/utils_disk.py @@ -21,9 +21,11 @@ from avocado.core import exceptions from avocado.utils import process from avocado.utils.service import SpecificServiceManager +from avocado.utils import path as utils_path from virttest import error_context from virttest import utils_numeric +from virttest import utils_misc from virttest.compat_52lts import decode_to_text from virttest.compat_52lts import results_stdout_52lts @@ -163,6 +165,394 @@ def umount(src, dst, fstype=None, verbose=False, session=None): return True +def get_dev_major_minor(dev): + """ + Get the major and minor numbers of the device + @return: Tuple(major, minor) numbers of the device + """ + try: + rdev = os.stat(dev).st_rdev + return (os.major(rdev), os.minor(rdev)) + except IOError as details: + raise exceptions.TestError("Fail to get major and minor numbers of the " + "device %s:\n%s" % (dev, details)) + + +def get_free_disk(session, mount): + """ + Get FreeSpace for given mount point. + + :param session: shell Object. + :param mount: mount point(eg. C:, /mnt) + + :return string: freespace M-bytes + """ + if re.match(r"[a-zA-Z]:", mount): + cmd = "wmic logicaldisk where \"DeviceID='%s'\" " % mount + cmd += "get FreeSpace" + output = session.cmd_output(cmd) + free = "%sK" % re.findall(r"\d+", output)[0] + else: + cmd = "df -h %s" % mount + output = session.cmd_output(cmd) + free = re.findall(r"\b([\d.]+[BKMGPETZ])\b", + output, re.M | re.I)[2] + free = float(utils_misc.normalize_data_size(free, order_magnitude="M")) + return int(free) + + +def get_win_disk_vol(session, condition="VolumeName='WIN_UTILS'"): + """ + Getting logicaldisk drive letter in windows guest. + + :param session: session Object. + :param condition: supported condition via cmd "wmic logicaldisk list". + + :return: volume ID. + """ + cmd = "wmic logicaldisk where (%s) get DeviceID" % condition + output = session.cmd(cmd, timeout=120) + device = re.search(r'(\w):', output, re.M) + if not device: + return "" + return device.group(1) + + +def get_winutils_vol(session, label="WIN_UTILS"): + """ + Return Volume ID of winutils CDROM ISO file should be create via command + ``mkisofs -V $label -o winutils.iso``. + + :param session: session Object. + :param label: volume label of WIN_UTILS.iso. + + :return: volume ID. + """ + return get_win_disk_vol(session, condition="VolumeName='%s'" % label) + + +def check_qemu_image_lock_support(): + """ + Check qemu-img whether supporting image lock or not + :return: The boolean of checking result + """ + cmd = "qemu-img" + binary_path = utils_path.find_command(cmd) + cmd_result = process.run(binary_path + ' -h', ignore_status=True, + shell=True, verbose=False) + return b'-U' in cmd_result.stdout + + +def get_linux_drive_path(session, did, timeout=120): + """ + Get drive path in guest by drive serial or wwn + + :param session: session object to guest. + :param did: drive serial or wwn. + :return String: drive path + """ + cmd = 'for dev_path in `ls -d /sys/block/*`; do ' + cmd += 'echo `udevadm info -q property -p $dev_path`; done' + status, output = session.cmd_status_output(cmd, timeout=timeout) + if status != 0: + logging.error("Can not get drive infomation:\n%s" % output) + return "" + p = r"DEVNAME=([^\s]+)\s.*(?:ID_SERIAL|ID_SERIAL_SHORT|ID_WWN)=%s" % did + dev = re.search(p, output, re.M) + if dev: + return dev.groups()[0] + logging.error("Can not get drive path by id '%s', " + "command output:\n%s" % (did, output)) + return "" + + +def get_image_info(image_file): + """ + Get image information and put it into a dict. Image information like this: + + :: + + ******************************* + image: /path/vm1_6.3.img + file format: raw + virtual size: 10G (10737418240 bytes) + disk size: 888M + .... + image: /path/vm2_6.3.img + file format: raw + virtual size: 1.0M (1024000 bytes) + disk size: 196M + .... + image: n3.qcow2 + file format: qcow2 + virtual size: 1.0G (1073741824 bytes) + disk size: 260K + cluster_size: 512 + Format specific information: + compat: 1.1 + lazy refcounts: false + refcount bits: 16 + corrupt: false + .... + ******************************* + + And the image info dict will be like this + + :: + + image_info_dict = {'format':'raw', + 'vsize' : '10737418240', + 'dsize' : '931135488', + 'csize' : '65536'} + """ + try: + cmd = "qemu-img info %s" % image_file + if check_qemu_image_lock_support(): + # Currently the qemu lock is introduced in qemu-kvm-rhev/ma, + # The " -U" is to avoid the qemu lock. + cmd += " -U" + image_info = decode_to_text(process.system_output(cmd, ignore_status=False)).strip() + image_info_dict = {} + vsize = None + if image_info: + for line in image_info.splitlines(): + if line.find("file format") != -1: + image_info_dict['format'] = line.split(':')[-1].strip() + elif line.find("virtual size") != -1 and vsize is None: + # Use the value in (xxxxxx bytes) since it's the more + # realistic value. For a "1000k" disk, qemu-img will + # show 1.0M and 1024000 bytes. The 1.0M will translate + # into 1048576 bytes which isn't necessarily correct + vsize = line.split("(")[-1].strip().split(" ")[0] + image_info_dict['vsize'] = int(vsize) + elif line.find("disk size") != -1: + dsize = line.split(':')[-1].strip() + image_info_dict['dsize'] = int(float( + utils_misc.normalize_data_size(dsize, order_magnitude="B", factor=1024))) + elif line.find("cluster_size") != -1: + csize = line.split(':')[-1].strip() + image_info_dict['csize'] = int(csize) + elif line.find("compat") != -1: + compat = line.split(':')[-1].strip() + image_info_dict['compat'] = compat + elif line.find("lazy refcounts") != -1: + lazy_refcounts = line.split(':')[-1].strip() + image_info_dict['lcounts'] = lazy_refcounts + return image_info_dict + except (KeyError, IndexError, process.CmdError) as detail: + raise exceptions.TestError("Fail to get information of %s:\n%s" % + (image_file, detail)) + + +def get_windows_drive_letters(session): + """ + Get drive letters has been assigned + + :param session: session object to guest + :return list: letters has been assigned + """ + list_letters_cmd = "fsutil fsinfo drives" + drive_letters = re.findall( + r'(\w+):\\', session.cmd_output(list_letters_cmd), re.M) + + return drive_letters + + +def list_linux_guest_disks(session, partition=False): + """ + List all disks OR disks with no partition in linux guest. + + :param session: session object to guest + :param partition: if true, list all disks; otherwise, + list only disks with no partition. + :return: the disks set. + """ + cmd = "ls /dev/[vhs]d*" + if not partition: + cmd = "%s | grep -v [0-9]$" % cmd + status, output = session.cmd_status_output(cmd) + if status != 0: + raise exceptions.TestFail("Get disks failed with output %s" % output) + return set(output.split()) + + +def get_all_disks_did(session, partition=False): + """ + Get all disks did lists in a linux guest, each disk list + include disk kname, serial and wwn. + + :param session: session object to guest. + :param partition: if true, get all disks did lists; otherwise, + get the ones with no partition. + :return: a dict with all disks did lists each include disk + kname, serial and wwn. + """ + disks = list_linux_guest_disks(session, partition) + logging.debug("Disks detail: %s" % disks) + all_disks_did = {} + for line in disks: + kname = line.split('/')[2] + get_disk_info_cmd = "udevadm info -q property -p /sys/block/%s" % kname + output = session.cmd_output_safe(get_disk_info_cmd) + re_str = r"(?<=DEVNAME=/dev/)(.*)|(?<=ID_SERIAL=)(.*)|" + re_str += "(?<=ID_SERIAL_SHORT=)(.*)|(?<=ID_WWN=)(.*)" + did_list_group = re.finditer(re_str, output, re.M) + did_list = [match.group() for match in did_list_group if match] + all_disks_did[kname] = did_list + + return all_disks_did + + +def format_windows_disk(session, did, mountpoint=None, size=None, + fstype="ntfs", force=False): + """ + Create a partition on disk in windows guest and format it. + + :param session: session object to guest. + :param did: disk index which show in 'diskpart list disk'. + :param mountpoint: mount point for the disk. + :param size: partition size. + :param fstype: filesystem type for the disk. + :return Boolean: disk usable or not. + """ + list_disk_cmd = "echo list disk > disk && " + list_disk_cmd += "echo exit >> disk && diskpart /s disk" + disks = session.cmd_output(list_disk_cmd, timeout=120) + + if size: + size = int(float(utils_misc.normalize_data_size(size, order_magnitude="M"))) + + for disk in disks.splitlines(): + if re.search(r"DISK %s" % did, disk, re.I | re.M): + cmd_header = 'echo list disk > disk &&' + cmd_header += 'echo select disk %s >> disk &&' % did + cmd_footer = '&& echo exit>> disk && diskpart /s disk' + cmd_footer += '&& del /f disk' + detail_cmd = 'echo detail disk >> disk' + detail_cmd = ' '.join([cmd_header, detail_cmd, cmd_footer]) + logging.debug("Detail for 'Disk%s'" % did) + details = session.cmd_output(detail_cmd) + + pattern = "DISK %s.*Offline" % did + if re.search(pattern, details, re.I | re.M): + online_cmd = 'echo online disk>> disk' + online_cmd = ' '.join([cmd_header, online_cmd, cmd_footer]) + logging.info("Online 'Disk%s'" % did) + session.cmd(online_cmd) + + if re.search("Read.*Yes", details, re.I | re.M): + set_rw_cmd = 'echo attributes disk clear readonly>> disk' + set_rw_cmd = ' '.join([cmd_header, set_rw_cmd, cmd_footer]) + logging.info("Clear readonly bit on 'Disk%s'" % did) + session.cmd(set_rw_cmd) + + if re.search(r"Volume.*%s" % fstype, details, re.I | re.M) and not force: + logging.info("Disk%s has been formated, cancel format" % did) + continue + + if not size: + mkpart_cmd = 'echo create partition primary >> disk' + else: + mkpart_cmd = 'echo create partition primary size=%s ' + mkpart_cmd += '>> disk' + mkpart_cmd = mkpart_cmd % size + mkpart_cmd = ' '.join([cmd_header, mkpart_cmd, cmd_footer]) + logging.info("Create partition on 'Disk%s'" % did) + session.cmd(mkpart_cmd) + logging.info("Format the 'Disk%s' to %s" % (did, fstype)) + format_cmd = 'echo list partition >> disk && ' + format_cmd += 'echo select partition 1 >> disk && ' + if not mountpoint: + format_cmd += 'echo assign >> disk && ' + else: + format_cmd += 'echo assign letter=%s >> disk && ' % mountpoint + format_cmd += 'echo format fs=%s quick >> disk ' % fstype + format_cmd = ' '.join([cmd_header, format_cmd, cmd_footer]) + session.cmd(format_cmd, timeout=300) + + return True + + return False + + +def format_linux_disk(session, did, all_disks_did, partition=False, + mountpoint=None, size=None, fstype="ext3"): + """ + Create a partition on disk in linux guest and format and mount it. + + :param session: session object to guest. + :param did: disk kname, serial or wwn. + :param all_disks_did: all disks did lists each include + disk kname, serial and wwn. + :param partition: if true, can format all disks; otherwise, + only format the ones with no partition originally. + :param mountpoint: mount point for the disk. + :param size: partition size. + :param fstype: filesystem type for the disk. + :return Boolean: disk usable or not. + """ + disks = list_linux_guest_disks(session, partition) + logging.debug("Disks detail: %s" % disks) + for line in disks: + kname = line.split('/')[2] + did_list = all_disks_did[kname] + if did not in did_list: + # Continue to search target disk + continue + if not size: + size_output = session.cmd_output_safe("lsblk -oKNAME,SIZE|grep %s" + % kname) + size = size_output.splitlines()[0].split()[1] + all_disks_before = list_linux_guest_disks(session, True) + devname = line + logging.info("Create partition on disk '%s'" % devname) + mkpart_cmd = "parted -s %s mklabel gpt mkpart " + mkpart_cmd += "primary 0 %s" + mkpart_cmd = mkpart_cmd % (devname, size) + session.cmd_output_safe(mkpart_cmd) + session.cmd_output_safe("partprobe %s" % devname) + all_disks_after = list_linux_guest_disks(session, True) + partname = (all_disks_after - all_disks_before).pop() + logging.info("Format partition to '%s'" % fstype) + format_cmd = "yes|mkfs -t %s %s" % (fstype, partname) + session.cmd_output_safe(format_cmd) + if not mountpoint: + session.cmd_output_safe("mkdir /mnt/%s" % kname) + mountpoint = os.path.join("/mnt", kname) + logging.info("Mount the disk to '%s'" % mountpoint) + mount_cmd = "mount -t %s %s %s" % (fstype, partname, mountpoint) + session.cmd_output_safe(mount_cmd) + return True + + return False + + +def format_guest_disk(session, did, all_disks_did, ostype, partition=False, + mountpoint=None, size=None, fstype=None): + """ + Create a partition on disk in guest and format and mount it. + + :param session: session object to guest. + :param did: disk ID in guest. + :param all_disks_did: a dict contains all disks did lists each + include disk kname, serial and wwn for linux guest. + :param ostype: guest os type 'windows' or 'linux'. + :param partition: if true, can format all disks; otherwise, + only format the ones with no partition originally. + :param mountpoint: mount point for the disk. + :param size: partition size. + :param fstype: filesystem type for the disk; when it's the default None, + it will use the default one for corresponding ostype guest + :return Boolean: disk usable or not. + """ + default_fstype = "ntfs" if (ostype == "windows") else "ext3" + fstype = fstype or default_fstype + if ostype == "windows": + return format_windows_disk(session, did, mountpoint, size, fstype) + return format_linux_disk(session, did, all_disks_did, partition, + mountpoint, size, fstype) + + @error_context.context_aware def cleanup(folder): """ diff --git a/virttest/utils_misc.py b/virttest/utils_misc.py index 9940a03c72..a73c93518e 100644 --- a/virttest/utils_misc.py +++ b/virttest/utils_misc.py @@ -1838,19 +1838,6 @@ def show(self): logging.info(" %s: %s" % (i, self.dict[i])) -def get_dev_major_minor(dev): - """ - Get the major and minor numbers of the device - @return: Tuple(major, minor) numbers of the device - """ - try: - rdev = os.stat(dev).st_rdev - return (os.major(rdev), os.minor(rdev)) - except IOError as details: - raise exceptions.TestError("Fail to get major and minor numbers of the " - "device %s:\n%s" % (dev, details)) - - class Flag(str): """ @@ -2624,29 +2611,6 @@ def __get_unit_index(M): return ("%.20f" % data_size).rstrip('0') -def get_free_disk(session, mount): - """ - Get FreeSpace for given mount point. - - :param session: shell Object. - :param mount: mount point(eg. C:, /mnt) - - :return string: freespace M-bytes - """ - if re.match(r"[a-zA-Z]:", mount): - cmd = "wmic logicaldisk where \"DeviceID='%s'\" " % mount - cmd += "get FreeSpace" - output = session.cmd_output(cmd) - free = "%sK" % re.findall(r"\d+", output)[0] - else: - cmd = "df -h %s" % mount - output = session.cmd_output(cmd) - free = re.findall(r"\b([\d.]+[BKMGPETZ])\b", - output, re.M | re.I)[2] - free = float(normalize_data_size(free, order_magnitude="M")) - return int(free) - - def get_free_mem(session, os_type): """ Get Free memory for given OS. @@ -2731,50 +2695,6 @@ def selinux_enforcing(): return utils_selinux.is_enforcing() -def get_win_disk_vol(session, condition="VolumeName='WIN_UTILS'"): - """ - Getting logicaldisk drive letter in windows guest. - - :param session: session Object. - :param condition: supported condition via cmd "wmic logicaldisk list". - - :return: volume ID. - """ - cmd = "wmic logicaldisk where (%s) get DeviceID" % condition - output = session.cmd(cmd, timeout=120) - device = re.search(r'(\w):', output, re.M) - if not device: - return "" - return device.group(1) - - -def get_winutils_vol(session, label="WIN_UTILS"): - """ - Return Volume ID of winutils CDROM ISO file should be create via command - ``mkisofs -V $label -o winutils.iso``. - - :param session: session Object. - :param label: volume label of WIN_UTILS.iso. - - :return: volume ID. - """ - return wait_for(lambda: get_win_disk_vol(session, - condition="VolumeName='%s'" % label), 240) - - -def set_winutils_letter(session, cmd, label="WIN_UTILS"): - """ - Replace label in command to real winutils CDROM drive letter. - - :param session: session Objest - :param cmd: cmd path in winutils.iso - :param label: volume label of WIN_UTILS.iso - """ - if label in cmd: - return cmd.replace(label, get_winutils_vol(session)) - return cmd - - def get_uptime(session=None): """ Get the uptime of system in secs @@ -2794,240 +2714,6 @@ def get_uptime(session=None): return float(uptime.split()[0]) -def list_linux_guest_disks(session, partition=False): - """ - List all disks OR disks with no partition in linux guest. - - :param session: session object to guest - :param partition: if true, list all disks; otherwise, - list only disks with no partition. - :return: the disks set. - """ - cmd = "ls /dev/[vhs]d*" - if not partition: - cmd = "%s | grep -v [0-9]$" % cmd - status, output = session.cmd_status_output(cmd) - if status != 0: - raise exceptions.TestFail("Get disks failed with output %s" % output) - return set(output.split()) - - -def get_all_disks_did(session, partition=False): - """ - Get all disks did lists in a linux guest, each disk list - include disk kname, serial and wwn. - - :param session: session object to guest. - :param partition: if true, get all disks did lists; otherwise, - get the ones with no partition. - :return: a dict with all disks did lists each include disk - kname, serial and wwn. - """ - disks = list_linux_guest_disks(session, partition) - logging.debug("Disks detail: %s" % disks) - all_disks_did = {} - for line in disks: - kname = line.split('/')[2] - get_disk_info_cmd = "udevadm info -q property -p /sys/block/%s" % kname - output = session.cmd_output_safe(get_disk_info_cmd) - re_str = r"(?<=DEVNAME=/dev/)(.*)|(?<=ID_SERIAL=)(.*)|" - re_str += "(?<=ID_SERIAL_SHORT=)(.*)|(?<=ID_WWN=)(.*)" - did_list_group = re.finditer(re_str, output, re.M) - did_list = [match.group() for match in did_list_group if match] - all_disks_did[kname] = did_list - - return all_disks_did - - -def format_windows_disk(session, did, mountpoint=None, size=None, - fstype="ntfs", force=False): - """ - Create a partition on disk in windows guest and format it. - - :param session: session object to guest. - :param did: disk index which show in 'diskpart list disk'. - :param mountpoint: mount point for the disk. - :param size: partition size. - :param fstype: filesystem type for the disk. - :return Boolean: disk usable or not. - """ - list_disk_cmd = "echo list disk > disk && " - list_disk_cmd += "echo exit >> disk && diskpart /s disk" - disks = session.cmd_output(list_disk_cmd, timeout=120) - - if size: - size = int(float(normalize_data_size(size, order_magnitude="M"))) - - for disk in disks.splitlines(): - if re.search(r"DISK %s" % did, disk, re.I | re.M): - cmd_header = 'echo list disk > disk &&' - cmd_header += 'echo select disk %s >> disk &&' % did - cmd_footer = '&& echo exit>> disk && diskpart /s disk' - cmd_footer += '&& del /f disk' - detail_cmd = 'echo detail disk >> disk' - detail_cmd = ' '.join([cmd_header, detail_cmd, cmd_footer]) - logging.debug("Detail for 'Disk%s'" % did) - details = session.cmd_output(detail_cmd) - - pattern = "DISK %s.*Offline" % did - if re.search(pattern, details, re.I | re.M): - online_cmd = 'echo online disk>> disk' - online_cmd = ' '.join([cmd_header, online_cmd, cmd_footer]) - logging.info("Online 'Disk%s'" % did) - session.cmd(online_cmd) - - if re.search("Read.*Yes", details, re.I | re.M): - set_rw_cmd = 'echo attributes disk clear readonly>> disk' - set_rw_cmd = ' '.join([cmd_header, set_rw_cmd, cmd_footer]) - logging.info("Clear readonly bit on 'Disk%s'" % did) - session.cmd(set_rw_cmd) - - if re.search(r"Volume.*%s" % fstype, details, re.I | re.M) and not force: - logging.info("Disk%s has been formated, cancel format" % did) - continue - - if not size: - mkpart_cmd = 'echo create partition primary >> disk' - else: - mkpart_cmd = 'echo create partition primary size=%s ' - mkpart_cmd += '>> disk' - mkpart_cmd = mkpart_cmd % size - list_cmd = ' && echo list partition >> disk ' - cmds = ' '.join([cmd_header, mkpart_cmd, list_cmd, cmd_footer]) - logging.info("Create partition on 'Disk%s'" % did) - partition_index = re.search( - r'\*\s+Partition\s(\d+)\s+', session.cmd(cmds), re.M).group(1) - logging.info("Format the 'Disk%s' to %s" % (did, fstype)) - format_cmd = 'echo list partition >> disk && ' - format_cmd += 'echo select partition %s >> disk && ' % partition_index - if not mountpoint: - format_cmd += 'echo assign >> disk && ' - else: - format_cmd += 'echo assign letter=%s >> disk && ' % mountpoint - format_cmd += 'echo format fs=%s quick >> disk ' % fstype - format_cmd = ' '.join([cmd_header, format_cmd, cmd_footer]) - session.cmd(format_cmd, timeout=300) - - return True - - return False - - -def format_linux_disk(session, did, all_disks_did, partition=False, - mountpoint=None, size=None, fstype="ext3"): - """ - Create a partition on disk in linux guest and format and mount it. - - :param session: session object to guest. - :param did: disk kname, serial or wwn. - :param all_disks_did: all disks did lists each include - disk kname, serial and wwn. - :param partition: if true, can format all disks; otherwise, - only format the ones with no partition originally. - :param mountpoint: mount point for the disk. - :param size: partition size. - :param fstype: filesystem type for the disk. - :return Boolean: disk usable or not. - """ - disks = list_linux_guest_disks(session, partition) - logging.debug("Disks detail: %s" % disks) - for line in disks: - kname = line.split('/')[2] - did_list = all_disks_did[kname] - if did not in did_list: - # Continue to search target disk - continue - if not size: - size_output = session.cmd_output_safe("lsblk -oKNAME,SIZE|grep %s" - % kname) - size = size_output.splitlines()[0].split()[1] - all_disks_before = list_linux_guest_disks(session, True) - devname = line - logging.info("Create partition on disk '%s'" % devname) - mkpart_cmd = "parted -s %s mklabel gpt mkpart " - mkpart_cmd += "primary 0 %s" - mkpart_cmd = mkpart_cmd % (devname, size) - session.cmd_output_safe(mkpart_cmd) - session.cmd_output_safe("partprobe %s" % devname) - all_disks_after = list_linux_guest_disks(session, True) - partname = (all_disks_after - all_disks_before).pop() - logging.info("Format partition to '%s'" % fstype) - format_cmd = "yes|mkfs -t %s %s" % (fstype, partname) - session.cmd_output_safe(format_cmd) - if not mountpoint: - session.cmd_output_safe("mkdir /mnt/%s" % kname) - mountpoint = os.path.join("/mnt", kname) - logging.info("Mount the disk to '%s'" % mountpoint) - mount_cmd = "mount -t %s %s %s" % (fstype, partname, mountpoint) - session.cmd_output_safe(mount_cmd) - return True - - return False - - -def format_guest_disk(session, did, all_disks_did, ostype, partition=False, - mountpoint=None, size=None, fstype=None): - """ - Create a partition on disk in guest and format and mount it. - - :param session: session object to guest. - :param did: disk ID in guest. - :param all_disks_did: a dict contains all disks did lists each - include disk kname, serial and wwn for linux guest. - :param ostype: guest os type 'windows' or 'linux'. - :param partition: if true, can format all disks; otherwise, - only format the ones with no partition originally. - :param mountpoint: mount point for the disk. - :param size: partition size. - :param fstype: filesystem type for the disk; when it's the default None, - it will use the default one for corresponding ostype guest - :return Boolean: disk usable or not. - """ - default_fstype = "ntfs" if (ostype == "windows") else "ext3" - fstype = fstype or default_fstype - if ostype == "windows": - return format_windows_disk(session, did, mountpoint, size, fstype) - return format_linux_disk(session, did, all_disks_did, partition, - mountpoint, size, fstype) - - -def get_linux_drive_path(session, did, timeout=120): - """ - Get drive path in guest by drive serial or wwn - - :param session: session object to guest. - :param did: drive serial or wwn. - :return String: drive path - """ - cmd = 'for dev_path in `ls -d /sys/block/*`; do ' - cmd += 'echo `udevadm info -q property -p $dev_path`; done' - status, output = session.cmd_status_output(cmd, timeout=timeout) - if status != 0: - logging.error("Can not get drive infomation:\n%s" % output) - return "" - p = r"DEVNAME=([^\s]+)\s.*(?:ID_SERIAL|ID_SERIAL_SHORT|ID_WWN)=%s" % did - dev = re.search(p, output, re.M) - if dev: - return dev.groups()[0] - logging.error("Can not get drive path by id '%s', " - "command output:\n%s" % (did, output)) - return "" - - -def get_windows_drive_letters(session): - """ - Get drive letters has been assigned - - :param session: session object to guest - :return list: letters has been assigned - """ - list_letters_cmd = "fsutil fsinfo drives" - drive_letters = re.findall( - r'(\w+):\\', session.cmd_output(list_letters_cmd), re.M) - - return drive_letters - - def valued_option_dict(options, split_pattern, start_count=0, dict_split=None): """ Divide the valued options into key and value @@ -3087,97 +2773,6 @@ def get_image_snapshot(image_file): (image_file, detail)) -def check_qemu_image_lock_support(): - """ - Check qemu-img whether supporting image lock or not - :return: The boolean of checking result - """ - cmd = "qemu-img" - binary_path = utils_path.find_command(cmd) - cmd_result = process.run(binary_path + ' -h', ignore_status=True, - shell=True, verbose=False) - return b'-U' in cmd_result.stdout - - -def get_image_info(image_file): - """ - Get image information and put it into a dict. Image information like this: - - :: - - ******************************* - image: /path/vm1_6.3.img - file format: raw - virtual size: 10G (10737418240 bytes) - disk size: 888M - .... - image: /path/vm2_6.3.img - file format: raw - virtual size: 1.0M (1024000 bytes) - disk size: 196M - .... - image: n3.qcow2 - file format: qcow2 - virtual size: 1.0G (1073741824 bytes) - disk size: 260K - cluster_size: 512 - Format specific information: - compat: 1.1 - lazy refcounts: false - refcount bits: 16 - corrupt: false - .... - ******************************* - - And the image info dict will be like this - - :: - - image_info_dict = {'format':'raw', - 'vsize' : '10737418240', - 'dsize' : '931135488', - 'csize' : '65536'} - """ - try: - cmd = "qemu-img info %s" % image_file - if check_qemu_image_lock_support(): - # Currently the qemu lock is introduced in qemu-kvm-rhev/ma, - # The " -U" is to avoid the qemu lock. - cmd += " -U" - image_info = decode_to_text(process.system_output(cmd, ignore_status=False)).strip() - image_info_dict = {} - vsize = None - if image_info: - for line in image_info.splitlines(): - if line.find("file format") != -1: - image_info_dict['format'] = line.split(':')[-1].strip() - elif line.find("virtual size") != -1 and vsize is None: - # Use the value in (xxxxxx bytes) since it's the more - # realistic value. For a "1000k" disk, qemu-img will - # show 1.0M and 1024000 bytes. The 1.0M will translate - # into 1048576 bytes which isn't necessarily correct - vsize = line.split("(")[-1].strip().split(" ")[0] - image_info_dict['vsize'] = int(vsize) - elif line.find("disk size") != -1: - dsize = line.split(':')[-1].strip() - image_info_dict['dsize'] = int(float( - normalize_data_size(dsize, order_magnitude="B", - factor=1024))) - elif line.find("cluster_size") != -1: - csize = line.split(':')[-1].strip() - image_info_dict['csize'] = int(csize) - elif line.find("compat") != -1: - compat = line.split(':')[-1].strip() - image_info_dict['compat'] = compat - elif line.find("lazy refcounts") != -1: - lazy_refcounts = line.split(':')[-1].strip() - image_info_dict['lcounts'] = lazy_refcounts - return image_info_dict - except (KeyError, IndexError, process.CmdError) as detail: - raise exceptions.TestError("Fail to get information of %s:\n%s" % - (image_file, detail)) - - def is_qemu_capability_supported(capability): """ Check if the specified qemu capability is supported diff --git a/virttest/utils_test/__init__.py b/virttest/utils_test/__init__.py index ef03a8d837..cd358376dc 100755 --- a/virttest/utils_test/__init__.py +++ b/virttest/utils_test/__init__.py @@ -52,6 +52,7 @@ from virttest import scan_autotest_results from virttest import storage from virttest import utils_misc +from virttest import utils_disk from virttest import utils_net from virttest import virt_vm from virttest import utils_package @@ -1952,7 +1953,7 @@ def is_alive(self): def get_image_info(image_file): - return utils_misc.get_image_info(image_file) + return utils_disk.get_image_info(image_file) def ntpdate(service_ip, session=None):