Updated windows_setup.py

This commit is contained in:
2Shirt 2018-12-27 20:14:29 -07:00
parent fa424a4576
commit ec0341027e
Signed by: 2Shirt
GPG key ID: 152FAC923B0E132C

View file

@ -5,234 +5,236 @@ from functions.disk import *
# STATIC VARIABLES # STATIC VARIABLES
WINDOWS_VERSIONS = [ WINDOWS_VERSIONS = [
{'Name': 'Windows 7 Home Basic', {'Name': 'Windows 7 Home Basic',
'Image File': 'Win7', 'Image File': 'Win7',
'Image Name': 'Windows 7 HOMEBASIC'}, 'Image Name': 'Windows 7 HOMEBASIC'},
{'Name': 'Windows 7 Home Premium', {'Name': 'Windows 7 Home Premium',
'Image File': 'Win7', 'Image File': 'Win7',
'Image Name': 'Windows 7 HOMEPREMIUM'}, 'Image Name': 'Windows 7 HOMEPREMIUM'},
{'Name': 'Windows 7 Professional', {'Name': 'Windows 7 Professional',
'Image File': 'Win7', 'Image File': 'Win7',
'Image Name': 'Windows 7 PROFESSIONAL'}, 'Image Name': 'Windows 7 PROFESSIONAL'},
{'Name': 'Windows 7 Ultimate', {'Name': 'Windows 7 Ultimate',
'Image File': 'Win7', 'Image File': 'Win7',
'Image Name': 'Windows 7 ULTIMATE'}, 'Image Name': 'Windows 7 ULTIMATE'},
{'Name': 'Windows 8.1', {'Name': 'Windows 8.1',
'Image File': 'Win8', 'Image File': 'Win8',
'Image Name': 'Windows 8.1', 'Image Name': 'Windows 8.1',
'CRLF': True}, 'CRLF': True},
{'Name': 'Windows 8.1 Pro', {'Name': 'Windows 8.1 Pro',
'Image File': 'Win8', 'Image File': 'Win8',
'Image Name': 'Windows 8.1 Pro'}, 'Image Name': 'Windows 8.1 Pro'},
{'Name': 'Windows 10 Home', {'Name': 'Windows 10 Home',
'Image File': 'Win10', 'Image File': 'Win10',
'Image Name': 'Windows 10 Home', 'Image Name': 'Windows 10 Home',
'CRLF': True}, 'CRLF': True},
{'Name': 'Windows 10 Pro', {'Name': 'Windows 10 Pro',
'Image File': 'Win10', 'Image File': 'Win10',
'Image Name': 'Windows 10 Pro'}, 'Image Name': 'Windows 10 Pro'},
] ]
def find_windows_image(windows_version): def find_windows_image(windows_version):
"""Search for a Windows source image file, returns dict. """Search for a Windows source image file, returns dict.
Searches on local disks and then the WINDOWS_SERVER share.""" Searches on local disks and then the WINDOWS_SERVER share."""
image = {} image = {}
imagefile = windows_version['Image File'] imagefile = windows_version['Image File']
imagename = windows_version['Image Name'] imagename = windows_version['Image Name']
# Search local source # Search local source
set_thread_error_mode(silent=True) # Prevents "No disk" popups set_thread_error_mode(silent=True) # Prevents "No disk" popups
for d in psutil.disk_partitions(): for d in psutil.disk_partitions():
for ext in ['esd', 'wim', 'swm']: for ext in ['esd', 'wim', 'swm']:
path = '{}images\{}.{}'.format(d.mountpoint, imagefile, ext) path = '{}images\{}.{}'.format(d.mountpoint, imagefile, ext)
if os.path.isfile(path) and wim_contains_image(path, imagename): if os.path.isfile(path) and wim_contains_image(path, imagename):
image['Path'] = path image['Path'] = path
image['Letter'] = d.mountpoint[:1].upper() image['Letter'] = d.mountpoint[:1].upper()
image['Local'] = True image['Local'] = True
if ext == 'swm': if ext == 'swm':
image['Glob'] = '--ref="{}*.swm"'.format(image['Path'][:-4]) image['Glob'] = '--ref="{}*.swm"'.format(image['Path'][:-4])
break break
set_thread_error_mode(silent=False) # Return to normal set_thread_error_mode(silent=False) # Return to normal
# Check for network source # Check for network source
if not image: if not image:
mount_windows_share() mount_windows_share()
if WINDOWS_SERVER['Mounted']: if WINDOWS_SERVER['Mounted']:
for ext in ['esd', 'wim', 'swm']: for ext in ['esd', 'wim', 'swm']:
path = r'\\{}\{}\images\{}.{}'.format( path = r'\\{}\{}\images\{}.{}'.format(
WINDOWS_SERVER['IP'], WINDOWS_SERVER['IP'],
WINDOWS_SERVER['Share'], WINDOWS_SERVER['Share'],
imagefile, imagefile,
ext) ext)
if os.path.isfile(path) and wim_contains_image(path, imagename): if os.path.isfile(path) and wim_contains_image(path, imagename):
image['Path'] = path image['Path'] = path
image['Letter'] = None image['Letter'] = None
image['Local'] = False image['Local'] = False
if ext == 'swm': if ext == 'swm':
image['Glob'] = '--ref="{}*.swm"'.format( image['Glob'] = '--ref="{}*.swm"'.format(
image['Path'][:-4]) image['Path'][:-4])
break break
# Display image to be used (if any) and return # Display image to be used (if any) and return
if image: if image:
print_info('Using image: {}'.format(image['Path'])) print_info('Using image: {}'.format(image['Path']))
return image return image
else: else:
print_error('Failed to find Windows source image for {}'.format( print_error('Failed to find Windows source image for {}'.format(
windows_version['Name'])) windows_version['Name']))
raise GenericAbort raise GenericAbort
def format_disk(disk, use_gpt): def format_disk(disk, use_gpt):
"""Format disk for use as a Windows OS disk.""" """Format disk for use as a Windows OS disk."""
if use_gpt: if use_gpt:
format_gpt(disk) format_gpt(disk)
else: else:
format_mbr(disk) format_mbr(disk)
def format_gpt(disk): def format_gpt(disk):
"""Format disk for use as a Windows OS disk using the GPT layout.""" """Format disk for use as a Windows OS disk using the GPT layout."""
script = [ script = [
# Partition table # Partition table
'select disk {}'.format(disk['Number']), 'select disk {}'.format(disk['Number']),
'clean', 'clean',
'convert gpt', 'convert gpt',
# System partition # System partition
# NOTE: ESP needs to be >= 260 for Advanced Format 4K disks # NOTE: ESP needs to be >= 260 for Advanced Format 4K disks
'create partition efi size=500', 'create partition efi size=500',
'format quick fs=fat32 label="System"', 'format quick fs=fat32 label="System"',
'assign letter="S"', 'assign letter="S"',
# Microsoft Reserved (MSR) partition # Microsoft Reserved (MSR) partition
'create partition msr size=128', 'create partition msr size=128',
# Windows partition # Windows partition
'create partition primary', 'create partition primary',
'format quick fs=ntfs label="Windows"', 'format quick fs=ntfs label="Windows"',
'assign letter="W"', 'assign letter="W"',
# Recovery Tools partition # Recovery Tools partition
'shrink minimum=500', 'shrink minimum=500',
'create partition primary', 'create partition primary',
'format quick fs=ntfs label="Recovery Tools"', 'format quick fs=ntfs label="Recovery Tools"',
'assign letter="T"', 'assign letter="T"',
'set id="de94bba4-06d1-4d40-a16a-bfd50179d6ac"', 'set id="de94bba4-06d1-4d40-a16a-bfd50179d6ac"',
'gpt attributes=0x8000000000000001', 'gpt attributes=0x8000000000000001',
] ]
# Run # Run
run_diskpart(script) run_diskpart(script)
def format_mbr(disk): def format_mbr(disk):
"""Format disk for use as a Windows OS disk using the MBR layout.""" """Format disk for use as a Windows OS disk using the MBR layout."""
script = [ script = [
# Partition table # Partition table
'select disk {}'.format(disk['Number']), 'select disk {}'.format(disk['Number']),
'clean', 'clean',
# System partition # System partition
'create partition primary size=100', 'create partition primary size=100',
'format fs=ntfs quick label="System Reserved"', 'format fs=ntfs quick label="System Reserved"',
'active', 'active',
'assign letter="S"', 'assign letter="S"',
# Windows partition # Windows partition
'create partition primary', 'create partition primary',
'format fs=ntfs quick label="Windows"', 'format fs=ntfs quick label="Windows"',
'assign letter="W"', 'assign letter="W"',
# Recovery Tools partition # Recovery Tools partition
'shrink minimum=500', 'shrink minimum=500',
'create partition primary', 'create partition primary',
'format quick fs=ntfs label="Recovery"', 'format quick fs=ntfs label="Recovery"',
'assign letter="T"', 'assign letter="T"',
'set id=27', 'set id=27',
] ]
# Run # Run
run_diskpart(script) run_diskpart(script)
def mount_windows_share(): def mount_windows_share():
"""Mount the Windows images share unless labeled as already mounted.""" """Mount the Windows images share unless labeled as already mounted."""
if not WINDOWS_SERVER['Mounted']: if not WINDOWS_SERVER['Mounted']:
# Mounting read-write in case a backup was done in the same session # Mounting read-write in case a backup was done in the same session
# and the server was left mounted read-write. This avoids throwing an # and the server was left mounted read-write. This avoids throwing an
# error by trying to mount the same server with multiple credentials. # error by trying to mount the same server with multiple credentials.
mount_network_share(WINDOWS_SERVER, read_write=True) mount_network_share(WINDOWS_SERVER, read_write=True)
def select_windows_version(): def select_windows_version():
"""Select Windows version from a menu, returns dict.""" """Select Windows version from a menu, returns dict."""
actions = [ actions = [
{'Name': 'Main Menu', 'Letter': 'M'}, {'Name': 'Main Menu', 'Letter': 'M'},
] ]
# Menu loop # Menu loop
selection = menu_select( selection = menu_select(
title = 'Which version of Windows are we installing?', title = 'Which version of Windows are we installing?',
main_entries = WINDOWS_VERSIONS, main_entries = WINDOWS_VERSIONS,
action_entries = actions) action_entries = actions)
if selection.isnumeric(): if selection.isnumeric():
return WINDOWS_VERSIONS[int(selection)-1] return WINDOWS_VERSIONS[int(selection)-1]
elif selection == 'M': elif selection == 'M':
raise GenericAbort raise GenericAbort
def setup_windows(windows_image, windows_version): def setup_windows(windows_image, windows_version):
"""Apply a Windows image to W:""" """Apply a Windows image to W:"""
cmd = [ cmd = [
global_vars['Tools']['wimlib-imagex'], global_vars['Tools']['wimlib-imagex'],
'apply', 'apply',
windows_image['Path'], windows_image['Path'],
windows_version['Image Name'], windows_version['Image Name'],
'W:\\'] 'W:\\']
if 'Glob' in windows_image: if 'Glob' in windows_image:
cmd.extend(windows_image['Glob']) cmd.extend(windows_image['Glob'])
run_program(cmd) run_program(cmd)
def setup_windows_re(windows_version, windows_letter='W', tools_letter='T'): def setup_windows_re(windows_version, windows_letter='W', tools_letter='T'):
"""Setup the WinRE partition.""" """Setup the WinRE partition."""
win = r'{}:\Windows'.format(windows_letter) win = r'{}:\Windows'.format(windows_letter)
winre = r'{}\System32\Recovery\WinRE.wim'.format(win) winre = r'{}\System32\Recovery\WinRE.wim'.format(win)
dest = r'{}:\Recovery\WindowsRE'.format(tools_letter) dest = r'{}:\Recovery\WindowsRE'.format(tools_letter)
# Copy WinRE.wim # Copy WinRE.wim
os.makedirs(dest, exist_ok=True) os.makedirs(dest, exist_ok=True)
shutil.copy(winre, r'{}\WinRE.wim'.format(dest)) shutil.copy(winre, r'{}\WinRE.wim'.format(dest))
# Set location # Set location
cmd = [ cmd = [
r'{}\System32\ReAgentc.exe'.format(win), r'{}\System32\ReAgentc.exe'.format(win),
'/setreimage', '/setreimage',
'/path', dest, '/path', dest,
'/target', win] '/target', win]
run_program(cmd) run_program(cmd)
def update_boot_partition(system_letter='S', windows_letter='W', mode='ALL'): def update_boot_partition(system_letter='S', windows_letter='W', mode='ALL'):
"""Setup the Windows boot partition.""" """Setup the Windows boot partition."""
cmd = [ cmd = [
r'{}\Windows\System32\bcdboot.exe'.format( r'{}\Windows\System32\bcdboot.exe'.format(
global_vars['Env']['SYSTEMDRIVE']), global_vars['Env']['SYSTEMDRIVE']),
r'{}:\Windows'.format(windows_letter), r'{}:\Windows'.format(windows_letter),
'/s', '{}:'.format(system_letter), '/s', '{}:'.format(system_letter),
'/f', mode] '/f', mode]
run_program(cmd) run_program(cmd)
def wim_contains_image(filename, imagename): def wim_contains_image(filename, imagename):
"""Check if an ESD/WIM contains the specified image, returns bool.""" """Check if an ESD/WIM contains the specified image, returns bool."""
cmd = [ cmd = [
global_vars['Tools']['wimlib-imagex'], global_vars['Tools']['wimlib-imagex'],
'info', 'info',
filename, filename,
imagename] imagename]
try: try:
run_program(cmd) run_program(cmd)
except subprocess.CalledProcessError: except subprocess.CalledProcessError:
return False return False
return True return True
if __name__ == '__main__': if __name__ == '__main__':
print("This file is not meant to be called directly.") print("This file is not meant to be called directly.")
# vim: sts=2 sw=2 ts=2