| Index: client/tests/kvm/scripts/unattended.py
 | 
| diff --git a/client/tests/kvm/scripts/unattended.py b/client/tests/kvm/scripts/unattended.py
 | 
| index a630fbc515221d5ae8c7a0b807f893b6fabd62e4..ba7d80b4df22324edb804d000317303eeabe8fd6 100755
 | 
| --- a/client/tests/kvm/scripts/unattended.py
 | 
| +++ b/client/tests/kvm/scripts/unattended.py
 | 
| @@ -3,10 +3,14 @@
 | 
|  Simple script to setup unattended installs on KVM guests.
 | 
|  """
 | 
|  # -*- coding: utf-8 -*-
 | 
| -import os, sys, shutil, tempfile, re
 | 
| +import os, sys, shutil, tempfile, re, ConfigParser, glob, inspect
 | 
|  import common
 | 
|  
 | 
|  
 | 
| +SCRIPT_DIR = os.path.dirname(sys.modules[__name__].__file__)
 | 
| +KVM_TEST_DIR = os.path.abspath(os.path.join(SCRIPT_DIR, ".."))
 | 
| +
 | 
| +
 | 
|  class SetupError(Exception):
 | 
|      """
 | 
|      Simple wrapper for the builtin Exception class.
 | 
| @@ -14,6 +18,227 @@ class SetupError(Exception):
 | 
|      pass
 | 
|  
 | 
|  
 | 
| +def find_command(cmd):
 | 
| +    """
 | 
| +    Searches for a command on common paths, error if it can't find it.
 | 
| +
 | 
| +    @param cmd: Command to be found.
 | 
| +    """
 | 
| +    for dir in ["/usr/local/sbin", "/usr/local/bin",
 | 
| +                "/usr/sbin", "/usr/bin", "/sbin", "/bin"]:
 | 
| +        file = os.path.join(dir, cmd)
 | 
| +        if os.path.exists(file):
 | 
| +            return file
 | 
| +    raise ValueError('Missing command: %s' % cmd)
 | 
| +
 | 
| +
 | 
| +def run(cmd, info=None):
 | 
| +    """
 | 
| +    Run a command and throw an exception if it fails.
 | 
| +    Optionally, you can provide additional contextual info.
 | 
| +
 | 
| +    @param cmd: Command string.
 | 
| +    @param reason: Optional string that explains the context of the failure.
 | 
| +
 | 
| +    @raise: SetupError if command fails.
 | 
| +    """
 | 
| +    print "Running '%s'" % cmd
 | 
| +    cmd_name = cmd.split(' ')[0]
 | 
| +    find_command(cmd_name)
 | 
| +    if os.system(cmd):
 | 
| +        e_msg = 'Command failed: %s' % cmd
 | 
| +        if info is not None:
 | 
| +            e_msg += '. %s' % info
 | 
| +        raise SetupError(e_msg)
 | 
| +
 | 
| +
 | 
| +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.
 | 
| +    """
 | 
| +    print "Cleaning up directory %s" % dir
 | 
| +    if os.path.ismount(dir):
 | 
| +        os.system('fuser -k %s' % dir)
 | 
| +        run('umount %s' % dir, info='Could not unmount %s' % dir)
 | 
| +    if os.path.isdir(dir):
 | 
| +        shutil.rmtree(dir)
 | 
| +
 | 
| +
 | 
| +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.
 | 
| +    """
 | 
| +    if os.path.exists(image):
 | 
| +        mtab = open('/etc/mtab', 'r')
 | 
| +        mtab_contents = mtab.read()
 | 
| +        mtab.close()
 | 
| +        if image in mtab_contents:
 | 
| +            os.system('fuser -k %s' % image)
 | 
| +            os.system('umount %s' % image)
 | 
| +        os.remove(image)
 | 
| +
 | 
| +
 | 
| +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):
 | 
| +        answer_file = open(os.path.join(self.mount, filename), 'w')
 | 
| +        answer_file.write(contents)
 | 
