From: Nikos Skalkotos Date: Mon, 29 Jul 2013 14:23:02 +0000 (+0300) Subject: In windows.py turn some constants to syspep params X-Git-Tag: 0.5~1^2~13^2~2 X-Git-Url: https://code.grnet.gr/git/snf-image-creator/commitdiff_plain/82e8c3578c649bb302fe8c8cf8b3986778654c1a In windows.py turn some constants to syspep params Remove constants BOOT_TIMEOUT, SHUTDOWN_TIMEOUT and CONNECTION_RETRIES and add then as sysprep_parameters --- diff --git a/image_creator/dialog_menu.py b/image_creator/dialog_menu.py index d14925f..4d913cb 100644 --- a/image_creator/dialog_menu.py +++ b/image_creator/dialog_menu.py @@ -70,6 +70,7 @@ CONFIGURATION_TASKS = [ SYSPREP_PARAM_MAXLEN = 20 + class MetadataMonitor(object): """Monitors image metadata chages""" def __init__(self, session, meta): @@ -632,33 +633,39 @@ def sysprep_params(session): if len(needed) == 0: return True - fields = [] - for name in names: - param = needed[name] - default = available[name] if name in available else "" - fields.append(("%s: " % param.description, default, - SYSPREP_PARAM_MAXLEN)) + while 1: + fields = [] + for name in names: + param = needed[name] + default = str(available[name]) if name in available else "" + fields.append(("%s: " % param.description, default, + SYSPREP_PARAM_MAXLEN)) - txt = "Please provide the following system preparation parameters:" - code, output = d.form(txt, height=13, width=WIDTH, form_height=len(fields), - fields=fields) + txt = "Please provide the following system preparation parameters:" + code, output = d.form(txt, height=13, width=WIDTH, + form_height=len(fields), fields=fields) - if code in (d.DIALOG_CANCEL, d.DIALOG_ESC): - return False + if code in (d.DIALOG_CANCEL, d.DIALOG_ESC): + return False - for i in range(len(fields)): - param = needed[names[i]] - try: - value = param.type(output[i]) - if param.validate(value): - image.os.sysprep_params[names[i]] = value - continue - except ValueError: - pass + def check_params(): + for i in range(len(fields)): + param = needed[names[i]] + try: + value = param.type(output[i]) + if param.validate(value): + image.os.sysprep_params[names[i]] = value + continue + except ValueError: + pass + + d.msgbox("Invalid value for parameter: `%s'" % names[i], + width=SMALL_WIDTH) + return False + return True - d.msgbox("The value you provided for parameter: `%s' is not valid" % - names[i], width=SMALL_WIDTH) - return False + if check_params(): + break return True diff --git a/image_creator/dialog_wizard.py b/image_creator/dialog_wizard.py index c737e51..0856d8a 100644 --- a/image_creator/dialog_wizard.py +++ b/image_creator/dialog_wizard.py @@ -336,14 +336,15 @@ def start_wizard(session): # Create Sysprep Params Wizard Page needed = image.os.needed_sysprep_params - param_names = needed.keys() + # Only show the parameters that don't have default values + param_names = [param for param in needed if needed[param].default is None] def sysprep_params_fields(): fields = [] available = image.os.sysprep_params for name in param_names: text = needed[name].description - default = available[name] if name in available else "" + default = str(available[name]) if name in available else "" fields.append(("%s: " % text, default, SYSPREP_PARAM_MAXLEN)) return fields @@ -359,7 +360,7 @@ def start_wizard(session): pass session['dialog'].msgbox("Invalid value for parameter `%s'" % - param_names[i]) + param_names[i]) raise WizardReloadPage return params diff --git a/image_creator/os_type/__init__.py b/image_creator/os_type/__init__.py index 6cecbb9..69e45d9 100644 --- a/image_creator/os_type/__init__.py +++ b/image_creator/os_type/__init__.py @@ -62,6 +62,7 @@ def os_cls(distro, osfamily): def add_prefix(target): + """Decorator that adds a prefix to the result of a function""" def wrapper(self, *args): prefix = args[0] return [prefix + path for path in target(self, *args)] @@ -98,6 +99,8 @@ def add_sysprep_param(name, type, default, descr, validate=lambda x: True): init(self, *args, **kwargs) self.needed_sysprep_params[name] = \ self.SysprepParam(type, default, descr, validate) + if default is not None: + self.sysprep_params[name] = default return inner return wrapper diff --git a/image_creator/os_type/windows.py b/image_creator/os_type/windows.py index 58d98c8..20029a3 100644 --- a/image_creator/os_type/windows.py +++ b/image_creator/os_type/windows.py @@ -50,10 +50,6 @@ import string import subprocess import struct -BOOT_TIMEOUT = 300 -SHUTDOWN_TIMEOUT = 120 -CONNECTION_RETRIES = 5 - # For more info see: http://technet.microsoft.com/en-us/library/jj612867.aspx KMS_CLIENT_SETUP_KEYS = { "Windows 8 Professional": "NG4HW-VH26C-733KW-K6F98-J8CK4", @@ -104,10 +100,17 @@ KMS_CLIENT_SETUP_KEYS = { "Windows Server 2008 for Itanium-Based Systems": "4DWFP-JF3DJ-B7DTH-78FJB-PDRHK"} +_POSINT = lambda x: type(x) == int and x >= 0 + class Windows(OSBase): """OS class for Windows""" - + @add_sysprep_param( + 'shutdown_timeout', int, 120, "Shutdown Timeout (seconds)", _POSINT) + @add_sysprep_param( + 'boot_timeout', int, 300, "Boot Timeout (seconds)", _POSINT) + @add_sysprep_param( + 'connection_retries', int, 5, "Connection Retries", _POSINT) @add_sysprep_param('password', str, None, 'Image Administrator Password') def __init__(self, image, **kargs): super(Windows, self).__init__(image, **kargs) @@ -311,7 +314,7 @@ class Windows(OSBase): self.out.output("Starting windows VM ...", False) monitorfd, monitor = tempfile.mkstemp() os.close(monitorfd) - vm = _VM(self.image.device, monitor) + vm = _VM(self.image.device, monitor, self.sysprep_params) self.out.success("started (console on vnc display: %d)." % vm.display) @@ -362,7 +365,7 @@ class Windows(OSBase): self.out.success("done") self.out.output("Waiting for windows to shut down ...", False) - vm.wait(SHUTDOWN_TIMEOUT) + vm.wait(self.sysprep_params['shutdown_timeout']) self.out.success("done") finally: if monitor is not None: @@ -395,7 +398,7 @@ class Windows(OSBase): def _wait_vm_boot(self, vm, fname, msg): """Wait until a message appears on a file or the vm process dies""" - for _ in range(BOOT_TIMEOUT): + for _ in range(self.sysprep_params['boot_timeout']): time.sleep(1) with open(fname) as f: for line in f: @@ -685,11 +688,17 @@ class Windows(OSBase): def _check_connectivity(self): """Check if winexe works on the Windows VM""" + retries = self.sysprep_params['connection_retries'] + # If the connection_retries parameter is set to 0 disable the + # connectivity check + if retries == 0: + return True + passwd = self.sysprep_params['password'] winexe = WinEXE('Administrator', passwd, 'localhost') winexe.uninstall().debug(9) - for i in range(CONNECTION_RETRIES): + for i in range(retries): (stdout, stderr, rc) = winexe.run('cmd /C') if rc == 0: return True @@ -699,10 +708,11 @@ class Windows(OSBase): finally: log.close() self.out.output("failed! See: `%s' for the full output" % log.name) - if i < CONNECTION_RETRIES - 1: - self.out.output("Retrying ...", False) - raise FatalError("Connection to the VM failed after %d retries" % - CONNECTION_RETRIES) + if i < retries - 1: + self.out.output("retrying ...", False) + + raise FatalError("Connection to the Windows VM failed after %d retries" + % retries) def _guest_exec(self, command, fatal=True): """Execute a command on a windows VM""" @@ -729,7 +739,7 @@ class Windows(OSBase): class _VM(object): """Windows Virtual Machine""" - def __init__(self, disk, serial): + def __init__(self, disk, serial, params): """Create _VM instance disk: VM's hard disk @@ -738,6 +748,7 @@ class _VM(object): self.disk = disk self.serial = serial + self.params = params def random_mac(): """creates a random mac address""" @@ -782,7 +793,7 @@ class _VM(object): signal.signal(signal.SIGALRM, handler) - signal.alarm(SHUTDOWN_TIMEOUT) + signal.alarm(self.params['shutdown_timeout']) self.process.communicate(input="system_powerdown\n") signal.alarm(0)