# interpreted as representing official policies, either expressed
# or implied, of GRNET S.A.
-import dialog
import time
import StringIO
class WizardExit(Exception):
+ """Exception used to exit the wizard"""
pass
class WizardInvalidData(Exception):
+ """Exception triggered when the user provided data are invalid"""
pass
class Wizard:
+ """Represents a dialog-based wizard
+
+ The wizard is a collection of pages that have a "Next" and a "Back" button
+ on them. The pages are used to collect user data.
+ """
+
def __init__(self, session):
self.session = session
self.pages = []
self.d = session['dialog']
def add_page(self, page):
+ """Add a new page to the wizard"""
self.pages.append(page)
def run(self):
+ """Run the wizard"""
idx = 0
while True:
try:
msg = "All necessary information has been gathered:\n\n"
for page in self.pages:
msg += " * %s\n" % page.info
- msg += "\nConfirm and Proceed."
+ msg += "\nContinue with the image creation process?"
ret = self.d.yesno(
- msg, width=PAGE_WIDTH, height=12, ok_label="Yes",
- cancel="Back", extra_button=1, extra_label="Quit",
- title="Confirmation")
+ msg, width=PAGE_WIDTH, height=8 + len(self.pages),
+ ok_label="Yes", cancel="Back", extra_button=1,
+ extra_label="Quit", title="Confirmation")
if ret == self.d.DIALOG_CANCEL:
idx -= 1
class WizardPage(object):
+ """Represents a page in a wizard"""
NEXT = 1
PREV = -1
def __init__(self, **kargs):
- if 'validate' in kargs:
- validate = kargs['validate']
- else:
- validate = lambda x: x
+ validate = kargs['validate'] if 'validate' in kargs else lambda x: x
setattr(self, "validate", validate)
- if 'display' in kargs:
- display = kargs['display']
- else:
- display = lambda x: x
+ display = kargs['display'] if 'display' in kargs else lambda x: x
setattr(self, "display", display)
def run(self, session, index, total):
+ """Display this wizard page
+
+ This function is used by the wizard program when accessing a page.
+ """
raise NotImplementedError
class WizardRadioListPage(WizardPage):
-
+ """Represent a Radio List in a wizard"""
def __init__(self, name, printable, message, choices, **kargs):
super(WizardRadioListPage, self).__init__(**kargs)
self.name = name
class WizardInputPage(WizardPage):
-
+ """Represents an input field in a wizard"""
def __init__(self, name, printable, message, **kargs):
super(WizardInputPage, self).__init__(**kargs)
self.name = name
self.printable = printable
self.message = message
+ self.info = "%s: <none>" % self.printable
self.title = kargs['title'] if 'title' in kargs else ''
self.init = kargs['init'] if 'init' in kargs else ''
return self.NEXT
-def wizard(session):
-
+def start_wizard(session):
+ """Run the image creation wizard"""
init_token = Kamaki.get_token()
if init_token is None:
init_token = ""
name = WizardInputPage(
"ImageName", "Image Name", "Please provide a name for the image:",
- title="Image Name", init=session['device'].distro)
+ title="Image Name", init=session['image'].distro)
descr = WizardInputPage(
"ImageDescription", "Image Description",
title="Registration Type", default="Private")
def validate_account(token):
+ """Check if a token is valid"""
+ d = session['dialog']
+
if len(token) == 0:
d.msgbox("The token cannot be empty", width=PAGE_WIDTH)
raise WizardInvalidData
account = Kamaki.get_account(token)
if account is None:
- session['dialog'].msgbox("The token you provided in not valid!",
- width=PAGE_WIDTH)
+ d.msgbox("The token you provided in not valid!", width=PAGE_WIDTH)
raise WizardInvalidData
return account
def create_image(session):
+ """Create an image using the information collected by the wizard"""
d = session['dialog']
- disk = session['disk']
- device = session['device']
- snapshot = session['snapshot']
- image_os = session['image_os']
+ image = session['image']
wizard = session['wizard']
# Save Kamaki credentials
Kamaki.save_token(wizard['Account']['auth_token'])
with_progress = OutputWthProgress(True)
- out = disk.out
+ out = image.out
out.add(with_progress)
try:
out.clear()
#Sysprep
- device.mount(False)
- image_os.do_sysprep()
- metadata = image_os.meta
- device.umount()
+ image.mount(False)
+ image.os.do_sysprep()
+ metadata = image.os.meta
+ image.umount()
#Shrink
- size = device.shrink()
+ size = image.shrink()
session['shrinked'] = True
update_background_title(session)
- metadata.update(device.meta)
+ metadata.update(image.meta)
metadata['DESCRIPTION'] = wizard['ImageDescription']
#MD5
md5 = MD5(out)
- session['checksum'] = md5.compute(snapshot, size)
+ session['checksum'] = md5.compute(image.device, size)
#Metadata
metastring = '\n'.join(
name = "%s-%s.diskdump" % (wizard['ImageName'],
time.strftime("%Y%m%d%H%M"))
pithos_file = ""
- with open(snapshot, 'rb') as f:
+ with open(image.device, 'rb') as f:
pithos_file = kamaki.upload(f, size, name,
"(1/4) Calculating block hashes",
"(2/4) Uploading missing blocks")