| +        answer_file.close()
 | 
| +
 | 
| +
 | 
| +    def copy_to(self, 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)
 | 
| +        print "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.
 | 
| +    """
 | 
| +    def __init__(self, path):
 | 
| +        print "Creating floppy unattended image %s" % path
 | 
| +        try:
 | 
| +            qemu_img_binary = os.environ['KVM_TEST_qemu_img_binary']
 | 
| +        except KeyError:
 | 
| +            qemu_img_binary = os.path.join(KVM_TEST_DIR, qemu_img_binary)
 | 
| +        if not os.path.exists(qemu_img_binary):
 | 
| +            raise SetupError('The qemu-img binary that is supposed to be used '
 | 
| +                             '(%s) does not exist. Please verify your '
 | 
| +                             'configuration' % qemu_img_binary)
 | 
| +
 | 
| +        self.mount = tempfile.mkdtemp(prefix='floppy_', dir='/tmp')
 | 
| +        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)
 | 
| +            run(c_cmd, info='Could not create floppy image')
 | 
| +            f_cmd = 'mkfs.msdos -s 1 %s' % path
 | 
| +            run(f_cmd, info='Error formatting floppy image')
 | 
| +            m_cmd = 'mount -o loop,rw %s %s' % (path, self.mount)
 | 
| +            run(m_cmd, info='Could not mount floppy image')
 | 
| +        except:
 | 
| +            cleanup(self.mount)
 | 
| +
 | 
| +
 | 
| +    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='/tmp')
 | 
| +
 | 
| +        pwd = os.getcwd()
 | 
| +        try:
 | 
| +            m_cmd = 'mount -o loop %s %s' % (virtio_floppy, virtio_mount)
 | 
| +            run(m_cmd, info='Could not mount virtio floppy driver')
 | 
| +            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 SetupError('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 SetupError('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):
 | 
| +        print "Creating ISO unattended image %s" % path
 | 
| +        self.mount = tempfile.mkdtemp(prefix='cdrom_unattended_', dir='/tmp')
 | 
| +        self.path = path
 | 
| +        clean_old_image(path)
 | 
| +        if not os.path.isdir(os.path.dirname(path)):
 | 
| +            os.makedirs(os.path.dirname(path))
 | 
| +
 | 
| +
 | 
| +    def close(self):
 | 
| +        g_cmd = ('mkisofs -o %s -max-iso9660-filenames '
 | 
| +                 '-relaxed-filenames -D --input-charset iso8859-1 '
 | 
| +                 '%s' % (self.path, self.mount))
 | 
| +        run(g_cmd, info='Could not generate iso with answer file')
 | 
| +
 | 
| +        os.chmod(self.path, 0755)
 | 
| +        cleanup(self.mount)
 | 
| +        print "Disk %s successfuly set" % self.path
 | 
| +
 | 
| +
 | 
|  class UnattendedInstall(object):
 | 
|      """
 | 
|      Creates a floppy disk image that will contain a config file for unattended
 | 
| @@ -25,144 +250,188 @@ class UnattendedInstall(object):
 | 
|          """
 | 
|          Gets params from environment variables and sets class attributes.
 | 
|          """
 | 
| -        script_dir = os.path.dirname(sys.modules[__name__].__file__)
 | 
| -        kvm_test_dir = os.path.abspath(os.path.join(script_dir, ".."))
 | 
| -        images_dir = os.path.join(kvm_test_dir, 'images')
 | 
| -        self.deps_dir = os.path.join(kvm_test_dir, 'deps')
 | 
| -        self.unattended_dir = os.path.join(kvm_test_dir, 'unattended')
 | 
| -
 | 
| -        tftp_root = os.environ.get('KVM_TEST_tftp', '')
 | 
| -        if tftp_root:
 | 
| -            self.tftp_root = os.path.join(kvm_test_dir, tftp_root)
 | 
| -            if not os.path.isdir(self.tftp_root):
 | 
| -                os.makedirs(self.tftp_root)
 | 
