Skip to content

Commit

Permalink
resolves #164 un-hardcode list of Windows versions
Browse files Browse the repository at this point in the history
Partially resolves #138 (support for insider base image is still missing)

This commit:
1. Drops the list of valid Windows versions. Instead, ue4-docker now trusts user input and will fail during image download if user enters something nonexistent
2. Drops 1603->ltsc2016, 1809->ltsc2019 and 2009->20H2 renaming. Instead, ue4-docker directly maps host OS release to Windows Server Core image tag
3. However, ue4-docker now uses advanced logic to determine host OS release. It tries to use DisplayName registry key and fallbacks to ReleaseId if DisplayName doesn't exist. This allows to properly detect 20H2 and 21H1 releases.

On the negative side, some checks are lost:
1. It is no longer possible to check that container version is newer that host OS. Though is should still be rejected by Hyper-V
2. ue4-docker no longer prevents user from using suffix that collides with Windows Server Core image tags
  • Loading branch information
slonopotamus committed May 25, 2021
1 parent 057f018 commit 99a5e30
Show file tree
Hide file tree
Showing 4 changed files with 11 additions and 76 deletions.
7 changes: 1 addition & 6 deletions ue4docker/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -138,13 +138,8 @@ def build():
logger.error('https://unrealcontainers.com/docs/concepts/windows-containers', False)
sys.exit(1)

# Verify that the user is not attempting to build images with a newer kernel version than the host OS
if WindowsUtils.isNewerBaseTag(config.hostBasetag, config.basetag):
logger.error('Error: cannot build container images with a newer kernel version than that of the host OS!')
sys.exit(1)

