Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(52)

Unified Diff: client/tests/kvm/test_setup.py

Issue 6883035: Merge remote branch 'autotest-upstream/master' into autotest-merge (Closed) Base URL: ssh://gitrw.chromium.org:9222/autotest.git@master
Patch Set: patch Created 9 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: client/tests/kvm/test_setup.py
diff --git a/client/tests/kvm/test_setup.py b/client/tests/kvm/test_setup.py
index 1125aeadff8370e908e63697f230dc362d613a68..f915c1b747b3981e21899506755dee9ccc51ba1d 100644
--- a/client/tests/kvm/test_setup.py
+++ b/client/tests/kvm/test_setup.py
@@ -1,511 +1,11 @@
"""
Library to perform pre/post test setup for KVM autotest.
"""
-import os, shutil, tempfile, re, ConfigParser, glob, inspect
-import logging, time
+import os, logging
from autotest_lib.client.common_lib import error
from autotest_lib.client.bin import utils
-@error.context_aware
-def cleanup(dir):
- """
- If dir is a mountpoint, do what is possible to unmount it. Afterwards,
- try to remove it.
-
- @param dir: Directory to be cleaned up.
- """
- error.context("cleaning up unattended install directory %s" % dir)
- if os.path.ismount(dir):
- utils.run('fuser -k %s' % dir, ignore_status=True)
- utils.run('umount %s' % dir)
- if os.path.isdir(dir):
- shutil.rmtree(dir)
-
-
-@error.context_aware
-def clean_old_image(image):
- """
- Clean a leftover image file from previous processes. If it contains a
- mounted file system, do the proper cleanup procedures.
-
- @param image: Path to image to be cleaned up.
- """
- error.context("cleaning up old leftover image %s" % image)
- if os.path.exists(image):
- mtab = open('/etc/mtab', 'r')
- mtab_contents = mtab.read()
- mtab.close()
- if image in mtab_contents:
- utils.run('fuser -k %s' % image, ignore_status=True)
- utils.run('umount %s' % image)
- os.remove(image)
-
-
-def display_attributes(instance):
- """
- Inspects a given class instance attributes and displays them, convenient
- for debugging.
- """
- logging.debug("Attributes set:")
- for member in inspect.getmembers(instance):
- name, value = member
- attribute = getattr(instance, name)
- if not (name.startswith("__") or callable(attribute) or not value):
- logging.debug(" %s: %s", name, value)
-
-
-class Disk(object):
- """
- Abstract class for Disk objects, with the common methods implemented.
- """
- def __init__(self):
- self.path = None
-
-
- def setup_answer_file(self, filename, contents):
- utils.open_write_close(os.path.join(self.mount, filename), contents)
-
-
- def copy_to(self, src):
- logging.debug("Copying %s to disk image mount", src)
- dst = os.path.join(self.mount, os.path.basename(src))
- if os.path.isdir(src):
- shutil.copytree(src, dst)
- elif os.path.isfile(src):
- shutil.copyfile(src, dst)
-
-
- def close(self):
- os.chmod(self.path, 0755)
- cleanup(self.mount)
- logging.debug("Disk %s successfuly set", self.path)
-
-
-class FloppyDisk(Disk):
- """
- Represents a 1.44 MB floppy disk. We can copy files to it, and setup it in
- convenient ways.
- """
- @error.context_aware
- def __init__(self, path, qemu_img_binary, tmpdir):
- error.context("Creating unattended install floppy image %s" % path)
- self.tmpdir = tmpdir
- self.mount = tempfile.mkdtemp(prefix='floppy_', dir=self.tmpdir)
- self.virtio_mount = None
- self.path = path
- clean_old_image(path)
- if not os.path.isdir(os.path.dirname(path)):
- os.makedirs(os.path.dirname(path))
-
- try:
- c_cmd = '%s create -f raw %s 1440k' % (qemu_img_binary, path)
- utils.run(c_cmd)
- f_cmd = 'mkfs.msdos -s 1 %s' % path
- utils.run(f_cmd)
- m_cmd = 'mount -o loop,rw %s %s' % (path, self.mount)
- utils.run(m_cmd)
- except error.CmdError, e:
- cleanup(self.mount)
- raise
-
-
- def _copy_virtio_drivers(self, virtio_floppy):
- """
- Copy the virtio drivers on the virtio floppy to the install floppy.
-
- 1) Mount the floppy containing the viostor drivers
- 2) Copy its contents to the root of the install floppy
- """
- virtio_mount = tempfile.mkdtemp(prefix='virtio_floppy_',
- dir=self.tmpdir)
-
- pwd = os.getcwd()
- try:
- m_cmd = 'mount -o loop %s %s' % (virtio_floppy, virtio_mount)
- utils.run(m_cmd)
- os.chdir(virtio_mount)
- path_list = glob.glob('*')
- for path in path_list:
- self.copy_to(path)
- finally:
- os.chdir(pwd)
- cleanup(virtio_mount)
-
-
- def setup_virtio_win2003(self, virtio_floppy, virtio_oemsetup_id):
- """
- Setup the install floppy with the virtio storage drivers, win2003 style.
-
- Win2003 and WinXP depend on the file txtsetup.oem file to install
- the virtio drivers from the floppy, which is a .ini file.
- Process:
-
- 1) Copy the virtio drivers on the virtio floppy to the install floppy
- 2) Parse the ini file with config parser
- 3) Modify the identifier of the default session that is going to be
- executed on the config parser object
- 4) Re-write the config file to the disk
- """
- self._copy_virtio_drivers(virtio_floppy)
- txtsetup_oem = os.path.join(self.mount, 'txtsetup.oem')
- if not os.path.isfile(txtsetup_oem):
- raise IOError('File txtsetup.oem not found on the install '
- 'floppy. Please verify if your floppy virtio '
- 'driver image has this file')
- parser = ConfigParser.ConfigParser()
- parser.read(txtsetup_oem)
- if not parser.has_section('Defaults'):
- raise ValueError('File txtsetup.oem does not have the session '
- '"Defaults". Please check txtsetup.oem')
- default_driver = parser.get('Defaults', 'SCSI')
- if default_driver != virtio_oemsetup_id:
- parser.set('Defaults', 'SCSI', virtio_oemsetup_id)
- fp = open(txtsetup_oem, 'w')
- parser.write(fp)
- fp.close()
-
-
- def setup_virtio_win2008(self, virtio_floppy):
- """
- Setup the install floppy with the virtio storage drivers, win2008 style.
-
- Win2008, Vista and 7 require people to point out the path to the drivers
- on the unattended file, so we just need to copy the drivers to the
- driver floppy disk.
- Process:
-
- 1) Copy the virtio drivers on the virtio floppy to the install floppy
- """
- self._copy_virtio_drivers(virtio_floppy)
-
-
-class CdromDisk(Disk):
- """
- Represents a CDROM disk that we can master according to our needs.
- """
- def __init__(self, path, tmpdir):
- self.mount = tempfile.mkdtemp(prefix='cdrom_unattended_', dir=tmpdir)
- self.path = path
- clean_old_image(path)
- if not os.path.isdir(os.path.dirname(path)):
- os.makedirs(os.path.dirname(path))
-
-
- @error.context_aware
- def close(self):
- error.context("Creating unattended install CD image %s" % self.path)
- g_cmd = ('mkisofs -o %s -max-iso9660-filenames '
- '-relaxed-filenames -D --input-charset iso8859-1 '
- '%s' % (self.path, self.mount))
- utils.run(g_cmd)
-
- os.chmod(self.path, 0755)
- cleanup(self.mount)
- logging.debug("unattended install CD image %s successfuly created",
- self.path)
-
-
-class UnattendedInstallConfig(object):
- """
- Creates a floppy disk image that will contain a config file for unattended
- OS install. The parameters to the script are retrieved from environment
- variables.
- """
- def __init__(self, test, params):
- """
- Sets class atributes from test parameters.
-
- @param test: KVM test object.
- @param params: Dictionary with test parameters.
- """
- root_dir = test.bindir
- images_dir = os.path.join(root_dir, 'images')
- self.deps_dir = os.path.join(root_dir, 'deps')
- self.unattended_dir = os.path.join(root_dir, 'unattended')
-
- attributes = ['kernel_args', 'finish_program', 'cdrom_cd1',
- 'unattended_file', 'medium', 'url', 'kernel', 'initrd',
- 'nfs_server', 'nfs_dir', 'install_virtio', 'floppy',
- 'cdrom_unattended', 'boot_path', 'extra_params',
- 'qemu_img_binary', 'cdkey', 'finish_program']
-
- for a in attributes:
- setattr(self, a, params.get(a, ''))
-
- if self.install_virtio == 'yes':
- v_attributes = ['virtio_floppy', 'virtio_storage_path',
- 'virtio_network_path', 'virtio_oemsetup_id',
- 'virtio_network_installer']
- for va in v_attributes:
- setattr(self, va, params.get(va, ''))
-
- self.tmpdir = test.tmpdir
-
- if getattr(self, 'unattended_file'):
- self.unattended_file = os.path.join(root_dir, self.unattended_file)
-
- if getattr(self, 'finish_program'):
- self.finish_program = os.path.join(root_dir, self.finish_program)
-
- if getattr(self, 'qemu_img_binary'):
- if not os.path.isfile(getattr(self, 'qemu_img_binary')):
- self.qemu_img_binary = os.path.join(root_dir,
- self.qemu_img_binary)
-
- if getattr(self, 'cdrom_cd1'):
- self.cdrom_cd1 = os.path.join(root_dir, self.cdrom_cd1)
- self.cdrom_cd1_mount = tempfile.mkdtemp(prefix='cdrom_cd1_',
- dir=self.tmpdir)
- if self.medium == 'nfs':
- self.nfs_mount = tempfile.mkdtemp(prefix='nfs_',
- dir=self.tmpdir)
-
- if getattr(self, 'floppy'):
- self.floppy = os.path.join(root_dir, self.floppy)
- if not os.path.isdir(os.path.dirname(self.floppy)):
- os.makedirs(os.path.dirname(self.floppy))
-
- self.image_path = os.path.dirname(self.kernel)
-
-
- @error.context_aware
- def render_answer_file(self):
- """
- Replace KVM_TEST_CDKEY (in the unattended file) with the cdkey
- provided for this test and replace the KVM_TEST_MEDIUM with
- the tree url or nfs address provided for this test.
-
- @return: Answer file contents
- """
- error.base_context('Rendering final answer file')
- error.context('Reading answer file %s' % self.unattended_file)
- unattended_contents = open(self.unattended_file).read()
- dummy_cdkey_re = r'\bKVM_TEST_CDKEY\b'
- if re.search(dummy_cdkey_re, unattended_contents):
- if self.cdkey:
- unattended_contents = re.sub(dummy_cdkey_re, self.cdkey,
- unattended_contents)
- else:
- print ("WARNING: 'cdkey' required but not specified for "
- "this unattended installation")
-
- dummy_medium_re = r'\bKVM_TEST_MEDIUM\b'
- if self.medium == "cdrom":
- content = "cdrom"
- elif self.medium == "url":
- content = "url --url %s" % self.url
- elif self.medium == "nfs":
- content = "nfs --server=%s --dir=%s" % (self.nfs_server,
- self.nfs_dir)
- else:
- raise ValueError("Unexpected installation medium %s" % self.url)
-
- unattended_contents = re.sub(dummy_medium_re, content,
- unattended_contents)
-
- def replace_virtio_key(contents, dummy_re, attribute_name):
- """
- Replace a virtio dummy string with contents.
-
- If install_virtio is not set, replace it with a dummy string.
-
- @param contents: Contents of the unattended file
- @param dummy_re: Regular expression used to search on the.
- unattended file contents.
- @param env: Name of the environment variable.
- """
- dummy_path = "C:"
- driver = getattr(self, attribute_name, '')
-
- if re.search(dummy_re, contents):
- if self.install_virtio == "yes":
- if driver.endswith("msi"):
- driver = 'msiexec /passive /package ' + driver
- else:
- try:
- # Let's escape windows style paths properly
- drive, path = driver.split(":")
- driver = drive + ":" + re.escape(path)
- except:
- pass
- contents = re.sub(dummy_re, driver, contents)
- else:
- contents = re.sub(dummy_re, dummy_path, contents)
- return contents
-
- vdict = {r'\bKVM_TEST_STORAGE_DRIVER_PATH\b':
- 'virtio_storage_path',
- r'\bKVM_TEST_NETWORK_DRIVER_PATH\b':
- 'virtio_network_path',
- r'\bKVM_TEST_VIRTIO_NETWORK_INSTALLER\b':
- 'virtio_network_installer_path'}
-
- for vkey in vdict:
- unattended_contents = replace_virtio_key(
- contents=unattended_contents,
- dummy_re=vkey,
- attribute_name=vdict[vkey])
-
- logging.debug("Unattended install contents:")
- for line in unattended_contents.splitlines():
- logging.debug(line)
- return unattended_contents
-
-
- def setup_boot_disk(self):
- answer_contents = self.render_answer_file()
-
- if self.unattended_file.endswith('.sif'):
- dest_fname = 'winnt.sif'
- setup_file = 'winnt.bat'
- boot_disk = FloppyDisk(self.floppy, self.qemu_img_binary,
- self.tmpdir)
- boot_disk.setup_answer_file(dest_fname, answer_contents)
- setup_file_path = os.path.join(self.unattended_dir, setup_file)
- boot_disk.copy_to(setup_file_path)
- if self.install_virtio == "yes":
- boot_disk.setup_virtio_win2003(self.virtio_floppy,
- self.virtio_oemsetup_id)
- boot_disk.copy_to(self.finish_program)
-
- elif self.unattended_file.endswith('.ks'):
- # Red Hat kickstart install
- dest_fname = 'ks.cfg'
- if self.cdrom_unattended:
- boot_disk = CdromDisk(self.cdrom_unattended, self.tmpdir)
- elif self.floppy:
- boot_disk = FloppyDisk(self.floppy, self.qemu_img_binary,
- self.tmpdir)
- else:
- raise ValueError("Neither cdrom_unattended nor floppy set "
- "on the config file, please verify")
- boot_disk.setup_answer_file(dest_fname, answer_contents)
-
- elif self.unattended_file.endswith('.xml'):
- if "autoyast" in self.extra_params:
- # SUSE autoyast install
- dest_fname = "autoinst.xml"
- if self.cdrom_unattended:
- boot_disk = CdromDisk(self.cdrom_unattended)
- elif self.floppy:
- boot_disk = FloppyDisk(self.floppy, self.qemu_img_binary,
- self.tmpdir)
- else:
- raise ValueError("Neither cdrom_unattended nor floppy set "
- "on the config file, please verify")
- boot_disk.setup_answer_file(dest_fname, answer_contents)
-
- else:
- # Windows unattended install
- dest_fname = "autounattend.xml"
- boot_disk = FloppyDisk(self.floppy, self.qemu_img_binary,
- self.tmpdir)
- boot_disk.setup_answer_file(dest_fname, answer_contents)
- if self.install_virtio == "yes":
- boot_disk.setup_virtio_win2008(self.virtio_floppy)
- boot_disk.copy_to(self.finish_program)
-
- else:
- raise ValueError('Unknown answer file type: %s' %
- self.unattended_file)
-
- boot_disk.close()
-
-
- @error.context_aware
- def setup_cdrom(self):
- """
- Mount cdrom and copy vmlinuz and initrd.img.
- """
- error.context("Copying vmlinuz and initrd.img from install cdrom %s" %
- self.cdrom_cd1)
- m_cmd = ('mount -t iso9660 -v -o loop,ro %s %s' %
- (self.cdrom_cd1, self.cdrom_cd1_mount))
- utils.run(m_cmd)
-
- try:
- if not os.path.isdir(self.image_path):
- os.makedirs(self.image_path)
- kernel_fetch_cmd = ("cp %s/%s/%s %s" %
- (self.cdrom_cd1_mount, self.boot_path,
- os.path.basename(self.kernel), self.kernel))
- utils.run(kernel_fetch_cmd)
- initrd_fetch_cmd = ("cp %s/%s/%s %s" %
- (self.cdrom_cd1_mount, self.boot_path,
- os.path.basename(self.initrd), self.initrd))
- utils.run(initrd_fetch_cmd)
- finally:
- cleanup(self.cdrom_cd1_mount)
-
-
- @error.context_aware
- def setup_url(self):
- """
- Download the vmlinuz and initrd.img from URL.
- """
- error.context("downloading vmlinuz and initrd.img from %s" % self.url)
- os.chdir(self.image_path)
- kernel_fetch_cmd = "wget -q %s/%s/%s" % (self.url, self.boot_path,
- os.path.basename(self.kernel))
- initrd_fetch_cmd = "wget -q %s/%s/%s" % (self.url, self.boot_path,
- os.path.basename(self.initrd))
-
- if os.path.exists(self.kernel):
- os.remove(self.kernel)
- if os.path.exists(self.initrd):
- os.remove(self.initrd)
-
- utils.run(kernel_fetch_cmd)
- utils.run(initrd_fetch_cmd)
-
-
- def setup_nfs(self):
- """
- Copy the vmlinuz and initrd.img from nfs.
- """
- error.context("copying the vmlinuz and initrd.img from NFS share")
-
- m_cmd = ("mount %s:%s %s -o ro" %
- (self.nfs_server, self.nfs_dir, self.nfs_mount))
- utils.run(m_cmd)
-
- try:
- kernel_fetch_cmd = ("cp %s/%s/%s %s" %
- (self.nfs_mount, self.boot_path,
- os.path.basename(self.kernel), self.image_path))
- utils.run(kernel_fetch_cmd)
- initrd_fetch_cmd = ("cp %s/%s/%s %s" %
- (self.nfs_mount, self.boot_path,
- os.path.basename(self.initrd), self.image_path))
- utils.run(initrd_fetch_cmd)
- finally:
- cleanup(self.nfs_mount)
-
-
- def setup(self):
- """
- Configure the environment for unattended install.
-
- Uses an appropriate strategy according to each install model.
- """
- logging.info("Starting unattended install setup")
- display_attributes(self)
-
- if self.unattended_file and (self.floppy or self.cdrom_unattended):
- self.setup_boot_disk()
- if self.medium == "cdrom":
- if self.kernel and self.initrd:
- self.setup_cdrom()
- elif self.medium == "url":
- self.setup_url()
- elif self.medium == "nfs":
- self.setup_nfs()
- else:
- raise ValueError("Unexpected installation method %s" %
- self.medium)
-
-
class HugePageConfig(object):
def __init__(self, params):
"""
@@ -605,96 +105,3 @@ class HugePageConfig(object):
return
utils.system("echo 0 > %s" % self.kernel_hp_file)
logging.debug("Hugepage memory successfuly dealocated")
-
-
-class EnospcConfig(object):
- """
- Performs setup for the test enospc. This is a borg class, similar to a
- singleton. The idea is to keep state in memory for when we call cleanup()
- on postprocessing.
- """
- __shared_state = {}
- def __init__(self, test, params):
- self.__dict__ = self.__shared_state
- root_dir = test.bindir
- self.tmpdir = test.tmpdir
- self.qemu_img_binary = params.get('qemu_img_binary')
- if not os.path.isfile(self.qemu_img_binary):
- self.qemu_img_binary = os.path.join(root_dir,
- self.qemu_img_binary)
- self.raw_file_path = os.path.join(self.tmpdir, 'enospc.raw')
- # Here we're trying to choose fairly explanatory names so it's less
- # likely that we run in conflict with other devices in the system
- self.vgtest_name = params.get("vgtest_name")
- self.lvtest_name = params.get("lvtest_name")
- self.lvtest_device = "/dev/%s/%s" % (self.vgtest_name, self.lvtest_name)
- image_dir = os.path.dirname(params.get("image_name"))
- self.qcow_file_path = os.path.join(image_dir, 'enospc.qcow2')
- try:
- getattr(self, 'loopback')
- except AttributeError:
- self.loopback = ''
-
-
- @error.context_aware
- def setup(self):
- logging.debug("Starting enospc setup")
- error.context("performing enospc setup")
- display_attributes(self)
- # Double check if there aren't any leftovers
- self.cleanup()
- try:
- utils.run("%s create -f raw %s 10G" %
- (self.qemu_img_binary, self.raw_file_path))
- # Associate a loopback device with the raw file.
- # Subject to race conditions, that's why try here to associate
- # it with the raw file as quickly as possible
- l_result = utils.run("losetup -f")
- utils.run("losetup -f %s" % self.raw_file_path)
- self.loopback = l_result.stdout.strip()
- # Add the loopback device configured to the list of pvs
- # recognized by LVM
- utils.run("pvcreate %s" % self.loopback)
- utils.run("vgcreate %s %s" % (self.vgtest_name, self.loopback))
- # Create an lv inside the vg with starting size of 200M
- utils.run("lvcreate -L 200M -n %s %s" %
- (self.lvtest_name, self.vgtest_name))
- # Create a 10GB qcow2 image in the logical volume
- utils.run("%s create -f qcow2 %s 10G" %
- (self.qemu_img_binary, self.lvtest_device))
- # Let's symlink the logical volume with the image name that autotest
- # expects this device to have
- os.symlink(self.lvtest_device, self.qcow_file_path)
- except Exception, e:
- self.cleanup()
- raise
-
- @error.context_aware
- def cleanup(self):
- error.context("performing enospc cleanup")
- if os.path.isfile(self.lvtest_device):
- utils.run("fuser -k %s" % self.lvtest_device)
- time.sleep(2)
- l_result = utils.run("lvdisplay")
- # Let's remove all volumes inside the volume group created
- if self.lvtest_name in l_result.stdout:
- utils.run("lvremove -f %s" % self.lvtest_device)
- # Now, removing the volume group itself
- v_result = utils.run("vgdisplay")
- if self.vgtest_name in v_result.stdout:
- utils.run("vgremove -f %s" % self.vgtest_name)
- # Now, if we can, let's remove the physical volume from lvm list
- if self.loopback:
- p_result = utils.run("pvdisplay")
- if self.loopback in p_result.stdout:
- utils.run("pvremove -f %s" % self.loopback)
- l_result = utils.run('losetup -a')
- if self.loopback and (self.loopback in l_result.stdout):
- try:
- utils.run("losetup -d %s" % self.loopback)
- except error.CmdError:
- logging.error("Failed to liberate loopback %s", self.loopback)
- if os.path.islink(self.qcow_file_path):
- os.remove(self.qcow_file_path)
- if os.path.isfile(self.raw_file_path):
- os.remove(self.raw_file_path)

Powered by Google App Engine
This is Rietveld 408576698