| -        else:
 | 
| -            self.tftp_root = tftp_root
 | 
| -
 | 
| -        self.kernel_args = os.environ.get('KVM_TEST_kernel_args', '')
 | 
| -        self.finish_program= os.environ.get('KVM_TEST_finish_program', '')
 | 
| -        cdrom_iso = os.environ.get('KVM_TEST_cdrom_cd1')
 | 
| -        self.unattended_file = os.environ.get('KVM_TEST_unattended_file')
 | 
| -
 | 
| -        self.qemu_img_bin = os.environ.get('KVM_TEST_qemu_img_binary')
 | 
| -        if not os.path.isabs(self.qemu_img_bin):
 | 
| -            self.qemu_img_bin = os.path.join(kvm_test_dir, self.qemu_img_bin)
 | 
| -        self.cdrom_iso = os.path.join(kvm_test_dir, cdrom_iso)
 | 
| -        self.floppy_mount = tempfile.mkdtemp(prefix='floppy_', dir='/tmp')
 | 
| -        self.cdrom_mount = tempfile.mkdtemp(prefix='cdrom_', dir='/tmp')
 | 
| -        self.nfs_mount = tempfile.mkdtemp(prefix='nfs_', dir='/tmp')
 | 
| -        floppy_name = os.environ['KVM_TEST_floppy']
 | 
| -        self.floppy_img = os.path.join(kvm_test_dir, floppy_name)
 | 
| -        floppy_dir = os.path.dirname(self.floppy_img)
 | 
| -        if not os.path.isdir(floppy_dir):
 | 
| -            os.makedirs(floppy_dir)
 | 
| -
 | 
| -        self.pxe_dir = os.environ.get('KVM_TEST_pxe_dir', '')
 | 
| -        self.pxe_image = os.environ.get('KVM_TEST_pxe_image', '')
 | 
| -        self.pxe_initrd = os.environ.get('KVM_TEST_pxe_initrd', '')
 | 
| -
 | 
| -        self.medium = os.environ.get('KVM_TEST_medium', '')
 | 
| -        self.url = os.environ.get('KVM_TEST_url', '')
 | 
| -        self.kernel = os.environ.get('KVM_TEST_kernel', '')
 | 
| -        self.initrd = os.environ.get('KVM_TEST_initrd', '')
 | 
| -        self.nfs_server = os.environ.get('KVM_TEST_nfs_server', '')
 | 
| -        self.nfs_dir = os.environ.get('KVM_TEST_nfs_dir', '')
 | 
| -        self.image_path = kvm_test_dir
 | 
| +        images_dir = os.path.join(KVM_TEST_DIR, 'images')
 | 
| +        self.deps_dir = os.path.join(KVM_TEST_DIR, 'deps')
 | 
| +        self.unattended_dir = os.path.join(KVM_TEST_DIR, 'unattended')
 | 
| +
 | 
| +        attributes = ['kernel_args', 'finish_program', 'cdrom_cd1',
 | 
| +                      'unattended_file', 'medium', 'url', 'kernel', 'initrd',
 | 
| +                      'nfs_server', 'nfs_dir', 'pxe_dir', 'pxe_image',
 | 
| +                      'pxe_initrd', 'install_virtio', 'tftp',
 | 
| +                      'floppy', 'cdrom_unattended']
 | 
| +        for a in attributes:
 | 
| +            self._setattr(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:
 | 
| +                self._setattr(va)
 | 
| +
 | 
| +        # Silly attribution just to calm pylint down...
 | 
| +        self.tftp = self.tftp
 | 
| +        if self.tftp:
 | 
| +            self.tftp = os.path.join(KVM_TEST_DIR, self.tftp)
 | 
| +            if not os.path.isdir(self.tftp):
 | 
| +                os.makedirs(self.tftp)
 | 
| +
 | 
| +        self.cdrom_cd1 = os.path.join(KVM_TEST_DIR, self.cdrom_cd1)
 | 
| +        self.cdrom_cd1_mount = tempfile.mkdtemp(prefix='cdrom_cd1_', dir='/tmp')
 | 
| +        if self.medium == 'nfs':
 | 
| +            self.nfs_mount = tempfile.mkdtemp(prefix='nfs_', dir='/tmp')
 | 
| +
 | 
| +        self.floppy = os.path.join(KVM_TEST_DIR, self.floppy)
 | 
| +        if not os.path.isdir(os.path.dirname(self.floppy)):
 | 
| +            os.makedirs(os.path.dirname(self.floppy))
 | 
| +
 | 
| +        self.image_path = KVM_TEST_DIR
 | 
|          self.kernel_path = os.path.join(self.image_path, self.kernel)
 | 
|          self.initrd_path = os.path.join(self.image_path, self.initrd)
 | 
|  
 | 
|  
 | 
| -    def create_boot_floppy(self):
 | 
| +    def _setattr(self, key):
 | 
|          """
 | 
| -        Prepares a boot floppy by creating a floppy image file, mounting it and
 | 
| -        copying an answer file (kickstarts for RH based distros, answer files
 | 
| -        for windows) to it. After that the image is umounted.
 | 
| -        """
 | 
| -        print "Creating boot floppy"
 | 
| -
 | 
| -        if os.path.exists(self.floppy_img):
 | 
| -            os.remove(self.floppy_img)
 | 
| +        Populate class attributes with contents of environment variables.
 | 
|  
 | 
| -        c_cmd = '%s create -f raw %s 1440k' % (self.qemu_img_bin,
 | 
| -                                               self.floppy_img)
 | 
| -        if os.system(c_cmd):
 | 
| -            raise SetupError('Could not create floppy image.')
 | 
| +        Example: KVM_TEST_medium will populate self.medium.
 | 
|  
 | 
| -        f_cmd = 'mkfs.msdos -s 1 %s' % self.floppy_img
 | 
| -        if os.system(f_cmd):
 | 
| -            raise SetupError('Error formatting floppy image.')
 | 
| +        @param key: Name of the class attribute we desire to have.
 | 
| +        """
 | 
| +        env_name = 'KVM_TEST_%s' % key
 | 
| +        value = os.environ.get(env_name, '')
 | 
| +        setattr(self, key, value)
 | 
| +
 | 
| +
 | 
| +    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.
 | 
| +        unattended_contents = open(self.unattended_file).read()
 | 
| +        dummy_cdkey_re = r'\bKVM_TEST_CDKEY\b'
 | 
| +        real_cdkey = os.environ.get('KVM_TEST_cdkey')
 | 
| +        if re.search(dummy_cdkey_re, unattended_contents):
 | 
| +            if real_cdkey:
 | 
| +                unattended_contents = re.sub(dummy_cdkey_re, real_cdkey,
 | 
| +                                             unattended_contents)
 | 
| +            else:
 | 
| +                print ("WARNING: 'cdkey' required but not specified for "
 | 
| +                       "this unattended installation")
 | 
|  
 | 
| -        try:
 | 
| -            m_cmd = 'mount -o loop %s %s' % (self.floppy_img, self.floppy_mount)
 | 
| -            if os.system(m_cmd):
 | 
| -                raise SetupError('Could not mount floppy image.')
 | 
| -
 | 
| -            if self.unattended_file.endswith('.sif'):
 | 
| -                dest_fname = 'winnt.sif'
 | 
| -                setup_file = 'winnt.bat'
 | 
| -                setup_file_path = os.path.join(self.unattended_dir, setup_file)
 | 
| -                setup_file_dest = os.path.join(self.floppy_mount, setup_file)
 | 
| -                shutil.copyfile(setup_file_path, setup_file_dest)
 | 
| -            elif self.unattended_file.endswith('.ks'):
 | 
| -                # Red Hat kickstart install
 | 
| -                dest_fname = 'ks.cfg'
 | 
| -            elif self.unattended_file.endswith('.xml'):
 | 
| -                if  self.tftp_root is '':
 | 
| -                    # Windows unattended install
 | 
| -                    dest_fname = "autounattend.xml"
 | 
| -                else:
 | 
| -                    # SUSE autoyast install
 | 
| -                    dest_fname = "autoinst.xml"
 | 
| -
 | 
| -            dest = os.path.join(self.floppy_mount, dest_fname)
 | 
| -
 | 
| -            # 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.
 | 
| -            unattended_contents = open(self.unattended_file).read()
 | 
| -            dummy_cdkey_re = r'\bKVM_TEST_CDKEY\b'
 | 
| -            real_cdkey = os.environ.get('KVM_TEST_cdkey')
 | 
| -            if re.search(dummy_cdkey_re, unattended_contents):
 | 
| -                if real_cdkey:
 | 
| -                    unattended_contents = re.sub(dummy_cdkey_re, real_cdkey,
 | 
| -                                                 unattended_contents)
 | 
| +        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 SetupError("Unexpected installation medium %s" % self.url)
 | 
| +
 | 
| +        unattended_contents = re.sub(dummy_medium_re, content,
 | 
| +                                     unattended_contents)
 | 
| +
 | 
| +        def replace_virtio_key(contents, dummy_re, env):
 | 
| +            """
 | 
| +            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 = os.environ.get(env, '')
 | 
| +
 | 
| +            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:
 | 
| -                    print ("WARNING: 'cdkey' required but not specified for "
 | 
| -                           "this unattended installation")
 | 
| -
 | 
| -            dummy_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)
 | 
