diff --git a/image_creator/dialog_menu.py b/image_creator/dialog_menu.py
index 028e6a854fcee7c652f0cc3bcd04eb4e0f52299d..831e583f9104159252ecbfde633d57752333539a 100644
--- a/image_creator/dialog_menu.py
+++ b/image_creator/dialog_menu.py
@@ -33,7 +33,7 @@ from image_creator.kamaki_wrapper import Kamaki, ClientError
from image_creator.help import get_help_file
from image_creator.dialog_util import SMALL_WIDTH, WIDTH, \
update_background_title, confirm_reset, confirm_exit, Reset, \
- extract_image, add_cloud, edit_cloud, select_file
+ extract_image, add_cloud, edit_cloud, virtio_versions, update_sysprep_param
CONFIGURATION_TASKS = [
("Partition table manipulation", ["FixPartitionTable"],
@@ -641,45 +641,6 @@ def exclude_tasks(session):
return True
-def update_sysprep_param(session, name, title=None):
- """Modify the value of a sysprep parameter"""
- d = session['dialog']
- image = session['image']
-
- param = image.os.sysprep_params[name]
-
- while 1:
- if param.type in ("file", "dir"):
- if not title:
- title = "Please select a %s to use for the `%s' parameter" % \
- ('file' if param.type == 'file' else 'directory', name)
- ftype = "br" if param.type == 'file' else 'd'
-
- value = select_file(d, ftype=ftype, title=title)
- if value is None:
- return False
- else:
- if not title:
- title = "Please provide a new value for configuration " \
- "parameter: `%s'" % name
- (code, answer) = d.inputbox(
- title, width=WIDTH, init=str(param.value))
-
- if code in (d.DIALOG_CANCEL, d.DIALOG_ESC):
- return False
-
- value = answer.strip()
-
- if param.set_value(value) is False:
- d.msgbox("Unable to update the value. Reason: %s" % param.error,
- width=WIDTH)
- param.error = None
- continue
- break
-
- return True
-
-
def sysprep_params(session):
"""Collect the needed sysprep parameters"""
d = session['dialog']
@@ -740,11 +701,7 @@ def virtio(session):
default_item = image.os.virtio_state.keys()[0]
while 1:
choices = []
- for name, infs in image.os.virtio_state.items():
- driver_ver = [drv['DriverVer'].split(',', 1) if 'DriverVer' in drv
- else [] for drv in infs.values()]
- vers = [v[1] if len(v) > 1 else " " for v in driver_ver]
- details = "<not installed>" if len(infs) == 0 else ", ".join(vers)
+ for name, details in virtio_versions(image.os.virtio_state).items():
choices.append((name, details))
(code, choice) = d.menu(
diff --git a/image_creator/dialog_util.py b/image_creator/dialog_util.py
index 6e4c95c91fa257f12d0527fa58c9a9c473131150..faef57612b0498199f0ad410ae574fa0d6a5744c 100644
--- a/image_creator/dialog_util.py
+++ b/image_creator/dialog_util.py
@@ -336,4 +336,56 @@ def edit_cloud(session, name):
return True
+
+def virtio_versions(virtio_state):
+ """Returns the versions of the drivers defined by the virtio state"""
+
+ ret = {}
+ for name, infs in virtio_state.items():
+ driver_ver = [drv['DriverVer'].split(',', 1) if 'DriverVer' in drv
+ else [] for drv in infs.values()]
+ vers = [v[1] if len(v) > 1 else " " for v in driver_ver]
+ ret[name] = "<not found>" if len(infs) == 0 else ", ".join(vers)
+
+ return ret
+
+
+def update_sysprep_param(session, name, title=None):
+ """Modify the value of a sysprep parameter"""
+ d = session['dialog']
+ image = session['image']
+
+ param = image.os.sysprep_params[name]
+
+ while 1:
+ if param.type in ("file", "dir"):
+ if not title:
+ title = "Please select a %s to use for the `%s' parameter" % \
+ ('file' if param.type == 'file' else 'directory', name)
+ ftype = "br" if param.type == 'file' else 'd'
+
+ value = select_file(d, ftype=ftype, title=title)
+ if value is None:
+ return False
+ else:
+ if not title:
+ title = "Please provide a new value for configuration " \
+ "parameter: `%s'" % name
+ (code, answer) = d.inputbox(
+ title, width=WIDTH, init=str(param.value))
+
+ if code in (d.DIALOG_CANCEL, d.DIALOG_ESC):
+ return False
+
+ value = answer.strip()
+
+ if param.set_value(value) is False:
+ d.msgbox("Unable to update the value. Reason: %s" % param.error,
+ width=WIDTH)
+ param.error = None
+ continue
+ break
+
+ return True
+
# vim: set sta sts=4 shiftwidth=4 sw=4 et ai :
diff --git a/image_creator/dialog_wizard.py b/image_creator/dialog_wizard.py
index bdcc41746f7888097d878646739be9df30bd34d7..470eb76fc22b6fe4d36012d972523833664e784e 100644
--- a/image_creator/dialog_wizard.py
+++ b/image_creator/dialog_wizard.py
@@ -27,11 +27,10 @@ from image_creator.kamaki_wrapper import Kamaki, ClientError
from image_creator.util import MD5, FatalError
from image_creator.output.cli import OutputWthProgress
from image_creator.dialog_util import extract_image, update_background_title, \
- add_cloud, edit_cloud
+ add_cloud, edit_cloud, virtio_versions, update_sysprep_param
PAGE_WIDTH = 70
-PAGE_HEIGHT = 10
-SYSPREP_PARAM_MAXLEN = 20
+PAGE_HEIGHT = 12
class WizardExit(Exception):
@@ -128,6 +127,37 @@ class WizardPage(object):
raise NotImplementedError
+class WizardInfoPage(WizardPage):
+ """Represents a Wizard Page that just displays some user-defined
+ information.
+ """
+ def __init__(self, name, display_name, text, body, **kargs):
+ super(WizardInfoPage, self).__init__(name, display_name, text, **kargs)
+ self.body = body
+
+ def run(self, session, title):
+ d = session['dialog']
+ w = session['wizard']
+
+ extra_button = 1 if self.extra else 0
+ text = "%s\n\n%s" % (self.text, self.body())
+
+ ret = d.yesno(text, width=PAGE_WIDTH, ok_label="Next",
+ cancel="Back", extra_button=extra_button, title=title,
+ extra_label=self.extra_label, height=PAGE_HEIGHT)
+
+ if ret in (d.DIALOG_CANCEL, d.DIALOG_ESC):
+ return self.PREV
+ elif ret == d.DIALOG_EXTRA:
+ self.extra()
+ raise WizardReloadPage
+
+ # DIALOG_OK
+ w[self.name] = self.validate(None)
+ self.info = "%s: %s" % (self.display_name, self.display(w[self.name]))
+ return self.NEXT
+
+
class WizardPageWthChoices(WizardPage):
"""Represents a Wizard Page that allows the user to select something from
a list of choices.
@@ -316,6 +346,53 @@ def start_wizard(session):
title="Image Description", default=session['metadata']['DESCRIPTION']
if 'DESCRIPTION' in session['metadata'] else '')
+ # Create VirtIO Installation Page
+ def display_installed_drivers():
+ """Returnes the installed virtio drivers"""
+ versions = virtio_versions(image.os.virtio_state)
+
+ ret = "Installed Block Device Driver: %(netkvm)s\n" \
+ "Installed Network Device Driver: %(viostor)s\n" % versions
+
+ virtio = image.os.sysprep_params['virtio'].value
+ if virtio:
+ ret += "\nNew Block Device Driver: %(netkvm)s\n" \
+ "New Network Device Driver: %(viostor)s\n" % \
+ virtio_versions(image.os.compute_virtio_state(virtio))
+ return ret
+
+ def validate_virtio(_):
+ netkvm = len(image.os.virtio_state['netkvm']) != 0
+ viostor = len(image.os.virtio_state['viostor']) != 0
+ drv_dir = image.os.sysprep_params['virtio'].value
+
+ if netkvm is False or viostor is False:
+ new = image.os.compute_virtio_state(drv_dir) if drv_dir else None
+ new_viostor = len(new['viostor']) != 0 if new else False
+ new_netkvm = len(new['netkvm']) != 0 if new else False
+
+ d = session['dialog']
+ title = "VirtIO driver missing"
+ msg = "Image creation cannot proceed unless a VirtIO %s driver " \
+ "is installed on the media!"
+ if not (viostor or new_viostor):
+ d.msgbox(msg % "Block Device", width=PAGE_WIDTH,
+ height=PAGE_HEIGHT, title=title)
+ raise WizardReloadPage
+ if not(netkvm or new_netkvm):
+ d.msgbox(msg % "Network Device", width=PAGE_WIDTH,
+ height=PAGE_HEIGHT, title=title)
+ raise WizardReloadPage
+
+ return drv_dir
+
+ virtio = WizardInfoPage(
+ "virtio", "VirtIO Drivers Path",
+ "Press <New> to install new VirtIO drivers.",
+ display_installed_drivers, title="VirtIO Drivers", extra_label='New',
+ extra=lambda: update_sysprep_param(session, 'virtio'),
+ validate=validate_virtio)
+
# Create Image Registration Wizard Page
def registration_choices():
return [("Private", "Image is accessible only by this user"),
@@ -326,14 +403,16 @@ def start_wizard(session):
"Please provide a registration type:", registration_choices,
title="Registration Type", default="Private")
- w = Wizard(session)
+ wizard = Wizard(session)
- w.add_page(cloud)
- w.add_page(name)
- w.add_page(descr)
- w.add_page(registration)
+ wizard.add_page(cloud)
+ wizard.add_page(name)
+ wizard.add_page(descr)
+ if hasattr(image.os, 'install_virtio_drivers'):
+ wizard.add_page(virtio)
+ wizard.add_page(registration)
- if w.run():
+ if wizard.run():
create_image(session)
else:
return False
@@ -353,6 +432,9 @@ def create_image(session):
try:
out.clear()
+ if 'virtio' in wizard and image.os.sysprep_params['virtio'].value:
+ image.os.install_virtio_drivers()
+
# Sysprep
image.os.do_sysprep()
metadata = image.os.meta
diff --git a/image_creator/os_type/windows/__init__.py b/image_creator/os_type/windows/__init__.py
index 8796eadd01a079034b887a8c0c08a5d265ec56b6..8767cecf4525d07e403b5f40a98bd36f5d33ee12 100644
--- a/image_creator/os_type/windows/__init__.py
+++ b/image_creator/os_type/windows/__init__.py
@@ -274,7 +274,7 @@ class Windows(OSBase):
with self.mount(readonly=True, silent=True):
self.out.output("Checking media state ...", False)
self.sysprepped = self.registry.get_setup_state() > 0
- self.virtio_state = self._virtio_state()
+ self.virtio_state = self.compute_virtio_state()
arch = self.image.g.inspect_get_arch(self.root)
if arch == 'x86_64':
arch = 'amd64'
@@ -677,7 +677,7 @@ class Windows(OSBase):
raise FatalError("Connection to the Windows VM failed after %d retries"
% retries)
- def _virtio_state(self, directory=None):
+ def compute_virtio_state(self, directory=None):
"""Returns information about the VirtIO drivers found either in a
directory or the media itself if the directory is None.
"""
@@ -718,7 +718,7 @@ class Windows(OSBase):
"""Examines a directory for VirtIO drivers and returns only the drivers
that are suitable for this media.
"""
- collection = self._virtio_state(dirname)
+ collection = self.compute_virtio_state(dirname)
files = set([f.lower() for f in os.listdir(dirname)
if os.path.isfile(dirname + os.sep + f)])
@@ -906,7 +906,7 @@ class Windows(OSBase):
self.vm.stop(shutdown_timeout if booted else 1, fatal=False)
with self.mount(readonly=True, silent=True):
- self.virtio_state = self._virtio_state()
+ self.virtio_state = self.compute_virtio_state()
viostor_service_found = self.registry.check_viostor_service()
if not (len(self.virtio_state['viostor']) and viostor_service_found):