Created
March 29, 2017 15:33
-
-
Save timsutton/db17054ed3afcd8947fcd5c499ced9af to your computer and use it in GitHub Desktop.
Munki conditional for checking eligible OS upgrades
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python | |
# encoding: utf-8 | |
# | |
# Modified from Hannes Juutilainen's check-1012-sierra-compatibility.py | |
# and check-10.8-mountainlion-compatibility.py scripts from | |
# | |
# Hannes Juutilainen <[email protected]> | |
# https://github.com/hjuutilainen/adminscripts | |
# | |
# Modified to return a single condition, `supported_major_os_upgrades`, which is | |
# an array containing a list of all major OS versions that this machine can be | |
# upgraded to, i.e. ['10.8', '10.9', '10.10', '10.11', '10.12'] | |
# | |
# Major versions which match the machine version or are older are removed from | |
# the list, so that Munki conditions don't need to also check for the current | |
# OS version - this script will handle that. | |
# | |
# See KNOWN_VERSIONS for the OS values supported. | |
import sys | |
import subprocess | |
import os | |
import re | |
import plistlib | |
from platform import mac_ver | |
from distutils.version import LooseVersion | |
from Foundation import CFPreferencesCopyAppValue | |
KNOWN_VERSIONS = ['10.8', '10.9', '10.10', '10.11', '10.12'] | |
# Set this to False if you don't want any output, just the exit codes | |
VERBOSE = True | |
CONDITIONAL_KEY = 'supported_major_os_upgrades' | |
def logger(message, status, info): | |
if VERBOSE: | |
print "%14s: %-40s [%s]" % (message, status, info) | |
pass | |
def conditional_items_path(): | |
# <http://code.google.com/p/munki/wiki/ConditionalItems> | |
# Read the location of the ManagedInstallDir from ManagedInstall.plist | |
bundle_id = 'ManagedInstalls' | |
pref_name = 'ManagedInstallDir' | |
managed_installs_dir = CFPreferencesCopyAppValue(pref_name, bundle_id) | |
# Make sure we're outputting our information to "ConditionalItems.plist" | |
if managed_installs_dir: | |
return os.path.join(managed_installs_dir, 'ConditionalItems.plist') | |
else: | |
# Munki default | |
return "/Library/Managed Installs/ConditionalItems.plist" | |
def get_full_system_version(): | |
'''Returns a LooseVersion like '10.12', '10.11.6', etc.''' | |
return LooseVersion(mac_ver()[0]) | |
def get_major_system_version(): | |
'''Returns the major system version as just an int''' | |
return int(mac_ver()[0].split('.')[1]) | |
def is_64bit_efi(): | |
cmd = ["/usr/sbin/ioreg", | |
"-l", | |
"-p", "IODeviceTree", | |
] | |
proc = subprocess.Popen(cmd, bufsize=1, stdout=subprocess.PIPE, stderr=subprocess.PIPE) | |
(results, _) = proc.communicate() | |
efi_64 = False | |
for line in results.splitlines(): | |
if re.search('firmware-abi.*EFI64', line): | |
efi_64 = True | |
break | |
if efi_64: | |
logger("EFI", | |
"64 bit capable", | |
"OK") | |
return True | |
else: | |
logger("EFI", | |
"not 64 bit capable", | |
"Failed") | |
return False | |
def get_board_id(): | |
cmd = ["/usr/sbin/ioreg", | |
"-p", "IODeviceTree", | |
"-r", | |
"-n", "/", | |
"-d", "1"] | |
p1 = subprocess.Popen(cmd, bufsize=1, stdout=subprocess.PIPE, stderr=subprocess.PIPE) | |
p2 = subprocess.Popen(["/usr/bin/grep", "board-id"], stdin=p1.stdout, stdout=subprocess.PIPE) | |
(results, err) = p2.communicate() | |
board_id = re.sub(r"^\s*\"board-id\" = <\"(.*)\">$", r"\1", results) | |
board_id = board_id.strip() | |
if board_id.startswith('Mac'): | |
return board_id | |
else: | |
return None | |
def is_virtual_machine(): | |
cmd = ["/usr/sbin/sysctl", "-n", "machdep.cpu.features"] | |
p = subprocess.Popen(cmd, bufsize=1, stdout=subprocess.PIPE, stderr=subprocess.PIPE) | |
(results, err) = p.communicate() | |
for feature in results.split(): | |
if feature == "VMM": | |
logger("Board ID", | |
"Virtual machine", | |
"OK") | |
return True | |
return False | |
def get_current_model(): | |
cmd = ["/usr/sbin/sysctl", "-n", "hw.model"] | |
p = subprocess.Popen(cmd, bufsize=1, stdout=subprocess.PIPE, stderr=subprocess.PIPE) | |
(results, err) = p.communicate() | |
return results.strip() | |
def is_sierra_supported_model(): | |
non_supported_models = [ | |
'iMac4,1', | |
'iMac4,2', | |
'iMac5,1', | |
'iMac5,2', | |
'iMac6,1', | |
'iMac7,1', | |
'iMac8,1', | |
'iMac9,1', | |
'MacBook1,1', | |
'MacBook2,1', | |
'MacBook3,1', | |
'MacBook4,1', | |
'MacBook5,1', | |
'MacBook5,2', | |
'MacBookAir1,1', | |
'MacBookAir2,1', | |
'MacBookPro1,1', | |
'MacBookPro1,2', | |
'MacBookPro2,1', | |
'MacBookPro2,2', | |
'MacBookPro3,1', | |
'MacBookPro4,1', | |
'MacBookPro5,1', | |
'MacBookPro5,2', | |
'MacBookPro5,3', | |
'MacBookPro5,4', | |
'MacBookPro5,5', | |
'Macmini1,1', | |
'Macmini2,1', | |
'Macmini3,1', | |
'MacPro1,1', | |
'MacPro2,1', | |
'MacPro3,1', | |
'MacPro4,1', | |
'Xserve1,1', | |
'Xserve2,1', | |
'Xserve3,1'] | |
current_model = get_current_model() | |
if current_model in non_supported_models: | |
logger("Model", | |
"\"%s\" is not supported" % current_model, | |
"Failed") | |
return False | |
else: | |
logger("Model", | |
current_model, | |
"OK") | |
return True | |
def is_sierra_supported_board_id(): | |
platform_support_values = [ | |
'Mac-00BE6ED71E35EB86', | |
'Mac-031AEE4D24BFF0B1', | |
'Mac-031B6874CF7F642A', | |
'Mac-06F11F11946D27C5', | |
'Mac-06F11FD93F0323C5', | |
'Mac-189A3D4F975D5FFC', | |
'Mac-27ADBB7B4CEE8E61', | |
'Mac-2BD1B31983FE1663', | |
'Mac-2E6FAB96566FE58C', | |
'Mac-35C1E88140C3E6CF', | |
'Mac-35C5E08120C7EEAF', | |
'Mac-3CBD00234E554E41', | |
'Mac-42FD25EABCABB274', | |
'Mac-4B7AC7E43945597E', | |
'Mac-4BC72D62AD45599E', | |
'Mac-50619A408DB004DA', | |
'Mac-65CE76090165799A', | |
'Mac-66F35F19FE2A0D05', | |
'Mac-6F01561E16C75D06', | |
'Mac-742912EFDBEE19B3', | |
'Mac-77EB7D7DAF985301', | |
'Mac-7BA5B2794B2CDB12', | |
'Mac-7DF21CB3ED6977E5', | |
'Mac-7DF2A3B5E5D671ED', | |
'Mac-81E3E92DD6088272', | |
'Mac-8ED6AF5B48C039E1', | |
'Mac-937CB26E2E02BB01', | |
'Mac-942452F5819B1C1B', | |
'Mac-942459F5819B171B', | |
'Mac-94245A3940C91C80', | |
'Mac-94245B3640C91C81', | |
'Mac-942B59F58194171B', | |
'Mac-942B5BF58194151B', | |
'Mac-942C5DF58193131B', | |
'Mac-9AE82516C7C6B903', | |
'Mac-9F18E312C5C2BF0B', | |
'Mac-A369DDC4E67F1C45', | |
'Mac-AFD8A9D944EA4843', | |
'Mac-B809C3757DA9BB8D', | |
'Mac-BE0E8AC46FE800CC', | |
'Mac-C08A6BB70A942AC2', | |
'Mac-C3EC7CD22292981F', | |
'Mac-DB15BD556843C820', | |
'Mac-E43C1C25D4880AD6', | |
'Mac-F2208EC8', | |
'Mac-F221BEC8', | |
'Mac-F221DCC8', | |
'Mac-F222BEC8', | |
'Mac-F2238AC8', | |
'Mac-F2238BAE', | |
'Mac-F22586C8', | |
'Mac-F22589C8', | |
'Mac-F2268CC8', | |
'Mac-F2268DAE', | |
'Mac-F2268DC8', | |
'Mac-F22C89C8', | |
'Mac-F22C8AC8', | |
'Mac-F305150B0C7DEEEF', | |
'Mac-F60DEB81FF30ACF6', | |
'Mac-F65AE981FFA204ED', | |
'Mac-FA842E06C61E91C5', | |
'Mac-FC02E91DDD3FA6A4', | |
'Mac-FFE5EF870D7BA81A'] | |
board_id = get_board_id() | |
if board_id in platform_support_values: | |
logger("Board ID", | |
board_id, | |
"OK") | |
return True | |
else: | |
logger("Board ID", | |
"\"%s\" is not supported" % board_id, | |
"Failed") | |
return False | |
def append_conditional_items(item): | |
output_dict = dict() | |
current_conditional_items_path = conditional_items_path() | |
if os.path.exists(current_conditional_items_path): | |
existing_dict = plistlib.readPlist(current_conditional_items_path) | |
output_dict.update(existing_dict) | |
output_dict[CONDITIONAL_KEY] = item | |
plistlib.writePlist(output_dict, current_conditional_items_path) | |
def main(): | |
supported_list = [] | |
if is_virtual_machine(): | |
supported_list = KNOWN_VERSIONS[:] | |
else: | |
if is_64bit_efi(): | |
supported_list.extend(['10.8', '10.9', '10.10', '10.11']) | |
if is_sierra_supported_board_id() and is_sierra_supported_model(): | |
if get_full_system_version() >= LooseVersion('10.7.5'): | |
supported_list.append('10.12') | |
# Now filter out all major versions <= what we're running so that | |
# we can't install on top of ourself, or attempt to install an | |
# older version | |
running_major_version = get_major_system_version() | |
filtered_list = [] | |
for version in supported_list: | |
if int(version.split('.')[1]) > running_major_version: | |
filtered_list.append(version) | |
append_conditional_items(filtered_list) | |
if __name__ == '__main__': | |
sys.exit(main()) | |
0 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment