new file mode 100644
@@ -0,0 +1,190 @@
+import logging, re, time, os
+from autotest_lib.client.common_lib import error
+from autotest_lib.client.bin import utils
+from autotest_lib.client.virt import virt_utils, aexpect, kvm_monitor
+
+
+@error.context_aware
+def run_cdrom(test, params, env):
+ """
+ KVM cdrom test:
+
+ 1) Boot up a VM with one iso.
+ 2) Check if VM identifies correctly the iso file.
+ 3) Eject cdrom and change with another iso several times.
+ 4) Try to format cdrom and check the return string.
+ 5) Mount cdrom device.
+ 6) Copy file from cdrom and compare files using diff.
+ 7) Umount and mount several times.
+
+ @param test: kvm test object
+ @param params: Dictionary with the test parameters
+ @param env: Dictionary with test environment.
+ """
+ def master_cdroms(params):
+ error.context("creating test cdrom")
+ os.chdir(test.tmpdir)
+ cdrom_cd1 = params.get("cdrom_cd1")
+ cdrom_dir = os.path.dirname(cdrom_cd1)
+ utils.run("dd if=/dev/urandom of=orig bs=10M count=1")
+ utils.run("dd if=/dev/urandom of=new bs=10M count=1")
+ utils.run("mkisofs -o %s/orig.iso orig" % cdrom_dir)
+ utils.run("mkisofs -o %s/new.iso new" % cdrom_dir)
+ return "%s/new.iso" % cdrom_dir
+
+
+ def cleanup_cdroms(cdrom_dir):
+ error.context("cleaning up temp cdrom images")
+ os.remove("%s/orig.iso" % cdrom_dir)
+ os.remove("%s/new.iso" % cdrom_dir)
+
+
+ def get_cdrom_info():
+ blocks = vm.monitor.info("block")
+ (device, file) = (None, None)
+ if isinstance(blocks, str):
+ try:
+ device = re.findall("(ide\d+-cd\d+): .*", blocks)[0]
+ except IndexError:
+ device = None
+ try:
+ file = re.findall("ide\d+-cd\d+: .*file=(\S*) ", blocks)[0]
+ except IndexError:
+ file = None
+ else:
+ for block in blocks:
+ d = block['device']
+ try:
+ device = re.findall("(ide\d+-cd\d+)", d)[0]
+ except IndexError:
+ device = None
+ continue
+ try:
+ file = block['inserted']['file']
+ except KeyError:
+ file = None
+ break
+ logging.debug("Device name: %s, ISO: %s" % (device, file))
+ return (device, file)
+
+
+ def check_cdrom_locked(cdrom):
+ blocks = vm.monitor.info("block")
+ if isinstance(blocks, str):
+ lock_str = "locked=1"
+ for block in blocks.splitlines():
+ if cdrom in block and lock_str in block:
+ return True
+ else:
+ for block in blocks:
+ if ('inserted' in block.keys() and
+ block['inserted']['file'] == cdrom):
+ return block['locked']
+ return False
+
+
+ def eject_cdrom(device, monitor):
+ if isinstance(monitor, kvm_monitor.HumanMonitor):
+ monitor.cmd("eject %s" % device)
+ elif isinstance(monitor, kvm_monitor.QMPMonitor):
+ monitor.cmd("eject", args={'device': device})
+
+
+ def change_cdrom(device, target, monitor):
+ if isinstance(monitor, kvm_monitor.HumanMonitor):
+ monitor.cmd("change %s %s" % (device, target))
+ elif isinstance(monitor, kvm_monitor.QMPMonitor):
+ monitor.cmd("change", args={'device': device, 'target': target})
+
+
+ cdrom_new = master_cdroms(params)
+ cdrom_dir = os.path.dirname(cdrom_new)
+ vm = env.get_vm(params["main_vm"])
+ vm.create()
+
+ session = vm.wait_for_login(timeout=int(params.get("login_timeout", 360)))
+ cdrom_orig = params.get("cdrom_cd1")
+ cdrom = cdrom_orig
+ output = session.get_command_output("ls /dev/cdrom*")
+ cdrom_dev_list = re.findall("/dev/cdrom-\w+|/dev/cdrom\d*", output)
+ logging.debug("cdrom_dev_list: %s" % cdrom_dev_list)
+
+ cdrom_dev = ""
+ test_cmd = "dd if=%s of=/dev/null bs=1 count=1"
+ for d in cdrom_dev_list:
+ try:
+ output = session.cmd(test_cmd % d)
+ cdrom_dev = d
+ break
+ except aexpect.ShellError:
+ logging.error(output)
+ if not cdrom_dev:
+ raise error.TestFail("Could not find a valid cdrom device")
+
+ error.context("Detecting the existence of a cdrom")
+ (device, file) = get_cdrom_info()
+ if file != cdrom:
+ raise error.TestError("Could not find a valid cdrom device")
+
+ session.get_command_output("umount %s" % cdrom_dev)
+ if not virt_utils.wait_for(lambda: not check_cdrom_locked(file), 300):
+ raise error.TestError("Device %s could not be unlocked" % device)
+
+ max_times = int(params.get("max_times", 100))
+ error.context("Eject the cdrom for %s times" % max_times)
+ for i in range(1, max_times):
+ eject_cdrom(device, vm.monitor)
+ (device, file) = get_cdrom_info()
+ if file is not None:
+ raise error.TestFail("Device %s was not ejected" % cdrom)
+
+ cdrom = cdrom_new
+ # On even attempts, try to change the cdrom
+ if i % 2 == 0:
+ cdrom = cdrom_orig
+ change_cdrom(device, cdrom, vm.monitor)
+ time.sleep(10)
+ (device, file) = get_cdrom_info()
+ if file != cdrom:
+ raise error.TestError("It wasn't possible to change cdrom %s" %
+ cdrom)
+
+ error.context("Check whether the cdrom is read-only")
+ try:
+ output = session.cmd("echo y | mkfs %s" % cdrom_dev)
+ raise error.TestFail("Attempt to format cdrom %s succeeded" % cdrom_dev)
+ except aexpect.ShellError:
+ pass
+
+ error.context("Mounting the cdrom under /mnt")
+ session.cmd("mount %s %s" % (cdrom_dev, "/mnt"), timeout=30)
+
+ filename = "new"
+
+ error.context("File copying test")
+ session.cmd("rm -f /tmp/%s" % filename)
+ session.cmd("cp -f /mnt/%s /tmp/" % filename)
+
+ error.context("Compare file on disk and on cdrom")
+ f1_hash = session.cmd("md5sum /mnt/%s" % filename).split()[0].strip()
+ f2_hash = session.cmd("md5sum /tmp/%s" % filename).split()[0].strip()
+ if f1_hash != f2_hash:
+ raise error.TestFail("On disk and on cdrom files are different, "
+ "md5 mismatch")
+
+ error.context("Mount/Unmount cdrom for %s times" % max_times)
+ for i in range(1, max_times):
+ try:
+ session.cmd("umount %s" % cdrom_dev)
+ session.cmd("mount %s /mnt" % cdrom_dev)
+ except aexpect.ShellError:
+ logging.debug(session.cmd("cat /etc/mtab"))
+ raise
+
+ session.cmd("umount %s" % cdrom_dev)
+ (device, file) = get_cdrom_info()
+ if device is not None:
+ eject_cdrom(device, vm.monitor)
+
+ session.close()
+ cleanup_cdroms(cdrom_dir)
@@ -1101,6 +1101,13 @@ variants:
kill_vm_gracefully = no
# Do not define test variants below shutdown
+ - cdrom_test: install setup image_copy unattended_install.cdrom
+ only Linux
+ start_vm = no
+ type = cdrom
+ cdrom_cd1 = orig.iso
+ max_times = 20
+
# NICs
variants: