Commit b6b4f861 authored by Nikos Skalkotos's avatar Nikos Skalkotos
Browse files

windows: Add script to install the virtio drivers

Add a powershell script in the input media that will properly install
the virtio drivers in the next boot.
parent 9eeecc6b
......@@ -23,6 +23,7 @@ from image_creator.util import FatalError
from image_creator.os_type.windows.vm import VM
from image_creator.os_type.windows.registry import Registry
from image_creator.os_type.windows.winexe import WinEXE
from image_creator.os_type.windows.powershell import DRVINST
import tempfile
import random
......@@ -174,12 +175,19 @@ class Windows(OSBase):
# If the image is already sysprepped we cannot further customize it
self.mount(readonly=True, silent=True)
try:
self.out.output("Checking if media is sysprepped ...", False)
self.syspreped = self.registry.get_setup_state() > 0
self.out.output("Checking media state ...", False)
self.sysprepped = self.registry.get_setup_state() > 0
self.virtio_state = self._virtio_state()
self.out.success("done")
finally:
self.umount(silent=True)
# If the image is sysprepped no driver mappings will be present.
self.systemdrive = None
for drive, root in self.image.g.inspect_get_drive_mappings(self.root):
if root == self.root:
self.systemdrive = drive
@sysprep('Disabling IPv6 privacy extensions')
def disable_ipv6_privacy_extensions(self):
"""Disable IPv6 privacy extensions"""
......@@ -236,7 +244,7 @@ class Windows(OSBase):
self.vm.rexec(r'C:\Windows\system32\sysprep\sysprep '
r'/quiet /generalize /oobe /shutdown')
self.syspreped = True
self.sysprepped = True
@sysprep('Converting the image into a KMS client', enabled=False)
def kms_client_setup(self):
......@@ -339,15 +347,31 @@ class Windows(OSBase):
"Winexe not found! In order to be able to customize a Windows "
"image you need to have Winexe installed.")
if self.syspreped:
if self.sysprepped:
raise FatalError(
"Microsoft's System Preparation Tool has ran on the Image. "
"Further image customization is not possible.")
virtio_dir = self.sysprep_params['virtio'].value
if len(self.virtio_state['viostor']) == 0 and not virtio_dir:
raise FatalError(
"The media has no VirtIO SCSI controller driver installed and "
"you have not specified a directory to retrieve the VirtIO "
"drivers from. Further image customization is not possible.")
if len(self.virtio_state['netkvm']) == 0 and not virtio_dir:
raise FatalError(
"The media has no VirtIO Ethernet Adapter driver installed and"
" you have not specified a directory to retrieve the VirtIO "
"drivers from. Further image customization is not possible.")
if virtio_dir:
self._install_virtio_drivers(virtio_dir)
admin = self.sysprep_params['admin'].value
timeout = self.sysprep_params['boot_timeout'].value
shutdown_timeout = self.sysprep_params['shutdown_timeout'].value
virtio_dir = self.sysprep_params['virtio'].value
self.out.output("Preparing media for boot ...", False)
try:
......@@ -356,26 +380,6 @@ class Windows(OSBase):
self._mount_error
raise FatalError(msg)
virtio_state = self._virtio_state()
if len(virtio_state['viostor']) == 0 and not virtio_dir:
raise FatalError(
"The media has no VirtIO SCSI controller driver installed "
"and you have not specified a directory to retrieve the "
"VirtIO drivers from. Further image customization is not "
"possible.")
elif len(virtio_state['viostor']) == 0:
self._install_viostor_driver(virtio_dir)
if len(virtio_state['netkvm']) == 0 and not virtio_dir:
raise FatalError(
"The media has no VirtIO Ethernet Adapter driver installed"
" and you have not specified a directory to retrieve the "
"VirtIO drivers from. Further image customization is not "
"possible.")
if virtio_dir:
self._install_virtio_drivers(virtio_dir)
v_val = self.registry.reset_passwd(admin)
disabled_uac = self.registry.update_uac_remote_setting(1)
token = self._add_boot_scripts()
......@@ -434,7 +438,7 @@ class Windows(OSBase):
if disabled_uac:
self.registry.update_uac_remote_setting(0)
if not self.syspreped:
if not self.sysprepped:
# Reset the old password
admin = self.sysprep_params['admin'].value
self.registry.reset_passwd(admin, v_val)
......@@ -473,7 +477,7 @@ class Windows(OSBase):
setattr(task.im_func, 'executed', True)
self.out.output("Sending shut down command ...", False)
if not self.syspreped:
if not self.sysprepped:
self._shutdown()
self.out.success("done")
......@@ -610,6 +614,54 @@ class Windows(OSBase):
return state
def _install_virtio_drivers(self, dirname):
self.out.output('Installing virtio drivers...', False)
try:
if not self.mount(readonly=False, silent=True):
msg = "Unable to mount the media read-write. Reason: %s" % \
self._mount_error
raise FatalError(msg)
admin = self.sysprep_params['admin'].value
v_val = self.registry.reset_passwd(admin)
self.registry.enable_autologon(admin)
self._install_viostor_driver(dirname)
self._upload_virtio_drivers(dirname)
remotedir = self.image.g.case_sensitive_path("%s/VirtIO" %
self.systemroot)
self.image.g.write(remotedir + "/InstallDrivers.ps1",
DRVINST.replace('\n', '\r\n'))
cmd = (
'%(drive)s:%(root)s\\System32\\WindowsPowerShell\\v1.0\\'
'powershell.exe -ExecutionPolicy RemoteSigned -File '
'%(drive)s:%(root)s\\VirtIO\\InstallDrivers.ps1 '
'%(drive)s:%(root)s\\Virtio' %
{'root': self.systemroot.replace('/', '\\'),
'drive': self.systemdrive})
self.registry.runonce({'InstallDrivers': cmd})
finally:
self.umount(silent=True)
try:
self.vm.start()
self.out.success("started (console on VNC display: %d)" %
self.vm.display)
finally:
self.vm.stop(6000)
try:
self.mount(readonly=True, silent=True)
self.virtio_state = self._virtio_state()
finally:
self.umount(silent=True)
def _install_viostor_driver(self, dirname):
"""Quick and dirty installation of the VirtIO SCSI controller driver.
It is done to make the image boot from the VirtIO disk.
......@@ -635,7 +687,7 @@ class Windows(OSBase):
self.registry.add_viostor()
def _install_virtio_drivers(self, dirname):
def _upload_virtio_drivers(self, dirname):
"""Install the virtio drivers to the media"""
virtio_dir = self.image.g.case_sensitive_path("%s/VirtIO" %
......
# -*- coding: utf-8 -*-
#
# Copyright (C) 2014 GRNET S.A.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
"""This module hosts Windows PowerShell scripts that need to be injected into
the windows image"""
DRVINST = r"""
#requires -version 2
Param([string]$dirName=$(throw "You need to provide a directory name"))
if (!(Test-Path -PathType Container "$dirName")) {
Write-Error -Category InvalidArgument "Invalid Directory: $dirName"
Exit
}
foreach ($file in Get-ChildItem "$dirName" -Filter *.cat) {
$cert = (Get-AuthenticodeSignature $file.FullName).SignerCertificate
$certFile = $dirName + "\" + $file.BaseName + ".cer"
[System.IO.File]::WriteAllBytes($certFile, $cert.Export("Cert"))
CertUtil -addstore TrustedPublisher "$certFile"
}
if (Test-Path "$dirName/viostor.inf") {
pnputil.exe -i -a "$dirName/viostor.inf"
}
pnputil.exe -a "$dirname\*.inf"
shutdown /s /t 5
"""
# vim: set sta sts=4 shiftwidth=4 sw=4 et ai :
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment