Skip to content

Commit

Permalink
Some changes to appleupdates.py to work around issues on 10.11
Browse files Browse the repository at this point in the history
  • Loading branch information
gregneagle committed Jul 29, 2015
1 parent d0f0862 commit 9e0deb7
Showing 1 changed file with 90 additions and 27 deletions.
117 changes: 90 additions & 27 deletions code/client/munkilib/appleupdates.py
Expand Up @@ -6,7 +6,7 @@
Utilities for dealing with Apple Software Update.
"""
# Copyright 2009-2014 Greg Neagle.
# Copyright 2009-2015 Greg Neagle.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -119,7 +119,6 @@
LOCAL_CATALOG_NAME = 'local_install.sucatalog'



class Error(Exception):
"""Class for domain specific exceptions."""

Expand Down Expand Up @@ -574,9 +573,14 @@ def DownloadAvailableUpdates(self):

catalog_url = 'file://localhost' + urllib2.quote(
self.local_download_catalog_path)

if munkicommon.getOsVersion() == '10.5':
os_version_tuple = munkicommon.getOsVersion(as_tuple=True)
if os_version_tuple == (10, 5):
retcode = self._LeopardDownloadAvailableUpdates(catalog_url)
elif os_version_tuple >= (10, 11):
# 10.11 seems not to like file:// URLs
catalog_url = self._GetAppleCatalogURL()
retcode = self._RunSoftwareUpdate(
['-d', '-a'], catalog_url=catalog_url, stop_allowed=True)
else:
retcode = self._RunSoftwareUpdate(
['-d', '-a'], catalog_url=catalog_url, stop_allowed=True)
Expand All @@ -599,13 +603,19 @@ def GetAvailableUpdateProductIDs(self, catalog_path=''):
msg = 'Checking for available Apple Software Updates...'
self._ResetMunkiStatusAndDisplayMessage(msg)

try: # remove any old ApplicableUpdates.plist, but ignore errors.
try:
# remove any old ApplicableUpdates.plist, but ignore errors.
os.unlink(self.applicable_updates_plist)
except (OSError, IOError):
pass

# use our locally-cached Apple catalog
catalog_url = 'file://localhost' + urllib2.quote(catalog_path)
os_version_tuple = munkicommon.getOsVersion(as_tuple=True)
if os_version_tuple >= (10, 11):
# 10.11 does not appear to like file:// URLs
catalog_url = self._GetAppleCatalogURL()
else:
# use our locally-cached Apple catalog
catalog_url = 'file://localhost' + urllib2.quote(catalog_path)
su_options = ['-l', '-f', self.applicable_updates_plist]

retcode = self._RunSoftwareUpdate(
Expand Down Expand Up @@ -994,16 +1004,28 @@ def _SetCustomCatalogURL(self, catalog_url):
APPLE_SOFTWARE_UPDATE_PREFS_DOMAIN,
kCFPreferencesAnyUser, kCFPreferencesCurrentHost)
# now set our custom CatalogURL
CFPreferencesSetValue(
'CatalogURL', catalog_url,
APPLE_SOFTWARE_UPDATE_PREFS_DOMAIN,
kCFPreferencesAnyUser, kCFPreferencesCurrentHost)
# finally, sync things up
if not CFPreferencesSynchronize(
os_version_tuple = munkicommon.getOsVersion(as_tuple=True)
if os_version_tuple < (10, 11):
CFPreferencesSetValue(
'CatalogURL', catalog_url,
APPLE_SOFTWARE_UPDATE_PREFS_DOMAIN,
kCFPreferencesAnyUser, kCFPreferencesCurrentHost):
munkicommon.display_error(
'Error setting com.apple.SoftwareUpdate CatalogURL.')
kCFPreferencesAnyUser, kCFPreferencesCurrentHost)
# finally, sync things up
if not CFPreferencesSynchronize(
APPLE_SOFTWARE_UPDATE_PREFS_DOMAIN,
kCFPreferencesAnyUser, kCFPreferencesCurrentHost):
munkicommon.display_error(
'Error setting com.apple.SoftwareUpdate CatalogURL.')
else:
# use softwareupdate --set-catalog
proc = subprocess.Popen(
['/usr/sbin/softwareupdate', '--set-catalog', catalog_url],
bufsize=-1, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
(output, err) = proc.communicate()
if output:
munkicommon.display_detail(output)
if err:
munkicommon.display_error(err)

def _ResetOriginalCatalogURL(self):
"""Resets SoftwareUpdate's CatalogURL to the original value"""
Expand All @@ -1020,10 +1042,24 @@ def _ResetOriginalCatalogURL(self):
if not original_catalog_url:
original_catalog_url = None
# reset CatalogURL to the one we stored
CFPreferencesSetValue(
'CatalogURL', original_catalog_url,
APPLE_SOFTWARE_UPDATE_PREFS_DOMAIN,
kCFPreferencesAnyUser, kCFPreferencesCurrentHost)
os_version_tuple = munkicommon.getOsVersion(as_tuple=True)
if os_version_tuple < (10, 11):
CFPreferencesSetValue(
'CatalogURL', original_catalog_url,
APPLE_SOFTWARE_UPDATE_PREFS_DOMAIN,
kCFPreferencesAnyUser, kCFPreferencesCurrentHost)
else:
# use softwareupdate --set-catalog
proc = subprocess.Popen(
['/usr/sbin/softwareupdate',
'--set-catalog', original_catalog_url],
bufsize=-1, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
(output, err) = proc.communicate()
if output:
munkicommon.display_detail(output)
if err:
munkicommon.display_error(err)

# remove ORIGINAL_CATALOG_URL_KEY
CFPreferencesSetValue(
self.ORIGINAL_CATALOG_URL_KEY, None,
Expand All @@ -1040,7 +1076,7 @@ def CatalogURLisManaged(self):
"""Returns True if Software Update's CatalogURL is managed
via MCX or Profiles"""
return CFPreferencesAppValueIsForced(
APPLE_SOFTWARE_UPDATE_PREFS_DOMAIN, 'CatalogURL')
'CatalogURL', APPLE_SOFTWARE_UPDATE_PREFS_DOMAIN)

def _LeopardSetupSoftwareUpdateCheck(self):
"""Set defaults for root user and current host; needed for Leopard."""
Expand Down Expand Up @@ -1382,8 +1418,18 @@ def InstallAppleUpdates(self, only_unattended=False):
if item.get('productKey') in
unattended_install_product_ids]
else:
# We're installing all available updates
su_options.extend(['-a'])
# We're installing all available updates; add all their names
for item in installlist:
su_options.append(
item['name'] + '-' + item['version_to_install'])

