Commit c12f530c authored by Nikos Skalkotos's avatar Nikos Skalkotos

Add a wizard page for the VirtIO drivers

Add a page in the dialog wizard that displays the current state of
the VirtIO drivers of the image and allow the user to update the
installed VirtIO drivers. This page will only be shown if the media
hosts a Windows image.
parent 533af7d9
......@@ -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(
......
......@@ -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 :
......@@ -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
......
......@@ -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):
......
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