# Check if the user is building a different kernel version to the host OS but is still copying DLLs from System32
differentKernels = WindowsUtils.isInsiderPreview() or config.basetag != config.hostBasetag
differentKernels = config.basetag != config.hostBasetag
if config.pullPrerequisites == False and differentKernels == True and config.dlldir == config.defaultDllDir:
logger.error('Error: building images with a different kernel version than the host,', False)
logger.error('but a custom DLL directory has not specified via the `-dlldir=DIR` arg.', False)
Expand Down
3 changes: 1 addition & 2 deletions ue4docker/diagnostics/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,7 @@ def _generateWindowsBuildArgs(self, logger, basetagOverride=None, isolationOverr
'''

# Determine the appropriate container image base tag for the host system release unless the user specified a base tag
buildArgs = []
defaultBaseTag = WindowsUtils.getReleaseBaseTag(WindowsUtils.getWindowsRelease())
defaultBaseTag = WindowsUtils.getWindowsRelease()
baseTag = basetagOverride if basetagOverride is not None else defaultBaseTag
buildArgs = ['--build-arg', 'BASETAG={}'.format(baseTag)]

Expand Down
13 changes: 2 additions & 11 deletions ue4docker/infrastructure/BuildConfiguration.py
Original file line number Diff line number Diff line change
Expand Up @@ -228,29 +228,20 @@ def _generateWindowsConfig(self):
self.dlldir = self.args.dlldir if self.args.dlldir is not None else self.defaultDllDir

# Determine base tag for the Windows release of the host system
self.hostRelease = WindowsUtils.getWindowsRelease()
self.hostBasetag = WindowsUtils.getReleaseBaseTag(self.hostRelease)
self.hostBasetag = WindowsUtils.getWindowsRelease()

# Store the tag for the base Windows Server Core image
self.basetag = self.args.basetag if self.args.basetag is not None else self.hostBasetag
self.baseImage = 'mcr.microsoft.com/windows/servercore:' + self.basetag
self.prereqsTag = self.basetag

# Verify that any user-specified base tag is valid
if WindowsUtils.isValidBaseTag(self.basetag) == False:
raise RuntimeError('unrecognised Windows Server Core base image tag "{}", supported tags are {}'.format(self.basetag, WindowsUtils.getValidBaseTags()))

# Verify that any user-specified tag suffix does not collide with our base tags
if WindowsUtils.isValidBaseTag(self.suffix) == True:
raise RuntimeError('tag suffix cannot be any of the Windows Server Core base image tags: {}'.format(WindowsUtils.getValidBaseTags()))

# If the user has explicitly specified an isolation mode then use it, otherwise auto-detect
if self.args.isolation is not None:
self.isolation = self.args.isolation
else:

# If we are able to use process isolation mode then use it, otherwise fallback to the Docker daemon's default isolation mode
differentKernels = WindowsUtils.isInsiderPreview() or self.basetag != self.hostBasetag
differentKernels = self.basetag != self.hostBasetag
hostSupportsProcess = WindowsUtils.supportsProcessIsolation()
dockerSupportsProcess = parse_version(DockerUtils.version()['Version']) >= parse_version('18.09.0')
if not differentKernels and hostSupportsProcess and dockerSupportsProcess:
Expand Down
64 changes: 7 additions & 57 deletions ue4docker/infrastructure/WindowsUtils.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,6 @@

class WindowsUtils(object):

# The latest Windows build version we recognise as a non-Insider build
_latestReleaseBuild = 19042

# The list of Windows Server Core base image tags that we recognise, in ascending version number order
_validTags = ['ltsc2016', '1709', '1803', 'ltsc2019', '1903', '1909', '2004', '20H2']

# The list of Windows Server and Windows 10 host OS releases that are blacklisted due to critical bugs
# (See: <https://unrealcontainers.com/docs/concepts/windows-containers>)
_blacklistedReleases = ['1903', '1909']
Expand Down Expand Up @@ -76,7 +70,13 @@ def getWindowsRelease() -> str:
'''
Determines the Windows 10 / Windows Server release (1607, 1709, 1803, etc.) of the Windows host system
'''
return WindowsUtils._getVersionRegKey('ReleaseId')
try:
# Starting with Windows 20H2 (also known as 2009), Microsoft stopped updating ReleaseId
# and instead updates DisplayVersion
return WindowsUtils._getVersionRegKey('DisplayVersion')
except FileNotFoundError:
# Fallback to ReleaseId for pre-20H2 releases that didn't have DisplayVersion
return WindowsUtils._getVersionRegKey('ReleaseId')

@staticmethod
def getWindowsBuild() -> int:
Expand Down Expand Up @@ -112,56 +112,6 @@ def isWindowsServer() -> bool:
# TODO: Replace this with something more reliable
return 'Windows Server' in WindowsUtils._getVersionRegKey('ProductName')

@staticmethod
def isInsiderPreview() -> bool:
'''
Determines if the Windows host system is a Windows Insider preview build
'''
return WindowsUtils.getWindowsBuild() > WindowsUtils._latestReleaseBuild

@staticmethod
def getReleaseBaseTag(release: str) -> str:
'''
Retrieves the tag for the Windows Server Core base image matching the specified Windows 10 / Windows Server release
'''

# For Windows Insider preview builds, build the latest release tag
if WindowsUtils.isInsiderPreview():
return WindowsUtils._validTags[-1]

# This lookup table is based on the list of valid tags from <https://hub.docker.com/r/microsoft/windowsservercore/>
return {
'1709': '1709',
'1803': '1803',
'1809': 'ltsc2019',
'1903': '1903',
'1909': '1909',
'2004': '2004',
'2009': '20H2',
'20H2': '20H2'
}.get(release, 'ltsc2016')

@staticmethod
def getValidBaseTags() -> [str]:
'''
Returns the list of valid tags for the Windows Server Core base image, in ascending chronological release order
'''
return WindowsUtils._validTags

@staticmethod
def isValidBaseTag(tag: str) -> bool:
'''
Determines if the specified tag is a valid Windows Server Core base image tag
'''
return tag in WindowsUtils._validTags

@staticmethod
def isNewerBaseTag(older: str, newer: str) -> bool:
'''
Determines if the base tag `newer` is chronologically newer than the base tag `older`
'''
return WindowsUtils._validTags.index(newer) > WindowsUtils._validTags.index(older)

@staticmethod
def supportsProcessIsolation() -> bool:
'''
Expand Down

0 comments on commit 99a5e30

Please sign in to comment.