import logging
import os
import aexpect
from avocado.utils import process
from virttest import libvirt_vm
from virttest import virsh
from virttest import remote
from virttest import virt_vm
from virttest import utils_test
from virttest.libvirt_xml import vm_xml
import virttest.utils_libguestfs as lgf
def run(test, params, env):
"""
Test the command virt-sysprep
"""
def prepare_action(vm):
"""
Do some actions before testing: Touch new file
in "/var/log" and "/var/mail/" etc.
"""
global o_ssh
if vm.is_dead():
vm.start()
try:
session = vm.wait_for_login()
session.cmd("touch /var/log/tmp.log")
session.cmd("touch /var/mail/tmp")
tmp_hostname = "%stmp" % sysprep_hostname
session.cmd("hostname %s" % tmp_hostname)
o_ssh = session.cmd_output("cd /etc/ssh && cat ssh_host_key.pub")
log_out = session.cmd_output("cd /var/log/ && ls | grep tmp.log")
mail_out = session.cmd_output("cd /var/mail && ls | grep tmp")
hname_out = session.cmd_output("hostname")
if (not log_out.strip() or not mail_out.strip() or
hname_out.strip() != tmp_hostname):
logging.debug("log:%s\nmail:%s\nhostname:%s"
% (log_out, mail_out, hname_out))
test.fail("Prepare action failed!")
session.close()
vm.destroy()
except (remote.LoginError, virt_vm.VMError,
aexpect.ShellError) as detail:
if "session" in dir():
session.close()
test.fail("Prepare action failed: %s" % detail)
def sysprep_action(vm_name, image_name, sysprep_target, hostname):
"""
Execute "virt-sysprep" command
"""
options = ""
if hostname:
options = "--hostname %s " % hostname
if sysprep_target == "guest":
disk_or_domain = vm_name
else:
disk_or_domain = image_name
lgf.virt_sysprep_cmd(disk_or_domain, options, ignore_status=False)
def modify_source(vm_name, target, dst_image):
"""
Modify domain's configuration to change its disk source
"""
try:
virsh.detach_disk(vm_name, target, extra="--config",
ignore_status=False)
dst_image_format = utils_test.get_image_info(dst_image)['format']
options = "--config --subdriver %s" % dst_image_format
virsh.attach_disk(vm_name, dst_image, target, extra=options,
ignore_status=False)
except (remote.LoginError, virt_vm.VMError,
aexpect.ShellError, process.CmdError) as detail:
test.fail("Modify guest source failed: %s" % detail)
def modify_network(vm_name, first_nic):
"""
Modify domain's interface to make sure domain can be login.
"""
iface_type = first_nic.type_name
iface_source = first_nic.source.get('bridge')
mac_address = first_nic.mac_address
try:
virsh.detach_interface(vm_name, "--type=%s --config" % iface_type,
ignore_status=False)
virsh.attach_interface(vm_name,
"--type=%s --source %s --mac %s --config"
% (iface_type, iface_source, mac_address),
ignore_status=False)
except (remote.LoginError, virt_vm.VMError,
aexpect.ShellError) as detail:
test.fail("Modify network failed:%s" % detail)
def result_confirm(vm):
"""
Confirm tmp file has been cleaned up, hostname has been changed, etc.
"""
global o_ssh
try:
if vm.is_dead():
vm.start()
session = vm.wait_for_login(nic_index=0)
log_out = session.cmd_output("cd /var/log/ && ls | grep tmp.log")
mail_out = session.cmd_output("cd /var/mail && ls | grep tmp")
hname_out = session.cmd_output("hostname")
ssh_out = session.cmd_output("cd /etc/ssh && cat ssh_host_key.pub")
session.close()
vm.destroy()
if (log_out.strip() or mail_out.strip() or
hname_out.strip() != sysprep_hostname or
ssh_out.strip() == o_ssh.strip()):
logging.debug("log: %s\nmail:%s\nhostname:%s\nsshkey:%s" %
(log_out, mail_out, hname_out, ssh_out))
return False
return True
except (remote.LoginError, virt_vm.VMError,
aexpect.ShellError) as detail:
logging.error(str(detail))
if "session" in dir():
session.close()
return False
def clean_clone_vm():
"""
Clean up cloned domain.
"""
try:
if virsh.domain_exists(vm_clone_name):
if virsh.is_alive(vm_clone_name):
virsh.destroy(vm_clone_name, ignore_status=False)
virsh.undefine(vm_clone_name, ignore_status=False)
if os.path.exists(clone_image):
os.remove(clone_image)
except process.CmdError as detail:
test.fail("Clean clone guest failed!:%s" % detail)
sysprep_type = params.get("sysprep_type", 'clone')
sysprep_target = params.get("sysprep_target", 'guest')
sysprep_hostname = params.get("sysprep_hostname", 'sysprep_test')
vm_name = params.get("main_vm", "avocado-vt-vm1")
file_system = params.get("sysprep_file_system", "ext3")
vm = env.get_vm(vm_name)
disks = vm.get_disk_devices()
if len(disks):
disk = list(disks.values())[0]
image = disk['source']
target = list(disks.keys())[0]
image_info_dict = utils_test.get_image_info(image)
if sysprep_type == "sparsify" and image_info_dict['format'] != 'qcow2':
test.cancel("This test case needs qcow2 format image.")
else:
test.error("Can not get disk of %s" % vm_name)
vt = utils_test.libguestfs.VirtTools(vm, params)
fs_type = vt.get_primary_disk_fs_type()
if fs_type != file_system:
test.cancel("This test case gets wrong disk file system."
"get: %s, expected: %s" % (fs_type,
file_system))
vm_clone_name = "%s_clone" % vm_name
clone_image = "%s_clone.img" % image
vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name)
first_nic = vmxml.get_devices(device_type="interface")[0]
clean_clone_vm()
dargs = {}
dargs['files'] = [clone_image]
dargs['ignore_status'] = True
clone_result = lgf.virt_clone_cmd(vm_name, newname=vm_clone_name, **dargs)
if clone_result.exit_status:
test.fail("virt-clone failed:%s"
% clone_result.stderr.strip())
try:
modify_network(vm_clone_name, first_nic)
new_vm = libvirt_vm.VM(vm_clone_name, params, vm.root_dir,
vm.address_cache)
prepare_action(new_vm)
test_image = clone_image
if sysprep_type == "resize":
img_size = image_info_dict['vsize'] / 1024 / 1024 / 1024
resize_image = "%s_resize.img" % clone_image
cmd = "qemu-img create -f raw %s %dG" % (resize_image, (img_size + 1))
process.run(cmd, shell=True)
lgf.virt_resize_cmd(clone_image, resize_image, timeout=600,
debug=True)
modify_source(vm_clone_name, target, resize_image)
test_image = resize_image
elif sysprep_type == "sparsify":
sparsify_image = "%s_sparsify.img" % clone_image
lgf.virt_sparsify_cmd(clone_image, sparsify_image, compress=True,
format=image_info_dict['format'],
timeout=600)
modify_source(vm_clone_name, target, sparsify_image)
test_image = sparsify_image
sysprep_action(vm_clone_name, test_image, sysprep_target,
sysprep_hostname)
if not result_confirm(new_vm):
test.fail("Test Falied!")
finally:
clean_clone_vm()
if "resize_image" in dir():
if os.path.exists(resize_image):
os.remove(resize_image)
if "sparsify_image" in dir():
if os.path.exists(sparsify_image):
os.remove(sparsify_image)