| +                    contents = re.sub(dummy_re, dummy_path, contents)
 | 
| +            return contents
 | 
| +
 | 
| +        vdict = {r'\bKVM_TEST_STORAGE_DRIVER_PATH\b':
 | 
| +                 'KVM_TEST_virtio_storage_path',
 | 
| +                 r'\bKVM_TEST_NETWORK_DRIVER_PATH\b':
 | 
| +                 'KVM_TEST_virtio_network_path',
 | 
| +                 r'\bKVM_TEST_VIRTIO_NETWORK_INSTALLER\b':
 | 
| +                 'KVM_TEST_virtio_network_installer_path'}
 | 
| +
 | 
| +        for vkey in vdict:
 | 
| +            unattended_contents = replace_virtio_key(unattended_contents,
 | 
| +                                                     vkey, vdict[vkey])
 | 
| +
 | 
| +        print "Unattended install contents:"
 | 
| +        print unattended_contents
 | 
| +        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)
 | 
| +            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)
 | 
| +            elif self.floppy:
 | 
| +                boot_disk = FloppyDisk(self.floppy)
 | 
|              else:
 | 
| -                raise SetupError("Unexpected installation medium %s" % self.url)
 | 
| -
 | 
| -            unattended_contents = re.sub(dummy_re, content, unattended_contents)
 | 
| -
 | 
| -            print
 | 
| -            print "Unattended install %s contents:" % dest_fname
 | 
| -            print unattended_contents
 | 
| -            # Write the unattended file contents to 'dest'
 | 
| -            open(dest, 'w').write(unattended_contents)
 | 
| -
 | 
| -            if self.finish_program:
 | 
| -                dest_fname = os.path.basename(self.finish_program)
 | 
| -                dest = os.path.join(self.floppy_mount, dest_fname)
 | 
| -                shutil.copyfile(self.finish_program, dest)
 | 
| +                raise SetupError("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 self.tftp:
 | 
| +                # 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)
 | 
| +                else:
 | 
| +                    raise SetupError("Neither cdrom_unattended nor floppy set "
 | 
| +                                     "on the config file, please verify")
 | 
| +                boot_disk.setup_answer_file(dest_fname, answer_contents)
 | 
|  
 | 
| -        finally:
 | 
| -            u_cmd = 'umount %s' % self.floppy_mount
 | 
| -            if os.system(u_cmd):
 | 
| -                raise SetupError('Could not unmount floppy at %s.' %
 | 
| -                                 self.floppy_mount)
 | 
| -            self.cleanup(self.floppy_mount)
 | 
| +            else:
 | 
| +                # Windows unattended install
 | 
| +                dest_fname = "autounattend.xml"
 | 
| +                boot_disk = FloppyDisk(self.floppy)
 | 
| +                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)
 | 
