Revision 82e8c357

b/image_creator/dialog_menu.py
70 70

  
71 71
SYSPREP_PARAM_MAXLEN = 20
72 72

  
73

  
73 74
class MetadataMonitor(object):
74 75
    """Monitors image metadata chages"""
75 76
    def __init__(self, session, meta):
......
632 633
    if len(needed) == 0:
633 634
        return True
634 635

  
635
    fields = []
636
    for name in names:
637
        param = needed[name]
638
        default = available[name] if name in available else ""
639
        fields.append(("%s: " % param.description, default,
640
                       SYSPREP_PARAM_MAXLEN))
636
    while 1:
637
        fields = []
638
        for name in names:
639
            param = needed[name]
640
            default = str(available[name]) if name in available else ""
641
            fields.append(("%s: " % param.description, default,
642
                           SYSPREP_PARAM_MAXLEN))
641 643

  
642
    txt = "Please provide the following system preparation parameters:"
643
    code, output = d.form(txt, height=13, width=WIDTH, form_height=len(fields),
644
                          fields=fields)
644
        txt = "Please provide the following system preparation parameters:"
645
        code, output = d.form(txt, height=13, width=WIDTH,
646
                              form_height=len(fields), fields=fields)
645 647

  
646
    if code in (d.DIALOG_CANCEL, d.DIALOG_ESC):
647
        return False
648
        if code in (d.DIALOG_CANCEL, d.DIALOG_ESC):
649
            return False
648 650

  
649
    for i in range(len(fields)):
650
        param = needed[names[i]]
651
        try:
652
            value = param.type(output[i])
653
            if param.validate(value):
654
                image.os.sysprep_params[names[i]] = value
655
                continue
656
        except ValueError:
657
            pass
651
        def check_params():
652
            for i in range(len(fields)):
653
                param = needed[names[i]]
654
                try:
655
                    value = param.type(output[i])
656
                    if param.validate(value):
657
                        image.os.sysprep_params[names[i]] = value
658
                        continue
659
                except ValueError:
660
                    pass
661

  
662
                d.msgbox("Invalid value for parameter: `%s'" % names[i],
663
                         width=SMALL_WIDTH)
664
                return False
665
            return True
658 666

  
659
        d.msgbox("The value you provided for parameter: `%s' is not valid" %
660
                 names[i], width=SMALL_WIDTH)
661
        return False
667
        if check_params():
668
            break
662 669

  
663 670
    return True
664 671

  
b/image_creator/dialog_wizard.py
336 336

  
337 337
    # Create Sysprep Params Wizard Page
338 338
    needed = image.os.needed_sysprep_params
339
    param_names = needed.keys()
339
    # Only show the parameters that don't have default values
340
    param_names = [param for param in needed if needed[param].default is None]
340 341

  
341 342
    def sysprep_params_fields():
342 343
        fields = []
343 344
        available = image.os.sysprep_params
344 345
        for name in param_names:
345 346
            text = needed[name].description
346
            default = available[name] if name in available else ""
347
            default = str(available[name]) if name in available else ""
347 348
            fields.append(("%s: " % text, default, SYSPREP_PARAM_MAXLEN))
348 349
        return fields
349 350

  
......
359 360
                pass
360 361

  
361 362
            session['dialog'].msgbox("Invalid value for parameter `%s'" %
362
                                         param_names[i])
363
                                     param_names[i])
363 364
            raise WizardReloadPage
364 365
        return params
365 366

  
b/image_creator/os_type/__init__.py
62 62

  
63 63

  
64 64
def add_prefix(target):
65
    """Decorator that adds a prefix to the result of a function"""
65 66
    def wrapper(self, *args):
66 67
        prefix = args[0]
67 68
        return [prefix + path for path in target(self, *args)]
......
98 99
            init(self, *args, **kwargs)
99 100
            self.needed_sysprep_params[name] = \
100 101
                self.SysprepParam(type, default, descr, validate)
102
            if default is not None:
103
                self.sysprep_params[name] = default
101 104
        return inner
102 105
    return wrapper
103 106

  
b/image_creator/os_type/windows.py
50 50
import subprocess
51 51
import struct
52 52

  
53
BOOT_TIMEOUT = 300
54
SHUTDOWN_TIMEOUT = 120
55
CONNECTION_RETRIES = 5
56

  
57 53
# For more info see: http://technet.microsoft.com/en-us/library/jj612867.aspx
58 54
KMS_CLIENT_SETUP_KEYS = {
59 55
    "Windows 8 Professional": "NG4HW-VH26C-733KW-K6F98-J8CK4",
......
104 100
    "Windows Server 2008 for Itanium-Based Systems":
105 101
    "4DWFP-JF3DJ-B7DTH-78FJB-PDRHK"}
