def installedApplePackagesChanged(): '''Generates a SHA-256 checksum of the info for all packages in the receipts database whose id matches com.apple.* and compares it to a stored version of this checksum. Returns False if the checksums match, True if they differ.''' cmd = ['/usr/sbin/pkgutil', '--regexp', '-pkg-info-plist', 'com\.apple\.*'] proc = subprocess.Popen(cmd, shell=False, bufsize=1, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) (output, unused_err) = proc.communicate() current_apple_packages_checksum = hashlib.sha256(output).hexdigest() old_apple_packages_checksum = munkicommon.pref( 'InstalledApplePackagesChecksum') if current_apple_packages_checksum == old_apple_packages_checksum: return False else: munkicommon.set_pref('InstalledApplePackagesChecksum', current_apple_packages_checksum) return True
def installAppleUpdates(): '''Uses /usr/sbin/softwareupdate to install previously downloaded updates. Returns True if a restart is needed after install, False otherwise.''' msg = "Installing available Apple Software Updates..." if munkicommon.munkistatusoutput: munkistatus.message(msg) munkistatus.detail("") munkistatus.percent(-1) munkicommon.log(msg) else: munkicommon.display_status(msg) restartneeded = restartNeeded() # use our filtered local catalog catalogpath = os.path.join(swupdCacheDir(), 'content/catalogs/local_install.sucatalog') if not os.path.exists(catalogpath): munkicommon.display_error( 'Missing local Software Update catalog at %s', catalogpath) # didn't do anything, so no restart needed return False installlist = getSoftwareUpdateInfo() installresults = {'installed': [], 'download': []} catalogURL = 'file://localhost' + urllib2.quote(catalogpath) retcode = run_softwareupdate(['--CatalogURL', catalogURL, '-i', '-a'], mode='install', results=installresults) if not 'InstallResults' in munkicommon.report: munkicommon.report['InstallResults'] = [] for item in installlist: rep = {} rep['name'] = item.get('display_name') rep['version'] = item.get('version_to_install', '') rep['applesus'] = True rep['productKey'] = item.get('productKey', '') message = "Apple Software Update install of %s-%s: %s" if rep['name'] in installresults['installed']: rep['status'] = 0 install_status = 'SUCCESSFUL' elif rep['name'] in installresults['download']: rep['status'] = -1 install_status = 'FAILED due to missing package.' munkicommon.display_warning( 'Apple update %s, %s failed. A sub-package was missing ' 'on disk at time of install.' % (rep['name'], rep['productKey'])) else: rep['status'] = -2 install_status = 'FAILED for unknown reason' munkicommon.display_warning( 'Apple update %s, %s failed to install. No record of ' 'success or failure.' % (rep['name'], rep['productKey'])) munkicommon.report['InstallResults'].append(rep) log_msg = message % (rep['name'], rep['version'], install_status) munkicommon.log(log_msg, "Install.log") if retcode: # there was an error munkicommon.display_error("softwareupdate error: %s" % retcode) # clean up our now stale local cache cachedir = os.path.join(swupdCacheDir()) if os.path.exists(cachedir): unused_retcode = subprocess.call(['/bin/rm', '-rf', cachedir]) # remove the now invalid appleUpdatesFile try: os.unlink(appleUpdatesFile()) except OSError: pass # Also clear our pref value for last check date. We may have # just installed an update which is a pre-req for some other update. # Let's check again soon. munkicommon.set_pref('LastAppleSoftwareUpdateCheck', None) return restartneeded
'of available updates.') forcecheck = True if forcecheck: updatelist = getAvailableUpdates() if updatelist: writeFilteredUpdateCatalog(updatelist) try: cacheSwupdMetadata() except ReplicationError, err: munkicommon.display_warning( 'Could not replicate software update metadata:') munkicommon.display_warning('\t', err) return False if downloadAvailableUpdates(): # Download success. Updates ready to install. munkicommon.set_pref('LastAppleSoftwareUpdateCheck', NSDate.date()) return True else: # Download error, allow check again soon. return False else: # No updates found (not currently differentiating # "softwareupdate -l" failure from no updates found). munkicommon.set_pref('LastAppleSoftwareUpdateCheck', NSDate.date()) return False else: munkicommon.log('Skipping Apple Software Update check because ' 'sucatalog is unchanged, installed Apple packages ' 'are unchanged and we recently did a full check') return False
def installAppleUpdates(): '''Uses /usr/sbin/softwareupdate to install previously downloaded updates. Returns True if a restart is needed after install, False otherwise.''' msg = "Installing available Apple Software Updates..." if munkicommon.munkistatusoutput: munkistatus.message(msg) munkistatus.detail("") munkistatus.percent(-1) munkicommon.log(msg) else: munkicommon.display_status(msg) restartneeded = restartNeeded() # use our filtered local catalog catalogpath = os.path.join(swupdCacheDir(), 'content/catalogs/local_install.sucatalog') if not os.path.exists(catalogpath): munkicommon.display_error( 'Missing local Software Update catalog at %s', catalogpath) # didn't do anything, so no restart needed return False installlist = getSoftwareUpdateInfo() installresults = {'installed':[], 'download':[]} catalogURL = 'file://localhost' + urllib2.quote(catalogpath) retcode = run_softwareupdate(['--CatalogURL', catalogURL, '-i', '-a'], mode='install', results=installresults) if not 'InstallResults' in munkicommon.report: munkicommon.report['InstallResults'] = [] for item in installlist: rep = {} rep['name'] = item.get('display_name') rep['version'] = item.get('version_to_install', '') rep['applesus'] = True rep['productKey'] = item.get('productKey', '') message = "Apple Software Update install of %s-%s: %s" if rep['name'] in installresults['installed']: rep['status'] = 0 install_status = 'SUCCESSFUL' elif rep['name'] in installresults['download']: rep['status'] = -1 install_status = 'FAILED due to missing package.' munkicommon.display_warning( 'Apple update %s, %s failed. A sub-package was missing ' 'on disk at time of install.' % (rep['name'], rep['productKey'])) else: rep['status'] = -2 install_status = 'FAILED for unknown reason' munkicommon.display_warning( 'Apple update %s, %s failed to install. No record of ' 'success or failure.' % (rep['name'],rep['productKey'])) munkicommon.report['InstallResults'].append(rep) log_msg = message % (rep['name'], rep['version'], install_status) munkicommon.log(log_msg, "Install.log") if retcode: # there was an error munkicommon.display_error("softwareupdate error: %s" % retcode) # clean up our now stale local cache cachedir = os.path.join(swupdCacheDir()) if os.path.exists(cachedir): unused_retcode = subprocess.call(['/bin/rm', '-rf', cachedir]) # remove the now invalid appleUpdatesFile try: os.unlink(appleUpdatesFile()) except OSError: pass # Also clear our pref value for last check date. We may have # just installed an update which is a pre-req for some other update. # Let's check again soon. munkicommon.set_pref('LastAppleSoftwareUpdateCheck', None) return restartneeded