|  
 | 
| -        os.chmod(self.floppy_img, 0755)
 | 
| +        else:
 | 
| +            raise SetupError('Unknown answer file %s' %
 | 
| +                             self.unattended_file)
 | 
|  
 | 
| -        print "Boot floppy created successfuly"
 | 
| +        boot_disk.close()
 | 
|  
 | 
|  
 | 
|      def setup_pxe_boot(self):
 | 
| @@ -173,7 +442,7 @@ class UnattendedInstall(object):
 | 
|          initrd.img files from the CD to a directory that qemu will serve trough
 | 
|          TFTP to the VM.
 | 
|          """
 | 
| -        print "Setting up PXE boot using TFTP root %s" % self.tftp_root
 | 
| +        print "Setting up PXE boot using TFTP root %s" % self.tftp
 | 
|  
 | 
|          pxe_file = None
 | 
|          pxe_paths = ['/usr/lib/syslinux/pxelinux.0',
 | 
| @@ -188,17 +457,15 @@ class UnattendedInstall(object):
 | 
|                               'sure pxelinux or equivalent package for your '
 | 
|                               'distro is installed.')
 | 
|  
 | 
| -        pxe_dest = os.path.join(self.tftp_root, 'pxelinux.0')
 | 
| +        pxe_dest = os.path.join(self.tftp, 'pxelinux.0')
 | 
|          shutil.copyfile(pxe_file, pxe_dest)
 | 
|  
 | 
|          try:
 | 
| -            m_cmd = 'mount -t iso9660 -v -o loop,ro %s %s' % (self.cdrom_iso,
 | 
| -                                                              self.cdrom_mount)
 | 
| -            if os.system(m_cmd):
 | 
| -                raise SetupError('Could not mount CD image %s.' %
 | 
| -                                 self.cdrom_iso)
 | 
| +            m_cmd = ('mount -t iso9660 -v -o loop,ro %s %s' %
 | 
| +                     (self.cdrom_cd1, self.cdrom_cd1_mount))
 | 
| +            run(m_cmd, info='Could not mount CD image %s.' % self.cdrom_cd1)
 | 
|  
 | 
| -            pxe_dir = os.path.join(self.cdrom_mount, self.pxe_dir)
 | 
| +            pxe_dir = os.path.join(self.cdrom_cd1_mount, self.pxe_dir)
 | 
|              pxe_image = os.path.join(pxe_dir, self.pxe_image)
 | 
|              pxe_initrd = os.path.join(pxe_dir, self.pxe_initrd)
 | 
|  
 | 
| @@ -213,19 +480,15 @@ class UnattendedInstall(object):
 | 
|                                   'or a initrd.img file. Cannot find a PXE '
 | 
|                                   'image to proceed.' % self.pxe_dir)
 | 
|  
 | 
| -            tftp_image = os.path.join(self.tftp_root, 'vmlinuz')
 | 
| -            tftp_initrd = os.path.join(self.tftp_root, 'initrd.img')
 | 
| +            tftp_image = os.path.join(self.tftp, 'vmlinuz')
 | 
| +            tftp_initrd = os.path.join(self.tftp, 'initrd.img')
 | 
|              shutil.copyfile(pxe_image, tftp_image)
 | 
|              shutil.copyfile(pxe_initrd, tftp_initrd)
 | 
|  
 | 
|          finally:
 | 
| -            u_cmd = 'umount %s' % self.cdrom_mount
 | 
| -            if os.system(u_cmd):
 | 
| -                raise SetupError('Could not unmount CD at %s.' %
 | 
| -                                 self.cdrom_mount)
 | 
| -            self.cleanup(self.cdrom_mount)
 | 
| +            cleanup(self.cdrom_cd1_mount)
 | 
|  
 | 
| -        pxe_config_dir = os.path.join(self.tftp_root, 'pxelinux.cfg')
 | 
| +        pxe_config_dir = os.path.join(self.tftp, 'pxelinux.cfg')
 | 
|          if not os.path.isdir(pxe_config_dir):
 | 
|              os.makedirs(pxe_config_dir)
 | 
|          pxe_config_path = os.path.join(pxe_config_dir, 'default')
 | 
| @@ -245,7 +508,7 @@ class UnattendedInstall(object):
 | 
|  
 | 
|      def setup_url(self):
 | 
|          """
 | 