106 102

  
103
_POSINT = lambda x: type(x) == int and x >= 0
104

  
107 105

  
108 106
class Windows(OSBase):
109 107
    """OS class for Windows"""
110

  
108
    @add_sysprep_param(
109
        'shutdown_timeout', int, 120, "Shutdown Timeout (seconds)", _POSINT)
110
    @add_sysprep_param(
111
        'boot_timeout', int, 300, "Boot Timeout (seconds)", _POSINT)
112
    @add_sysprep_param(
113
        'connection_retries', int, 5, "Connection Retries", _POSINT)
111 114
    @add_sysprep_param('password', str, None, 'Image Administrator Password')
112 115
    def __init__(self, image, **kargs):
113 116
        super(Windows, self).__init__(image, **kargs)
......
311 314
            self.out.output("Starting windows VM ...", False)
312 315
            monitorfd, monitor = tempfile.mkstemp()
313 316
            os.close(monitorfd)
314
            vm = _VM(self.image.device, monitor)
317
            vm = _VM(self.image.device, monitor, self.sysprep_params)
315 318
            self.out.success("started (console on vnc display: %d)." %
316 319
                             vm.display)
317 320

  
......
362 365
            self.out.success("done")
363 366

  
364 367
            self.out.output("Waiting for windows to shut down ...", False)
365
            vm.wait(SHUTDOWN_TIMEOUT)
368
            vm.wait(self.sysprep_params['shutdown_timeout'])
366 369
            self.out.success("done")
367 370
        finally:
368 371
            if monitor is not None:
......
395 398
    def _wait_vm_boot(self, vm, fname, msg):
396 399
        """Wait until a message appears on a file or the vm process dies"""
397 400

  
398
        for _ in range(BOOT_TIMEOUT):
401
        for _ in range(self.sysprep_params['boot_timeout']):
399 402
            time.sleep(1)
400 403
            with open(fname) as f:
401 404
                for line in f:
......
685 688
    def _check_connectivity(self):
686 689
        """Check if winexe works on the Windows VM"""
687 690

  
691
        retries = self.sysprep_params['connection_retries']
692
        # If the connection_retries parameter is set to 0 disable the
693
        # connectivity check
694
        if retries == 0:
695
            return True
696

  
688 697
        passwd = self.sysprep_params['password']
689 698
        winexe = WinEXE('Administrator', passwd, 'localhost')
690 699
        winexe.uninstall().debug(9)
691 700

  
692
        for i in range(CONNECTION_RETRIES):
701
        for i in range(retries):
693 702
            (stdout, stderr, rc) = winexe.run('cmd /C')
694 703
            if rc == 0:
695 704
                return True
......
699 708
            finally:
700 709
                log.close()
701 710
            self.out.output("failed! See: `%s' for the full output" % log.name)
702
            if i < CONNECTION_RETRIES - 1:
703
                self.out.output("Retrying ...", False)
704
        raise FatalError("Connection to the VM failed after %d retries" %
705
                         CONNECTION_RETRIES)
711
            if i < retries - 1:
712
                self.out.output("retrying ...", False)
713

  
714
        raise FatalError("Connection to the Windows VM failed after %d retries"
715
                         % retries)
706 716

  
707 717
    def _guest_exec(self, command, fatal=True):
708 718
        """Execute a command on a windows VM"""
......
729 739

  
730 740
class _VM(object):
731 741
    """Windows Virtual Machine"""
732
    def __init__(self, disk, serial):
742
    def __init__(self, disk, serial, params):
733 743
        """Create _VM instance
734 744

  
735 745
            disk: VM's hard disk
......
738 748

  
739 749
        self.disk = disk
740 750
        self.serial = serial
751
        self.params = params
741 752

  
742 753
        def random_mac():
743 754
            """creates a random mac address"""
......
782 793

  
783 794
        signal.signal(signal.SIGALRM, handler)
784 795

  
785
        signal.alarm(SHUTDOWN_TIMEOUT)
796
        signal.alarm(self.params['shutdown_timeout'])
786 797
        self.process.communicate(input="system_powerdown\n")
787 798
        signal.alarm(0)
788 799

  

Also available in: Unified diff