From 74ab4d3792bd72f6810168d739a8ca7c43ff7471 Mon Sep 17 00:00:00 2001 From: twangboy Date: Wed, 27 Mar 2019 17:03:13 -0600 Subject: [PATCH] Use old way to get osrelease if new way fails --- salt/grains/core.py | 76 ++++++++++++++++------- tests/unit/grains/test_core.py | 109 +++++++++++++++++++++++++++++++++ 2 files changed, 162 insertions(+), 23 deletions(-) diff --git a/salt/grains/core.py b/salt/grains/core.py index 9758275f2c..60d701c8ea 100644 --- a/salt/grains/core.py +++ b/salt/grains/core.py @@ -1131,6 +1131,57 @@ def _clean_value(key, val): return val +def _windows_os_release_grain(caption, product_type): + ''' + helper function for getting the osrelease grain + :return: + ''' + # This creates the osrelease grain based on the Windows Operating + # System Product Name. As long as Microsoft maintains a similar format + # this should be future proof + version = 'Unknown' + release = '' + if 'Server' in caption: + for item in caption.split(' '): + # If it's all digits, then it's version + if re.match(r'\d+', item): + version = item + # If it starts with R and then numbers, it's the release + # ie: R2 + if re.match(r'^R\d+$', item): + release = item + os_release = '{0}Server{1}'.format(version, release) + else: + for item in caption.split(' '): + # If it's a number, decimal number, Thin or Vista, then it's the + # version + if re.match(r'^(\d+(\.\d+)?)|Thin|Vista|XP$', item): + version = item + os_release = version + + # If the version is still Unknown, revert back to the old way of getting + # the os_release + # https://github.com/saltstack/salt/issues/52339 + if os_release in ['Unknown']: + os_release = platform.release() + server = {'Vista': '2008Server', + '7': '2008ServerR2', + '8': '2012Server', + '8.1': '2012ServerR2', + '10': '2016Server'} + + # Starting with Python 2.7.12 and 3.5.2 the `platform.uname()` + # function started reporting the Desktop version instead of the + # Server version on # Server versions of Windows, so we need to look + # those up. So, if you find a Server Platform that's a key in the + # server dictionary, then lookup the actual Server Release. + # (Product Type 1 is Desktop, Everything else is Server) + if product_type > 1 and os_release in server: + os_release = server[os_release] + + return os_release + + def _windows_platform_data(): ''' Use the platform module for as much as we can. @@ -1177,7 +1228,6 @@ def _windows_platform_data(): except IndexError: log.debug('Motherboard info not available on this system') - os_release = platform.release() kernel_version = platform.version() info = salt.utils.win_osinfo.get_os_version_info() @@ -1185,28 +1235,8 @@ def _windows_platform_data(): if info['ServicePackMajor'] > 0: service_pack = ''.join(['SP', six.text_type(info['ServicePackMajor'])]) - # This creates the osrelease grain based on the Windows Operating - # System Product Name. As long as Microsoft maintains a similar format - # this should be future proof - version = 'Unknown' - release = '' - if 'Server' in osinfo.Caption: - for item in osinfo.Caption.split(' '): - # If it's all digits, then it's version - if re.match(r'\d+', item): - version = item - # If it starts with R and then numbers, it's the release - # ie: R2 - if re.match(r'^R\d+$', item): - release = item - os_release = '{0}Server{1}'.format(version, release) - else: - for item in osinfo.Caption.split(' '): - # If it's a number, decimal number, Thin or Vista, then it's the - # version - if re.match(r'^(\d+(\.\d+)?)|Thin|Vista$', item): - version = item - os_release = version + os_release = _windows_os_release_grain(caption=osinfo.Caption, + product_type=osinfo.ProductType) grains = { 'kernelrelease': _clean_value('kernelrelease', osinfo.Version), diff --git a/tests/unit/grains/test_core.py b/tests/unit/grains/test_core.py index 3874b0001c..aab6b52452 100644 --- a/tests/unit/grains/test_core.py +++ b/tests/unit/grains/test_core.py @@ -580,6 +580,115 @@ class CoreGrainsTestCase(TestCase, LoaderModuleMockMixin): } self._run_os_grains_tests("ubuntu-17.10", _os_release_map, expectation) + def test__windows_os_release_grain(self): + versions = { + 'Windows 10 Home': '10', + 'Windows 10 Pro': '10', + 'Windows 10 Pro for Workstations': '10', + 'Windows 10 Pro Education': '10', + 'Windows 10 Enterprise': '10', + 'Windows 10 Enterprise LTSB': '10', + 'Windows 10 Education': '10', + 'Windows 10 IoT Core': '10', + 'Windows 10 IoT Enterprise': '10', + 'Windows 10 S': '10', + 'Windows 8.1': '8.1', + 'Windows 8.1 Pro': '8.1', + 'Windows 8.1 Enterprise': '8.1', + 'Windows 8.1 OEM': '8.1', + 'Windows 8.1 with Bing': '8.1', + 'Windows 8': '8', + 'Windows 8 Pro': '8', + 'Windows 8 Enterprise': '8', + 'Windows 8 OEM': '8', + 'Windows 7 Starter': '7', + 'Windows 7 Home Basic': '7', + 'Windows 7 Home Premium': '7', + 'Windows 7 Professional': '7', + 'Windows 7 Enterprise': '7', + 'Windows 7 Ultimate': '7', + 'Windows Thin PC': 'Thin', + 'Windows Vista Starter': 'Vista', + 'Windows Vista Home Basic': 'Vista', + 'Windows Vista Home Premium': 'Vista', + 'Windows Vista Business': 'Vista', + 'Windows Vista Enterprise': 'Vista', + 'Windows Vista Ultimate': 'Vista', + 'Windows Server 2019 Essentials': '2019Server', + 'Windows Server 2019 Standard': '2019Server', + 'Windows Server 2019 Datacenter': '2019Server', + 'Windows Server 2016 Essentials': '2016Server', + 'Windows Server 2016 Standard': '2016Server', + 'Windows Server 2016 Datacenter': '2016Server', + 'Windows Server 2012 R2 Foundation': '2012ServerR2', + 'Windows Server 2012 R2 Essentials': '2012ServerR2', + 'Windows Server 2012 R2 Standard': '2012ServerR2', + 'Windows Server 2012 R2 Datacenter': '2012ServerR2', + 'Windows Server 2012 Foundation': '2012Server', + 'Windows Server 2012 Essentials': '2012Server', + 'Windows Server 2012 Standard': '2012Server', + 'Windows Server 2012 Datacenter': '2012Server', + 'Windows MultiPoint Server 2012': '2012Server', + 'Windows Small Business Server 2011': '2011Server', + 'Windows MultiPoint Server 2011': '2011Server', + 'Windows Home Server 2011': '2011Server', + 'Windows MultiPoint Server 2010': '2010Server', + 'Windows Server 2008 R2 Foundation': '2008ServerR2', + 'Windows Server 2008 R2 Standard': '2008ServerR2', + 'Windows Server 2008 R2 Enterprise': '2008ServerR2', + 'Windows Server 2008 R2 Datacenter': '2008ServerR2', + 'Windows Server 2008 R2 for Itanium-based Systems': '2008ServerR2', + 'Windows Web Server 2008 R2': '2008ServerR2', + 'Windows Storage Server 2008 R2': '2008ServerR2', + 'Windows HPC Server 2008 R2': '2008ServerR2', + 'Windows Server 2008 Standard': '2008Server', + 'Windows Server 2008 Enterprise': '2008Server', + 'Windows Server 2008 Datacenter': '2008Server', + 'Windows Server 2008 for Itanium-based Systems': '2008Server', + 'Windows Server Foundation 2008': '2008Server', + 'Windows Essential Business Server 2008': '2008Server', + 'Windows HPC Server 2008': '2008Server', + 'Windows Small Business Server 2008': '2008Server', + 'Windows Storage Server 2008': '2008Server', + 'Windows Web Server 2008': '2008Server' + } + for caption in versions: + version = core._windows_os_release_grain(caption, 1) + self.assertEqual( + version, + versions[caption], + 'version: {0}\n' + 'found: {1}\n' + 'caption: {2}'.format(version, versions[caption], caption) + ) + + embedded_versions = { + 'Windows Embedded 8.1 Industry Pro': '8.1', + 'Windows Embedded 8 Industry Pro': '8', + 'Windows POSReady 7': '7', + 'Windows Embedded Standard 7': '7', + 'Windows Embedded POSReady 2009': '2009', + 'Windows Embedded Standard 2009': '2009', + 'Windows XP Embedded': 'XP', + } + for caption in embedded_versions: + version = core._windows_os_release_grain(caption, 1) + self.assertEqual( + version, + embedded_versions[caption], + '{0} != {1}\n' + 'version: {0}\n' + 'found: {1}\n' + 'caption: {2}'.format(version, embedded_versions[caption], caption) + ) + + # Special Cases + # Windows Embedded Standard is Windows 7 + caption = 'Windows Embedded Standard' + with patch('platform.release', MagicMock(return_value='7')): + version = core._windows_os_release_grain(caption, 1) + self.assertEqual(version, '7') + @skipIf(not salt.utils.platform.is_linux(), 'System is not Linux') def test_linux_memdata(self): '''