| -        Download the vmlinuz and initrd.img from URL
 | 
| +        Download the vmlinuz and initrd.img from URL.
 | 
|          """
 | 
|          print "Downloading the vmlinuz and initrd.img"
 | 
|          os.chdir(self.image_path)
 | 
| @@ -258,12 +521,11 @@ class UnattendedInstall(object):
 | 
|          if os.path.exists(self.initrd):
 | 
|              os.unlink(self.initrd)
 | 
|  
 | 
| -        if os.system(kernel_fetch_cmd) != 0:
 | 
| -            raise SetupError("Could not fetch vmlinuz from %s" % self.url)
 | 
| -        if os.system(initrd_fetch_cmd) != 0:
 | 
| -            raise SetupError("Could not fetch initrd.img from %s" % self.url)
 | 
| +        run(kernel_fetch_cmd, info="Could not fetch vmlinuz from %s" % self.url)
 | 
| +        run(initrd_fetch_cmd, info=("Could not fetch initrd.img from %s" %
 | 
| +                                    self.url))
 | 
| +        print "Download of vmlinuz and initrd.img finished"
 | 
|  
 | 
| -        print "Downloading finish"
 | 
|  
 | 
|      def setup_nfs(self):
 | 
|          """
 | 
| @@ -271,71 +533,44 @@ class UnattendedInstall(object):
 | 
|          """
 | 
|          print "Copying the vmlinuz and initrd.img from nfs"
 | 
|  
 | 
| -        m_cmd = "mount %s:%s %s -o ro" % (self.nfs_server, self.nfs_dir, self.nfs_mount)
 | 
| -        if os.system(m_cmd):
 | 
| -            raise SetupError('Could not mount nfs server.')
 | 
| -
 | 
| -        kernel_fetch_cmd = "cp %s/isolinux/%s %s" % (self.nfs_mount,
 | 
| -                                                     self.kernel,
 | 
| -                                                     self.image_path)
 | 
| -        initrd_fetch_cmd = "cp %s/isolinux/%s %s" % (self.nfs_mount,
 | 
| -                                                     self.initrd,
 | 
| -                                                     self.image_path)
 | 
| +        m_cmd = ("mount %s:%s %s -o ro" %
 | 
| +                 (self.nfs_server, self.nfs_dir, self.nfs_mount))
 | 
| +        run(m_cmd, info='Could not mount nfs server')
 | 
|  
 | 
|          try:
 | 
| -            if os.system(kernel_fetch_cmd):
 | 
| -                raise SetupError("Could not copy the vmlinuz from %s" %
 | 
| -                                 self.nfs_mount)
 | 
| -            if os.system(initrd_fetch_cmd):
 | 
| -                raise SetupError("Could not copy the initrd.img from %s" %
 | 
| -                                 self.nfs_mount)
 | 
| +            kernel_fetch_cmd = ("cp %s/isolinux/%s %s" %
 | 
| +                                (self.nfs_mount, self.kernel, self.image_path))
 | 
| +            run(kernel_fetch_cmd, info=("Could not copy the vmlinuz from %s" %
 | 
| +                                        self.nfs_mount))
 | 
| +            initrd_fetch_cmd = ("cp %s/isolinux/%s %s" %
 | 
| +                                (self.nfs_mount, self.initrd, self.image_path))
 | 
| +            run(initrd_fetch_cmd, info=("Could not copy the initrd.img from "
 | 
| +                                        "%s" % self.nfs_mount))
 | 
|          finally:
 | 
| -            u_cmd = "umount %s" % self.nfs_mount
 | 
| -            if os.system(u_cmd):
 | 
| -                raise SetupError("Could not unmont nfs at %s" % self.nfs_mount)
 | 
| -            self.cleanup(self.nfs_mount)
 | 
| +            cleanup(self.nfs_mount)
 | 
|  
 | 
| -    def cleanup(self, mount):
 | 
| -        """
 | 
| -        Clean up a previously used mountpoint.
 | 
|  
 | 
| -        @param mount: Mountpoint to be cleaned up.
 | 
| +    def setup(self):
 | 
|          """
 | 
| -        if os.path.isdir(mount):
 | 
| -            if os.path.ismount(mount):
 | 
| -                print "Path %s is still mounted, please verify" % mount
 | 
| -            else:
 | 
| -                print "Removing mount point %s" % mount
 | 
| -                os.rmdir(mount)
 | 
| -
 | 
| +        Configure the environment for unattended install.
 | 
|  
 | 
| -    def setup(self):
 | 
| +        Uses an appropriate strategy according to each install model.
 | 
| +        """
 | 
|          print "Starting unattended install setup"
 | 
| +        print
 | 
|  
 | 
|          print "Variables set:"
 | 
| -        print "    medium: " + str(self.medium)
 | 
| -        print "    qemu_img_bin: " + str(self.qemu_img_bin)
 | 
| -        print "    cdrom iso: " + str(self.cdrom_iso)
 | 
| -        print "    unattended_file: " + str(self.unattended_file)
 | 
| -        print "    kernel_args: " + str(self.kernel_args)
 | 
| -        print "    tftp_root: " + str(self.tftp_root)
 | 
| -        print "    floppy_mount: " + str(self.floppy_mount)
 | 
| -        print "    floppy_img: " + str(self.floppy_img)
 | 
| -        print "    finish_program: " + str(self.finish_program)
 | 
| -        print "    pxe_dir: " + str(self.pxe_dir)
 | 
| -        print "    pxe_image: " + str(self.pxe_image)
 | 
| -        print "    pxe_initrd: " + str(self.pxe_initrd)
 | 
| -        print "    url: " + str(self.url)
 | 
| -        print "    kernel: " + str(self.kernel)
 | 
| -        print "    initrd: " + str(self.initrd)
 | 
| -        print "    nfs_server: " + str(self.nfs_server)
 | 
| -        print "    nfs_dir: " + str(self.nfs_dir)
 | 
| -        print "    nfs_mount: " + str(self.nfs_mount)
 | 
| -
 | 
| -        if self.unattended_file and self.floppy_img is not None:
 | 
| -            self.create_boot_floppy()
 | 
| +        for member in inspect.getmembers(self):
 | 
| +            name, value = member
 | 
| +            attribute = getattr(self, name)
 | 
| +            if not (name.startswith("__") or callable(attribute) or not value):
 | 
| +                print "    %s: %s" % (name, value)
 | 
| +        print
 | 
| +
 | 
| +        if self.unattended_file and (self.floppy or self.cdrom_unattended):
 | 
| +            self.setup_boot_disk()
 | 
|          if self.medium == "cdrom":
 | 
| -            if self.tftp_root:
 | 
| +            if self.tftp:
 | 
|                  self.setup_pxe_boot()
 | 
|          elif self.medium == "url":
 | 
|              self.setup_url()
 | 
| @@ -343,7 +578,7 @@ class UnattendedInstall(object):
 | 
|              self.setup_nfs()
 | 
|          else:
 | 
|              raise SetupError("Unexpected installation method %s" %
 | 
| -                                   self.medium)
 | 
| +                             self.medium)
 | 
|          print "Unattended install setup finished successfuly"
 | 
|  
 | 
|  
 | 
| 
 |