未验证 提交 6c359219 编写于 作者: X Xu Han 提交者: GitHub

Merge pull request #2548 from XueqiangWei/qcow2_external_data_file

Support qcow2 external data file
......@@ -1560,7 +1560,7 @@ class DevContainer(object):
scsi=None, drv_extra_params=None,
num_queues=None, bus_extra_params=None,
force_fmt=None, image_encryption=None,
image_access=None):
image_access=None, external_data_file=None):
"""
Creates related devices by variables
:note: To skip the argument use None, to disable it use False
......@@ -1600,6 +1600,7 @@ class DevContainer(object):
:param bus_extra_params: options want to add to virtio-scsi-pci bus
:param image_encryption: ImageEncryption object for image
:param image_access: The logical image access information object
:param external_data_file: external data file for qcow2 image
"""
def _get_access_tls_creds(image_access):
"""Get all tls-creds objects of the image and its backing images"""
......@@ -2000,6 +2001,20 @@ class DevContainer(object):
elif imgfmt == "luks":
devices[-1].set_param('key-secret', secret_obj.get_qid())
external_data_file_path = getattr(external_data_file,
"image_filename", None)
if external_data_file_path:
# by now we only support local files
ext_data_file_driver = "file"
# check if the data file is a block device
if ext_data_file_driver == "file":
ext_data_file_mode = os.stat(external_data_file_path).st_mode
if stat.S_ISBLK(ext_data_file_mode):
ext_data_file_driver = "host_device"
devices[-1].set_param('data-file.driver', ext_data_file_driver)
devices[-1].set_param('data-file.filename', external_data_file_path)
if 'aio' in self.get_help_text():
if aio == 'native' and snapshot == 'yes':
logging.warn('snapshot is on, fallback aio to threads.')
......@@ -2268,6 +2283,10 @@ class DevContainer(object):
sn, sn_params)
imgfmt = 'qcow2'
# external data file
ext_data_file = storage.QemuImg.external_data_file_defined_by_params(
image_params, data_root, name)
return self.images_define_by_variables(name,
image_filename,
pci_bus,
......@@ -2324,7 +2343,8 @@ class DevContainer(object):
image_params.get(
"force_drive_format"),
image_encryption,
image_access)
image_access,
ext_data_file)
def serials_define_by_variables(self, serial_id, serial_type, chardev_id,
bus_type=None, serial_name=None,
......
......@@ -412,6 +412,11 @@ class QemuImg(storage.QemuImg):
options.append("%s=%s" % (opt_key.replace("_", "-"),
str(opt_val)))
if self.data_file:
options.extend(
("data_file=%s" % self.data_file.image_filename,
"data_file_raw=%s" % params.get("image_data_file_raw", "off")))
access_secret, secret_type = self._image_access_secret
if access_secret is not None:
if secret_type == 'password':
......@@ -980,6 +985,12 @@ class QemuImg(storage.QemuImg):
logging.debug("Removing image file %s", self.image_filename)
storage.file_remove(self.params, self.image_filename)
if self.data_file:
logging.debug("Removing external data file of image %s",
self.data_file.image_filename)
storage.file_remove(self.data_file.params,
self.data_file.image_filename)
secret_files = []
if self.encryption_config.key_secret:
secret_files.append(self.encryption_config.key_secret.filename)
......
......@@ -22,6 +22,7 @@ from virttest import nbd
from virttest import iscsi
from virttest import utils_misc
from virttest import utils_numeric
from virttest import utils_params
from virttest import virt_vm
from virttest import gluster
from virttest import lvm
......@@ -667,6 +668,32 @@ class QemuImg(object):
self.image_access = ImageAccessInfo.access_info_define_by_params(
self.tag, self.params)
self.data_file = self.external_data_file_defined_by_params(
params, root_dir, tag)
@classmethod
def external_data_file_defined_by_params(cls, params, root_dir, tag):
"""Link image to an external data file."""
enable_data_file = params.get("enable_data_file", "no") == "yes"
image_format = params.get("image_format", "qcow2")
if not enable_data_file:
return
if image_format != "qcow2":
raise ValueError("The %s format does not support external "
"data file" % image_format)
image_size = params["image_size"]
base_name = os.path.basename(params["image_name"])
data_file_path = params.get("image_data_file_path",
os.path.join(root_dir, "images",
"%s.data_file"
% base_name))
data_file_params = utils_params.Params(
{"image_name": data_file_path,
"image_format": "raw",
"image_size": image_size,
"image_raw_device": "yes"})
return cls(data_file_params, root_dir, "%s_data_file" % tag)
def check_option(self, option):
"""
Check if object has the option required.
......@@ -777,6 +804,11 @@ class QemuImg(object):
for src, dst in bk_set:
self.copy_data_file(src, dst)
# backup external data file
if self.data_file:
self.data_file.backup_image(self.data_file.params, root_dir,
action, good, skip_existing)
for src, dst in backup_set:
if action == 'backup' and skip_existing and os.path.exists(dst):
logging.debug("Image backup %s already exists, skipping...",
......@@ -788,6 +820,10 @@ class QemuImg(object):
"""
Remove backup image
"""
# remove external data file backup
if self.data_file:
self.data_file.rm_backup_image()
backup_dir = utils_misc.get_path(self.root_dir,
self.params.get("backup_dir", ""))
image_name = os.path.join(backup_dir, "%s.backup" %
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册