# new in 10.11: '--no-scan' flag to tell softwareupdate to just install
# and not rescan for available updates.
os_version_tuple = munkicommon.getOsVersion(as_tuple=True)
if os_version_tuple >= (10, 11):
su_options.append('--no-scan')
# 10.11 seems not like file:// URLs
catalog_url = self._GetAppleCatalogURL()

retcode = self._RunSoftwareUpdate(
su_options, mode='install', catalog_url=catalog_url,
Expand Down Expand Up @@ -1641,12 +1687,29 @@ def installAppleUpdates(only_unattended=False):
def appleSoftwareUpdatesAvailable(forcecheck=False, suppresscheck=False,
client_id='', forcecatalogrefresh=False):
"""Method for drop-in appleupdates replacement; see primary method docs."""
os_version_tuple = munkicommon.getOsVersion(as_tuple=True)
munkisuscatalog = munkicommon.pref('SoftwareUpdateServerURL')
appleUpdatesObject = getAppleUpdatesInstance()
if appleUpdatesObject.CatalogURLisManaged():
munkicommon.display_warning(
"Cannot manage Apple Software updates because CatalogURL "
"is managed via MCX or profiles.")
return False
if os_version_tuple >= (10, 11):
if munkisuscatalog:
munkicommon.display_warning(
"softwareupdate's CatalogURL is managed via MCX or "
"profiles. Custom softwareupate catalog %s will be "
"ignored." % munkisuscatalog)
else:
munkicommon.display_warning(
"Cannot efficiently manage Apple Software updates because "
"softwareupdate's CatalogURL is managed via MCX or profiles. "
"You may see unexpected or undesirable results.")
else:
if os_version_tuple >= (10, 11) and munkisuscatalog:
munkicommon.display_warning(
"Setting SoftwareUpdateServerURL in Munki's preferences under "
"OS X 10.11 and later may result in poor performance of "
"Apple Software Updates via Munki. It is recommended to "
"remove this setting and use com.apple.SoftwareUpdate's "
'settings for CatalogURL.')
appleUpdatesObject.client_id = client_id
appleUpdatesObject.force_catalog_refresh = forcecatalogrefresh

Expand Down

0 comments on commit 9e0deb7

Please sign in to comment.