diff mbox

[2/3] KVM test: Adapt scripts/unattended.py to handle win virtio drivers

Message ID 1279772594-10281-2-git-send-email-lmr@redhat.com (mailing list archive)
State New, archived
Headers show

Commit Message

Lucas Meneghel Rodrigues July 22, 2010, 4:23 a.m. UTC
None
diff mbox

Patch

diff --git a/client/tests/kvm/scripts/unattended.py b/client/tests/kvm/scripts/unattended.py
index d9b8912..80e848a 100755
--- a/client/tests/kvm/scripts/unattended.py
+++ b/client/tests/kvm/scripts/unattended.py
@@ -3,9 +3,49 @@ 
 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
 import common
 
+KNOWN_PACKAGE_MANAGERS = ['rpm', 'dpkg']
+
+
+def command(cmd):
+    """
+    Find a given command on the user's PATH.
+
+    @param cmd: Command you wish to find (ie, 'ls').
+    @return: Full path to the command.
+    @raise ValueError: In case the command are not found on PATH.
+    """
+    for dir in os.environ['PATH'].split(':'):
+        file = os.path.join(dir, cmd)
+        if os.path.exists(file):
+            return file
+    raise ValueError('Missing command: %s' % cmd)
+
+
+def package_that_owns(file):
+    """
+    Inquiry the main package manager which package owns file.
+
+    @param file: Path to a given file
+    """
+    support_info = {}
+    for package_manager in KNOWN_PACKAGE_MANAGERS:
+        try:
+            command(package_manager)
+            support_info[package_manager] = True
+        except:
+            support_info[package_manager] = False
+
+    if support_info['rpm']:
+        return str(os.popen('rpm -qf %s' % file).read())
+    elif support_info['dpkg']:
+        return str(os.popen('dpkg -S %s' % file).read())
+    else:
+        return ('Did not find a known package manager to inquire about '
+                'file %s' % file)
+
 
 class SetupError(Exception):
     """
@@ -40,10 +80,44 @@  class UnattendedInstall(object):
             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', '')
+        self.finish_program = os.environ.get('KVM_TEST_finish_program', '')
+
         cdrom_iso = os.environ.get('KVM_TEST_cdrom')
         self.unattended_file = os.environ.get('KVM_TEST_unattended_file')
 
+        install_virtio = os.environ.get('KVM_TEST_install_virtio', 'no')
+        if install_virtio == 'yes':
+            self.install_virtio = True
+        else:
+            self.install_virtio = False
+
+        virtio_floppy = os.environ.get('KVM_TEST_virtio_floppy', '')
+        self.virtio_floppy = None
+        self.virtio_floppy_mount = tempfile.mkdtemp(prefix='floppy_',
+                                                    dir='/tmp')
+        if self.install_virtio:
+            if virtio_floppy and os.path.isfile(virtio_floppy):
+                print package_that_owns(virtio_floppy)
+                self.virtio_floppy = virtio_floppy
+            elif virtio_floppy and not os.path.isfile(virtio_floppy):
+                print ('Virtio floppy path %s was not found. Please verify' %
+                       virtio_floppy)
+
+        vni = os.environ.get('KVM_TEST_virtio_network_installer', '')
+        self.virtio_network_installer = None
+        if self.install_virtio and vni:
+            self.virtio_network_installer = vni
+
+        voi = os.environ.get('KVM_TEST_virtio_oemsetup_id', '')
+        self.virtio_oemsetup_identifier = None
+        if self.install_virtio and voi:
+            self.virtio_oemsetup_identifier = voi
+
+        vsp = os.environ.get('KVM_TEST_virtio_storage_path', '')
+        self.virtio_storage_path = None
+        if self.install_virtio and vsp:
+            self.virtio_storage_path = vsp
+
         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)
@@ -72,6 +146,84 @@  class UnattendedInstall(object):
         self.initrd_path = os.path.join(self.image_path, self.initrd)
 
 
+    def copy_virtio_drivers_floppy(self):
+        """
+        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
+        """
+        m_cmd = 'mount -o loop %s %s' % (self.virtio_floppy,
+                                         self.virtio_floppy_mount)
+        pwd = os.getcwd()
+        try:
+            if os.system(m_cmd):
+                raise SetupError('Could not mount virtio floppy driver')
+            os.chdir(self.virtio_floppy_mount)
+            path_list = glob.glob('*')
+            for path in path_list:
+                src = os.path.join(self.virtio_floppy_mount, path)
+                dst = os.path.join(self.floppy_mount, path)
+                if os.path.isdir(path):
+                    shutil.copytree(src, dst)
+                elif os.path.isfile(path):
+                    shutil.copyfile(src, dst)
+        finally:
+            os.chdir(pwd)
+            u_cmd = 'umount %s' % self.virtio_floppy_mount
+            if os.system(u_cmd):
+                raise SetupError('Could not unmount virtio floppy at %s' %
+                                 self.virtio_floppy_mount)
+            self.cleanup(self.virtio_floppy_mount)
+
+
+    def setup_virtio_win2008(self):
+        """
+        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_floppy()
+
+
+    def setup_virtio_win2003(self):
+        """
+        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_floppy()
+        txtsetup_oem = os.path.join(self.floppy_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 != self.virtio_oemsetup_identifier:
+            parser.set('Defaults', 'SCSI', self.virtio_oemsetup_identifier)
+            fp = open(txtsetup_oem, 'w')
+            parser.write(fp)
+            fp.close()
+
+
     def create_boot_floppy(self):
         """
         Prepares a boot floppy by creating a floppy image file, mounting it and
@@ -93,7 +245,8 @@  class UnattendedInstall(object):
             raise SetupError('Error formatting floppy image.')
 
         try:
-            m_cmd = 'mount -o loop %s %s' % (self.floppy_img, self.floppy_mount)
+            m_cmd = 'mount -o loop,rw %s %s' % (self.floppy_img,
+                                                self.floppy_mount)
             if os.system(m_cmd):
                 raise SetupError('Could not mount floppy image.')
 
@@ -103,6 +256,9 @@  class UnattendedInstall(object):
                 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)
+                if self.install_virtio:
+                    self.setup_virtio_win2003()
+
             elif self.unattended_file.endswith('.ks'):
                 # Red Hat kickstart install
                 dest_fname = 'ks.cfg'
@@ -110,6 +266,8 @@  class UnattendedInstall(object):
                 if  self.tftp_root is '':
                     # Windows unattended install
                     dest_fname = "autounattend.xml"
+                    if self.install_virtio:
+                        self.setup_virtio_win2008()
                 else:
                     # SUSE autoyast install
                     dest_fname = "autoinst.xml"
@@ -130,7 +288,7 @@  class UnattendedInstall(object):
                     print ("WARNING: 'cdkey' required but not specified for "
                            "this unattended installation")
 
-            dummy_re = r'\bKVM_TEST_MEDIUM\b'
+            dummy_medium_re = r'\bKVM_TEST_MEDIUM\b'
             if self.medium == "cdrom":
                 content = "cdrom"
             elif self.medium == "url":
@@ -140,7 +298,46 @@  class UnattendedInstall(object):
             else:
                 raise SetupError("Unexpected installation medium %s" % self.url)
 
-            unattended_contents = re.sub(dummy_re, content, unattended_contents)
+            unattended_contents = re.sub(dummy_medium_re, content, unattended_contents)
+
+            dummy_path = "C:"
+
+            dummy_storage_re = r'\bKVM_TEST_STORAGE_DRIVER_PATH\b'
+            storage_driver = os.environ.get('KVM_TEST_virtio_storage_path', '')
+            if re.search(dummy_storage_re, unattended_contents):
+                if self.install_virtio:
+                    unattended_contents = re.sub(dummy_storage_re,
+                                                 storage_driver,
+                                                 unattended_contents)
+                else:
+                    unattended_contents = re.sub(dummy_storage_re,
+                                                 dummy_path,
+                                                 unattended_contents)
+
+            dummy_network_re = r'\bKVM_TEST_NETWORK_DRIVER_PATH\b'
+            network_driver = os.environ.get('KVM_TEST_virtio_network_path', '')
+            if re.search(dummy_network_re, unattended_contents):
+                if self.install_virtio:
+                    unattended_contents = re.sub(dummy_network_re,
+                                                 network_driver,
+                                                 unattended_contents)
+                else:
+                    unattended_contents = re.sub(dummy_network_re,
+                                                 dummy_path,
+                                                 unattended_contents)
+
+            dummy_nw_install_re = r'\bKVM_TEST_VIRTIO_NETWORK_INSTALLER\b'
+            nw_install = os.environ.get('KVM_TEST_virtio_network_installer',
+                                        'help')
+            if re.search(dummy_nw_install_re, unattended_contents):
+                if self.install_virtio:
+                    unattended_contents = re.sub(dummy_nw_install_re,
+                                                 nw_install,
+                                                 unattended_contents)
+                else:
+                    unattended_contents = re.sub(dummy_nw_install_re,
+                                                 'help',
+                                                 unattended_contents)
 
             print
             print "Unattended install %s contents:" % dest_fname