Revision 47505e53 image_creator/os_type/windows.py
b/image_creator/os_type/windows.py | ||
---|---|---|
37 | 37 |
Windows OSs.""" |
38 | 38 |
|
39 | 39 |
from image_creator.os_type import OSBase, sysprep, add_sysprep_param |
40 |
from image_creator.util import FatalError, check_guestfs_version, get_command
|
|
40 |
from image_creator.util import FatalError, check_guestfs_version |
|
41 | 41 |
from image_creator.winexe import WinEXE, WinexeTimeout |
42 | 42 |
|
43 | 43 |
import hivex |
... | ... | |
108 | 108 |
class Windows(OSBase): |
109 | 109 |
"""OS class for Windows""" |
110 | 110 |
|
111 |
@add_sysprep_param('password', 'Image Administrator Password', 20)
|
|
111 |
@add_sysprep_param('password', None, 'Image Administrator Password')
|
|
112 | 112 |
def __init__(self, image, **kargs): |
113 | 113 |
super(Windows, self).__init__(image, **kargs) |
114 | 114 |
|
... | ... | |
127 | 127 |
assert self.system_drive |
128 | 128 |
|
129 | 129 |
self.product_name = self.g.inspect_get_product_name(self.root) |
130 |
self.syspreped = False |
|
130 | 131 |
|
131 | 132 |
@sysprep('Disabling IPv6 privacy extensions') |
132 | 133 |
def disable_ipv6_privacy_extensions(self): |
... | ... | |
202 | 203 |
return |
203 | 204 |
|
204 | 205 |
self._guest_exec( |
205 |
"cscript \Windows\system32\slmgr.vbs /ipk %s" % setup_key) |
|
206 |
r"cscript \Windows\system32\slmgr.vbs /ipk %s" % setup_key)
|
|
206 | 207 |
|
207 | 208 |
@sysprep('Shrinking the last filesystem') |
208 | 209 |
def shrink(self): |
... | ... | |
273 | 274 |
raise FatalError("Image is already syspreped!") |
274 | 275 |
|
275 | 276 |
txt = "System preparation parameter: `%s' is needed but missing!" |
276 |
for param in self.needed_sysprep_params:
|
|
277 |
if param not in self.sysprep_params:
|
|
277 |
for name, param in self.needed_sysprep_params.items():
|
|
278 |
if name not in self.sysprep_params:
|
|
278 | 279 |
raise FatalError(txt % param) |
279 | 280 |
|
280 | 281 |
self.mount(readonly=False) |
... | ... | |
298 | 299 |
# guestfs_shutdown which is the prefered way to shutdown the backend |
299 | 300 |
# process was introduced in version 1.19.16 |
300 | 301 |
if check_guestfs_version(self.g, 1, 19, 16) >= 0: |
301 |
ret = self.g.shutdown()
|
|
302 |
self.g.shutdown() |
|
302 | 303 |
else: |
303 |
ret = self.g.kill_subprocess()
|
|
304 |
self.g.kill_subprocess() |
|
304 | 305 |
|
305 | 306 |
self.out.success('done') |
306 | 307 |
|
... | ... | |
329 | 330 |
self.out.output('Preparing system for image creation:') |
330 | 331 |
|
331 | 332 |
tasks = self.list_syspreps() |
332 |
enabled = filter(lambda x: x.enabled, tasks)
|
|
333 |
enabled = [task for task in tasks if task.enabled]
|
|
333 | 334 |
size = len(enabled) |
334 | 335 |
|
335 | 336 |
# Make sure shrink runs in the end, before ms sysprep |
336 |
enabled = filter(lambda x: self.sysprep_info(x).name != 'shrink',
|
|
337 |
enabled)
|
|
337 |
enabled = [task for task in enabled if
|
|
338 |
self.sysprep_info(task).name != 'shrink']
|
|
338 | 339 |
|
339 |
shrink_enabled = False |
|
340 | 340 |
if len(enabled) != size: |
341 | 341 |
enabled.append(self.shrink) |
342 |
shrink_enabled = True |
|
343 | 342 |
|
344 | 343 |
# Make sure the ms sysprep is the last task to run if it is enabled |
345 |
enabled = filter( |
|
346 |
lambda x: self.sysprep_info(x).name != 'microsoft-sysprep', |
|
347 |
enabled) |
|
344 |
enabled = [task for task in enabled if |
|
345 |
self.sysprep_info(task).name != 'microsoft-sysprep'] |
|
348 | 346 |
|
349 | 347 |
ms_sysprep_enabled = False |
350 | 348 |
if len(enabled) != size: |
... | ... | |
397 | 395 |
def _wait_vm_boot(self, vm, fname, msg): |
398 | 396 |
"""Wait until a message appears on a file or the vm process dies""" |
399 | 397 |
|
400 |
for i in range(BOOT_TIMEOUT):
|
|
398 |
for _ in range(BOOT_TIMEOUT):
|
|
401 | 399 |
time.sleep(1) |
402 | 400 |
with open(fname) as f: |
403 | 401 |
for line in f: |
... | ... | |
425 | 423 |
path = "%s/system32/config/%s" % (systemroot, regfile) |
426 | 424 |
try: |
427 | 425 |
path = self.g.case_sensitive_path(path) |
428 |
except RuntimeError as e: |
|
426 |
except RuntimeError as error:
|
|
429 | 427 |
raise FatalError("Unable to retrieve registry file: %s. Reason: %s" |
430 |
% (regfile, str(e))) |
|
428 |
% (regfile, str(error)))
|
|
431 | 429 |
return path |
432 | 430 |
|
433 | 431 |
def _enable_os_monitor(self): |
... | ... | |
634 | 632 |
|
635 | 633 |
def _get_users(self): |
636 | 634 |
"""Returns a list of users found in the images""" |
637 |
path = self._registry_file_path('SAM') |
|
638 | 635 |
samfd, sam = tempfile.mkstemp() |
639 | 636 |
try: |
640 | 637 |
os.close(samfd) |
641 |
self.g.download(path, sam)
|
|
638 |
self.g.download(self._registry_file_path('SAM'), sam)
|
|
642 | 639 |
|
643 | 640 |
h = hivex.Hivex(sam) |
644 | 641 |
|
... | ... | |
701 | 698 |
log.file.write(stdout) |
702 | 699 |
finally: |
703 | 700 |
log.close() |
704 |
self.out.output("failed! See: `%' for the full output" % log.name) |
|
701 |
self.out.output("failed! See: `%s' for the full output" % log.name)
|
|
705 | 702 |
if i < CONNECTION_RETRIES - 1: |
706 | 703 |
self.out.output("Retrying ...", False) |
707 | 704 |
raise FatalError("Connection to the VM failed after %d retries" % |
... | ... | |
743 | 740 |
self.serial = serial |
744 | 741 |
|
745 | 742 |
def random_mac(): |
743 |
"""creates a random mac address""" |
|
746 | 744 |
mac = [0x00, 0x16, 0x3e, |
747 | 745 |
random.randint(0x00, 0x7f), |
748 | 746 |
random.randint(0x00, 0xff), |
749 | 747 |
random.randint(0x00, 0xff)] |
750 | 748 |
|
751 |
return ':'.join(map(lambda x: "%02x" % x, mac))
|
|
749 |
return ':'.join(['%02x' % x for x in mac])
|
|
752 | 750 |
|
753 | 751 |
# Use ganeti's VNC port range for a random vnc port |
754 | 752 |
self.display = random.randint(11000, 14999) - 5900 |
... | ... | |
780 | 778 |
if self.isalive(): |
781 | 779 |
self.process.kill() |
782 | 780 |
self.process.wait() |
783 |
self.out.output("timed-out") |
|
784 | 781 |
raise FatalError("VM destroy timed-out") |
785 | 782 |
|
786 | 783 |
signal.signal(signal.SIGALRM, handler) |
Also available in: Unified diff