mirror of
https://github.com/munki/munki.git
synced 2026-04-22 20:48:36 -05:00
When a user clicks Stop while processing removals, Munki should not crash.
Fixes this traceback: Traceback (most recent call last): File '/usr/local/munki/managedsoftwareupdate', line 849, in main() File '/usr/local/munki/managedsoftwareupdate', line 705, in main mustrestart = doInstallTasks() File '/usr/local/munki/managedsoftwareupdate', line 225, in doInstallTasks need_to_restart = installer.run(only_unattended=only_unattended) File '/usr/local/munki/munkilib/installer.py', line 1169, in run removallist, only_unattended=only_unattended) TypeError: 'bool' object is not iterable
This commit is contained in:
@@ -44,7 +44,7 @@ from CoreFoundation import kCFStringEncodingASCII
|
||||
from objc import pyobjc_id
|
||||
|
||||
libIOKit = cdll.LoadLibrary('/System/Library/Frameworks/IOKit.framework/IOKit')
|
||||
libIOKit.IOPMAssertionCreateWithName.argtypes = [
|
||||
libIOKit.IOPMAssertionCreateWithName.argtypes = [
|
||||
c_void_p, c_uint32, c_void_p, POINTER(c_uint32) ]
|
||||
libIOKit.IOPMAssertionRelease.argtypes = [ c_uint32 ]
|
||||
|
||||
@@ -91,7 +91,7 @@ def removeBundleRelocationInfo(pkgpath):
|
||||
"Removed Contents/Resources/TokenDefinitions.plist")
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
|
||||
plist = {}
|
||||
infoplist = os.path.join(pkgpath, "Contents/Info.plist")
|
||||
if os.path.exists(infoplist):
|
||||
@@ -99,7 +99,7 @@ def removeBundleRelocationInfo(pkgpath):
|
||||
plist = FoundationPlist.readPlist(infoplist)
|
||||
except FoundationPlist.NSPropertyListSerializationException:
|
||||
pass
|
||||
|
||||
|
||||
if 'IFPkgPathMappings' in plist:
|
||||
del plist['IFPkgPathMappings']
|
||||
try:
|
||||
@@ -118,17 +118,17 @@ def install(pkgpath, choicesXMLpath=None, suppressBundleRelocation=False,
|
||||
Returns a tuple:
|
||||
the installer return code and restart needed as a boolean.
|
||||
"""
|
||||
|
||||
|
||||
restartneeded = False
|
||||
installeroutput = []
|
||||
|
||||
|
||||
if os.path.islink(pkgpath):
|
||||
# resolve links before passing them to /usr/bin/installer
|
||||
pkgpath = os.path.realpath(pkgpath)
|
||||
|
||||
|
||||
if suppressBundleRelocation:
|
||||
removeBundleRelocationInfo(pkgpath)
|
||||
|
||||
|
||||
packagename = ''
|
||||
restartaction = 'None'
|
||||
pkginfo = munkicommon.getInstallerPkgInfo(pkgpath)
|
||||
@@ -153,7 +153,7 @@ def install(pkgpath, choicesXMLpath=None, suppressBundleRelocation=False,
|
||||
munkicommon.display_status_minor(
|
||||
'%s requires a restart after installation.' % packagename)
|
||||
restartneeded = True
|
||||
|
||||
|
||||
# get the OS version; we need it later when processing installer's output,
|
||||
# which varies depending on OS version.
|
||||
os_version = munkicommon.getOsVersion()
|
||||
@@ -161,7 +161,7 @@ def install(pkgpath, choicesXMLpath=None, suppressBundleRelocation=False,
|
||||
'-target', '/']
|
||||
if choicesXMLpath:
|
||||
cmd.extend(['-applyChoiceChangesXML', choicesXMLpath])
|
||||
|
||||
|
||||
# set up environment for installer
|
||||
env_vars = os.environ.copy()
|
||||
# get info for root
|
||||
@@ -180,7 +180,7 @@ def install(pkgpath, choicesXMLpath=None, suppressBundleRelocation=False,
|
||||
env_vars[key] = environment[key]
|
||||
munkicommon.display_debug1(
|
||||
'Using custom installer environment variables: %s', env_vars)
|
||||
|
||||
|
||||
# run installer as a launchd job
|
||||
try:
|
||||
job = launchd.Job(cmd, environment_vars=env_vars)
|
||||
@@ -190,7 +190,7 @@ def install(pkgpath, choicesXMLpath=None, suppressBundleRelocation=False,
|
||||
'Error with launchd job (%s): %s', cmd, str(err))
|
||||
munkicommon.display_error('Can\'t run installer.')
|
||||
return (-3, False)
|
||||
|
||||
|
||||
timeout = 2 * 60 * 60
|
||||
inactive = 0
|
||||
last_output = None
|
||||
@@ -212,16 +212,16 @@ def install(pkgpath, choicesXMLpath=None, suppressBundleRelocation=False,
|
||||
# sleep a bit before checking for more output
|
||||
time.sleep(1)
|
||||
continue
|
||||
|
||||
|
||||
# we got non-empty output, reset inactive timer
|
||||
inactive = 0
|
||||
|
||||
|
||||
# Don't bother parsing the stdout output if it hasn't changed since
|
||||
# the last loop iteration.
|
||||
if last_output == installinfo:
|
||||
continue
|
||||
last_output = installinfo
|
||||
|
||||
|
||||
installinfo = installinfo.decode('UTF-8')
|
||||
if installinfo.startswith("installer:"):
|
||||
# save all installer output in case there is
|
||||
@@ -256,7 +256,7 @@ def install(pkgpath, choicesXMLpath=None, suppressBundleRelocation=False,
|
||||
munkistatus.detail(msg)
|
||||
else:
|
||||
munkicommon.log(msg)
|
||||
|
||||
|
||||
# installer exited
|
||||
retcode = job.returncode()
|
||||
if retcode != 0:
|
||||
@@ -271,7 +271,7 @@ def install(pkgpath, choicesXMLpath=None, suppressBundleRelocation=False,
|
||||
munkicommon.log("Install of %s was successful." % packagename)
|
||||
if munkicommon.munkistatusoutput:
|
||||
munkistatus.percent(100)
|
||||
|
||||
|
||||
return (retcode, restartneeded)
|
||||
|
||||
|
||||
@@ -312,9 +312,9 @@ def installall(dirpath, choicesXMLpath=None, suppressBundleRelocation=False,
|
||||
# ran into error; should unmount and stop.
|
||||
munkicommon.unmountdmg(mountpoints[0])
|
||||
return (retcode, restartflag)
|
||||
|
||||
|
||||
munkicommon.unmountdmg(mountpoints[0])
|
||||
|
||||
|
||||
if munkicommon.hasValidInstallerItemExt(item):
|
||||
(retcode, needsrestart) = install(itempath, choicesXMLpath,
|
||||
suppressBundleRelocation,
|
||||
@@ -324,7 +324,7 @@ def installall(dirpath, choicesXMLpath=None, suppressBundleRelocation=False,
|
||||
if retcode:
|
||||
# ran into error; should stop.
|
||||
return (retcode, restartflag)
|
||||
|
||||
|
||||
return (retcode, restartflag)
|
||||
|
||||
|
||||
@@ -345,7 +345,7 @@ def copyAppFromDMG(dmgpath):
|
||||
if munkicommon.isApplication(itempath):
|
||||
appname = item
|
||||
break
|
||||
|
||||
|
||||
if appname:
|
||||
# make an itemlist we can pass to copyItemsFromMountpoint
|
||||
itemlist = []
|
||||
@@ -373,25 +373,25 @@ def copyAppFromDMG(dmgpath):
|
||||
def copyItemsFromMountpoint(mountpoint, itemlist):
|
||||
'''copies items from the mountpoint to the startup disk
|
||||
Returns 0 if no issues; some error code otherwise.
|
||||
|
||||
|
||||
If the 'destination_item' key is provided, items will be copied
|
||||
as its value.'''
|
||||
for item in itemlist:
|
||||
|
||||
|
||||
# get itemname
|
||||
source_itemname = item.get("source_item")
|
||||
dest_itemname = item.get("destination_item")
|
||||
if not source_itemname:
|
||||
munkicommon.display_error("Missing name of item to copy!")
|
||||
return -1
|
||||
|
||||
|
||||
# check source path
|
||||
source_itempath = os.path.join(mountpoint, source_itemname)
|
||||
if not os.path.exists(source_itempath):
|
||||
munkicommon.display_error(
|
||||
"Source item %s does not exist!" % source_itemname)
|
||||
return -1
|
||||
|
||||
|
||||
# check destination path
|
||||
destpath = item.get("destination_path")
|
||||
if not os.path.exists(destpath):
|
||||
@@ -434,7 +434,7 @@ def copyItemsFromMountpoint(mountpoint, itemlist):
|
||||
else:
|
||||
full_destpath = os.path.join(
|
||||
destpath, os.path.basename(source_itemname))
|
||||
|
||||
|
||||
# remove item if it already exists
|
||||
if os.path.exists(full_destpath):
|
||||
retcode = subprocess.call(["/bin/rm", "-rf", full_destpath])
|
||||
@@ -442,7 +442,7 @@ def copyItemsFromMountpoint(mountpoint, itemlist):
|
||||
munkicommon.display_error(
|
||||
"Error removing existing %s" % full_destpath)
|
||||
return retcode
|
||||
|
||||
|
||||
# all tests passed, OK to copy
|
||||
munkicommon.display_status_minor(
|
||||
"Copying %s to %s" % (source_itemname, full_destpath))
|
||||
@@ -452,7 +452,7 @@ def copyItemsFromMountpoint(mountpoint, itemlist):
|
||||
munkicommon.display_error(
|
||||
"Error copying %s to %s" % (source_itempath, full_destpath))
|
||||
return retcode
|
||||
|
||||
|
||||
# set owner
|
||||
user = item.get('user', 'root')
|
||||
munkicommon.display_detail(
|
||||
@@ -463,7 +463,7 @@ def copyItemsFromMountpoint(mountpoint, itemlist):
|
||||
munkicommon.display_error(
|
||||
"Error setting owner for %s" % (full_destpath))
|
||||
return retcode
|
||||
|
||||
|
||||
# set group
|
||||
group = item.get('group', 'admin')
|
||||
munkicommon.display_detail(
|
||||
@@ -474,7 +474,7 @@ def copyItemsFromMountpoint(mountpoint, itemlist):
|
||||
munkicommon.display_error(
|
||||
"Error setting group for %s" % (full_destpath))
|
||||
return retcode
|
||||
|
||||
|
||||
# set mode
|
||||
mode = item.get('mode', 'o-w')
|
||||
munkicommon.display_detail(
|
||||
@@ -484,7 +484,7 @@ def copyItemsFromMountpoint(mountpoint, itemlist):
|
||||
munkicommon.display_error(
|
||||
"Error setting mode for %s" % (full_destpath))
|
||||
return retcode
|
||||
|
||||
|
||||
# remove com.apple.quarantine attribute from copied item
|
||||
cmd = ["/usr/bin/xattr", full_destpath]
|
||||
proc = subprocess.Popen(cmd, shell=False, bufsize=1,
|
||||
@@ -498,7 +498,7 @@ def copyItemsFromMountpoint(mountpoint, itemlist):
|
||||
unused_result = subprocess.call(
|
||||
["/usr/bin/xattr", "-d", "com.apple.quarantine",
|
||||
full_destpath])
|
||||
|
||||
|
||||
# all items copied successfully!
|
||||
return 0
|
||||
|
||||
@@ -508,7 +508,7 @@ def copyFromDMG(dmgpath, itemlist):
|
||||
if not itemlist:
|
||||
munkicommon.display_error("No items to copy!")
|
||||
return -1
|
||||
|
||||
|
||||
munkicommon.display_status_minor(
|
||||
'Mounting disk image %s' % os.path.basename(dmgpath))
|
||||
mountpoints = munkicommon.mountdmg(dmgpath)
|
||||
@@ -534,7 +534,7 @@ def removeCopiedItems(itemlist):
|
||||
if not itemlist:
|
||||
munkicommon.display_error("Nothing to remove!")
|
||||
return -1
|
||||
|
||||
|
||||
for item in itemlist:
|
||||
if 'destination_item' in item:
|
||||
itemname = item.get("destination_item")
|
||||
@@ -562,7 +562,7 @@ def removeCopiedItems(itemlist):
|
||||
# note it, but not an error
|
||||
munkicommon.display_detail("Path %s doesn't exist." %
|
||||
path_to_remove)
|
||||
|
||||
|
||||
return retcode
|
||||
|
||||
|
||||
@@ -572,7 +572,7 @@ def itemPrereqsInSkippedItems(item, skipped_items):
|
||||
munkicommon.display_debug1(
|
||||
'Checking for skipped prerequisites for %s-%s'
|
||||
% (item['name'], item.get('version_to_install')))
|
||||
|
||||
|
||||
# get list of prerequisites for this item
|
||||
prerequisites = item.get('requires', [])
|
||||
prerequisites.extend(item.get('update_for', []))
|
||||
@@ -582,7 +582,7 @@ def itemPrereqsInSkippedItems(item, skipped_items):
|
||||
% (item['name'], item.get('version_to_install')))
|
||||
return []
|
||||
munkicommon.display_debug1('Prerequisites: %s' % ", ".join(prerequisites))
|
||||
|
||||
|
||||
# build a dictionary of names and versions of skipped items
|
||||
skipped_item_dict = {}
|
||||
for skipped_item in skipped_items:
|
||||
@@ -593,7 +593,7 @@ def itemPrereqsInSkippedItems(item, skipped_items):
|
||||
munkicommon.display_debug1('Adding skipped item: %s-%s'
|
||||
% (skipped_item['name'], normalized_version))
|
||||
skipped_item_dict[skipped_item['name']].append(normalized_version)
|
||||
|
||||
|
||||
# now check prereqs against the skipped items
|
||||
matched_prereqs = []
|
||||
for prereq in prerequisites:
|
||||
@@ -647,23 +647,23 @@ def installWithInfo(
|
||||
'prerequisites were skipped: %s'
|
||||
% (item['name'], ", ".join(skipped_prereqs)))
|
||||
continue
|
||||
|
||||
|
||||
if munkicommon.stopRequested():
|
||||
return restartflag, skipped_installs
|
||||
|
||||
|
||||
retcode = 0
|
||||
if 'preinstall_script' in item:
|
||||
retcode = munkicommon.runEmbeddedScript('preinstall_script', item)
|
||||
|
||||
|
||||
if retcode == 0 and 'installer_item' in item:
|
||||
display_name = item.get('display_name') or item.get('name')
|
||||
version_to_install = item.get('version_to_install','')
|
||||
munkicommon.display_status_major(
|
||||
"Installing %s (%s of %s)"
|
||||
% (display_name, itemindex, len(installlist)))
|
||||
|
||||
|
||||
installer_type = item.get("installer_type","")
|
||||
|
||||
|
||||
itempath = os.path.join(dirpath, item["installer_item"])
|
||||
if installer_type != "nopkg" and not os.path.exists(itempath):
|
||||
# can't install, so we should stop. Since later items might
|
||||
@@ -671,7 +671,7 @@ def installWithInfo(
|
||||
munkicommon.display_error("Installer item %s was not found." %
|
||||
item["installer_item"])
|
||||
return restartflag, skipped_installs
|
||||
|
||||
|
||||
if installer_type.startswith("Adobe"):
|
||||
retcode = adobeutils.doAdobeInstall(item)
|
||||
if retcode == 0:
|
||||
@@ -733,7 +733,7 @@ def installWithInfo(
|
||||
if munkicommon.stopRequested():
|
||||
munkicommon.unmountdmg(mountpoints[0])
|
||||
return restartflag, skipped_installs
|
||||
|
||||
|
||||
retcode = -99 # in case we find nothing to install
|
||||
needtorestart = False
|
||||
if munkicommon.hasValidInstallerItemExt(item.get('package_path', '')):
|
||||
@@ -772,14 +772,14 @@ def installWithInfo(
|
||||
item.get("RestartAction") == "RequireRestart" or
|
||||
item.get("RestartAction") == "RecommendRestart"):
|
||||
restartflag = True
|
||||
|
||||
|
||||
else:
|
||||
# we didn't find anything we know how to install
|
||||
munkicommon.log(
|
||||
"Found nothing we know how to install in %s"
|
||||
% itempath)
|
||||
retcode = -99
|
||||
|
||||
|
||||
if retcode == 0 and 'postinstall_script' in item:
|
||||
# only run embedded postinstall script if the install did not
|
||||
# return a failure code
|
||||
@@ -795,29 +795,29 @@ def installWithInfo(
|
||||
# reset retcode to 0 so we will mark this install
|
||||
# as successful
|
||||
retcode = 0
|
||||
|
||||
|
||||
# record install success/failure
|
||||
if not 'InstallResults' in munkicommon.report:
|
||||
munkicommon.report['InstallResults'] = []
|
||||
|
||||
|
||||
if applesus:
|
||||
message = "Apple SUS install of %s-%s: %s"
|
||||
else:
|
||||
message = "Install of %s-%s: %s"
|
||||
|
||||
|
||||
if retcode == 0:
|
||||
status = "SUCCESSFUL"
|
||||
else:
|
||||
status = "FAILED with return code: %s" % retcode
|
||||
|
||||
|
||||
log_msg = message % (display_name, version_to_install, status)
|
||||
munkicommon.log(log_msg, "Install.log")
|
||||
|
||||
|
||||
# Calculate install duration; note, if a machine is put to sleep
|
||||
# during the install this time may be inaccurate.
|
||||
utc_now_complete = datetime.datetime.utcnow()
|
||||
duration_seconds = (utc_now_complete - utc_now).seconds
|
||||
|
||||
|
||||
download_speed = item.get('download_kbytes_per_sec', 0)
|
||||
install_result = {
|
||||
'name': display_name,
|
||||
@@ -829,7 +829,7 @@ def installWithInfo(
|
||||
'download_kbytes_per_sec': download_speed,
|
||||
}
|
||||
munkicommon.report['InstallResults'].append(install_result)
|
||||
|
||||
|
||||
# check to see if this installer item is needed by any additional
|
||||
# items in installinfo
|
||||
# this might happen if there are multiple things being installed
|
||||
@@ -848,7 +848,7 @@ def installWithInfo(
|
||||
current_installer_item):
|
||||
foundagain = True
|
||||
break
|
||||
|
||||
|
||||
# need to check skipped_installs as well
|
||||
if not foundagain:
|
||||
for skipped_item in skipped_installs:
|
||||
@@ -856,7 +856,7 @@ def installWithInfo(
|
||||
current_installer_item):
|
||||
foundagain = True
|
||||
break
|
||||
|
||||
|
||||
if not foundagain:
|
||||
# now remove the item from the install cache
|
||||
# (if it's still there)
|
||||
@@ -878,7 +878,7 @@ def installWithInfo(
|
||||
if os.path.exists(shadowfile):
|
||||
retcode = subprocess.call(
|
||||
["/bin/rm", shadowfile])
|
||||
|
||||
|
||||
return (restartflag, skipped_installs)
|
||||
|
||||
|
||||
@@ -887,7 +887,7 @@ def skippedItemsThatRequireThisItem(item, skipped_items):
|
||||
the current item. Returns a list of matches.'''
|
||||
munkicommon.display_debug1(
|
||||
'Checking for skipped items that require %s' % item['name'])
|
||||
|
||||
|
||||
matched_skipped_items = []
|
||||
for skipped_item in skipped_items:
|
||||
# get list of prerequisites for this skipped_item
|
||||
@@ -932,23 +932,23 @@ def processRemovals(removallist, only_unattended=False):
|
||||
'skipped items required it: %s'
|
||||
% (item['name'], ", ".join(dependent_skipped_items)))
|
||||
continue
|
||||
|
||||
|
||||
if munkicommon.stopRequested():
|
||||
return restartFlag
|
||||
return restartFlag, skipped_removals
|
||||
if not item.get('installed'):
|
||||
# not installed, so skip it (this shouldn't happen...)
|
||||
continue
|
||||
|
||||
|
||||
index += 1
|
||||
name = item.get('display_name') or item.get('name')
|
||||
munkicommon.display_status_major(
|
||||
"Removing %s (%s of %s)..." % (name, index, len(removallist)))
|
||||
|
||||
|
||||
retcode = 0
|
||||
# run preuninstall_script if it exists
|
||||
if 'preuninstall_script' in item:
|
||||
retcode = munkicommon.runEmbeddedScript('preuninstall_script', item)
|
||||
|
||||
|
||||
if retcode == 0 and 'uninstall_method' in item:
|
||||
uninstallmethod = item['uninstall_method']
|
||||
if uninstallmethod == "removepackages":
|
||||
@@ -967,13 +967,13 @@ def processRemovals(removallist, only_unattended=False):
|
||||
else:
|
||||
munkicommon.log("Uninstall of %s was "
|
||||
"successful." % name)
|
||||
|
||||
|
||||
elif uninstallmethod.startswith("Adobe"):
|
||||
retcode = adobeutils.doAdobeRemoval(item)
|
||||
|
||||
|
||||
elif uninstallmethod == "remove_copied_items":
|
||||
retcode = removeCopiedItems(item.get('items_to_remove'))
|
||||
|
||||
|
||||
elif uninstallmethod == "remove_app":
|
||||
remove_app_info = item.get('remove_app_info', None)
|
||||
if remove_app_info:
|
||||
@@ -990,14 +990,14 @@ def processRemovals(removallist, only_unattended=False):
|
||||
munkicommon.display_error("Application removal "
|
||||
"info missing from %s" %
|
||||
name)
|
||||
|
||||
|
||||
elif uninstallmethod == 'uninstall_script':
|
||||
retcode = munkicommon.runEmbeddedScript(
|
||||
'uninstall_script', item)
|
||||
if (retcode == 0 and
|
||||
item.get('RestartAction') == "RequireRestart"):
|
||||
restartFlag = True
|
||||
|
||||
|
||||
elif os.path.exists(uninstallmethod) and \
|
||||
os.access(uninstallmethod, os.X_OK):
|
||||
# it's a script or program to uninstall
|
||||
@@ -1006,13 +1006,13 @@ def processRemovals(removallist, only_unattended=False):
|
||||
if (retcode == 0 and
|
||||
item.get('RestartAction') == "RequireRestart"):
|
||||
restartFlag = True
|
||||
|
||||
|
||||
else:
|
||||
munkicommon.log("Uninstall of %s failed because "
|
||||
"there was no valid uninstall "
|
||||
"method." % name)
|
||||
retcode = -99
|
||||
|
||||
|
||||
if retcode == 0 and item.get('postuninstall_script'):
|
||||
retcode = munkicommon.runEmbeddedScript(
|
||||
'postuninstall_script', item)
|
||||
@@ -1026,7 +1026,7 @@ def processRemovals(removallist, only_unattended=False):
|
||||
# reset retcode to 0 so we will mark this uninstall
|
||||
# as successful
|
||||
retcode = 0
|
||||
|
||||
|
||||
# record removal success/failure
|
||||
if not 'RemovalResults' in munkicommon.report:
|
||||
munkicommon.report['RemovalResults'] = []
|
||||
@@ -1041,7 +1041,7 @@ def processRemovals(removallist, only_unattended=False):
|
||||
" FAILED with return code: %s" % retcode
|
||||
munkicommon.log(failure_msg, "Install.log")
|
||||
munkicommon.report['RemovalResults'].append(failure_msg)
|
||||
|
||||
|
||||
return (restartFlag, skipped_removals)
|
||||
|
||||
|
||||
@@ -1072,7 +1072,7 @@ def blockingApplicationsRunning(pkginfoitem):
|
||||
"""Returns true if any application in the blocking_applications list
|
||||
is running or, if there is no blocking_applications list, if any
|
||||
application in the installs list is running."""
|
||||
|
||||
|
||||
if 'blocking_applications' in pkginfoitem:
|
||||
appnames = pkginfoitem['blocking_applications']
|
||||
else:
|
||||
@@ -1081,7 +1081,7 @@ def blockingApplicationsRunning(pkginfoitem):
|
||||
appnames = [os.path.basename(item.get('path'))
|
||||
for item in pkginfoitem.get('installs', [])
|
||||
if item['type'] == 'application']
|
||||
|
||||
|
||||
munkicommon.display_debug1("Checking for %s" % appnames)
|
||||
running_apps = [appname for appname in appnames
|
||||
if munkicommon.isAppRunning(appname)]
|
||||
@@ -1097,37 +1097,37 @@ def blockingApplicationsRunning(pkginfoitem):
|
||||
def assertNoIdleSleep():
|
||||
"""Uses IOKit functions to prevent idle sleep"""
|
||||
# based on code by Michael Lynn, pudquick@github
|
||||
|
||||
|
||||
kIOPMAssertionTypeNoIdleSleep = "NoIdleSleepAssertion"
|
||||
kIOPMAssertionLevelOn = 255
|
||||
reason = "Munki is installing software"
|
||||
|
||||
|
||||
errcode, assertID = IOPMAssertionCreateWithName(
|
||||
kIOPMAssertionTypeNoIdleSleep,
|
||||
kIOPMAssertionLevelOn,
|
||||
kIOPMAssertionLevelOn,
|
||||
reason)
|
||||
return assertID
|
||||
|
||||
|
||||
def run(only_unattended=False):
|
||||
"""Runs the install/removal session.
|
||||
|
||||
|
||||
Args:
|
||||
only_unattended: Boolean. If True, only do unattended_(un)install pkgs.
|
||||
"""
|
||||
# hold onto the assertionID so we can release it later
|
||||
no_idle_sleep_assertion_id = assertNoIdleSleep()
|
||||
|
||||
|
||||
managedinstallbase = munkicommon.pref('ManagedInstallDir')
|
||||
installdir = os.path.join(managedinstallbase , 'Cache')
|
||||
|
||||
|
||||
removals_need_restart = installs_need_restart = False
|
||||
|
||||
|
||||
if only_unattended:
|
||||
munkicommon.log("### Beginning unattended installer session ###")
|
||||
else:
|
||||
munkicommon.log("### Beginning managed installer session ###")
|
||||
|
||||
|
||||
installinfopath = os.path.join(managedinstallbase, 'InstallInfo.plist')
|
||||
if os.path.exists(installinfopath):
|
||||
try:
|
||||
@@ -1135,7 +1135,7 @@ def run(only_unattended=False):
|
||||
except FoundationPlist.NSPropertyListSerializationException:
|
||||
munkicommon.display_error("Invalid %s" % installinfopath)
|
||||
return -1
|
||||
|
||||
|
||||
# remove the install info file
|
||||
# it's no longer valid once we start running
|
||||
try:
|
||||
@@ -1143,11 +1143,11 @@ def run(only_unattended=False):
|
||||
except (OSError, IOError):
|
||||
munkicommon.display_warning(
|
||||
"Could not remove %s" % installinfopath)
|
||||
|
||||
|
||||
if (munkicommon.munkistatusoutput and
|
||||
munkicommon.pref('SuppressStopButtonOnInstall')):
|
||||
munkistatus.hideStopButton()
|
||||
|
||||
|
||||
if "removals" in installinfo:
|
||||
# filter list to items that need to be removed
|
||||
removallist = [item for item in installinfo['removals']
|
||||
@@ -1169,7 +1169,7 @@ def run(only_unattended=False):
|
||||
removallist, only_unattended=only_unattended)
|
||||
# if any removals were skipped, record them for later
|
||||
installinfo['removals'] = skipped_removals
|
||||
|
||||
|
||||
if "managed_installs" in installinfo:
|
||||
if not munkicommon.stopRequested():
|
||||
# filter list to items that need to be installed
|
||||
@@ -1195,7 +1195,7 @@ def run(only_unattended=False):
|
||||
only_unattended=only_unattended)
|
||||
# if any installs were skipped record them for later
|
||||
installinfo['managed_installs'] = skipped_installs
|
||||
|
||||
|
||||
if (only_unattended and
|
||||
installinfo['managed_installs'] or installinfo['removals']):
|
||||
# need to write the installinfo back out minus the stuff we
|
||||
@@ -1206,20 +1206,20 @@ def run(only_unattended=False):
|
||||
# not fatal
|
||||
munkicommon.display_warning(
|
||||
"Could not write to %s" % installinfopath)
|
||||
|
||||
|
||||
else:
|
||||
if not only_unattended: # no need to log that no unattended pkgs found.
|
||||
munkicommon.log("No %s found." % installinfo)
|
||||
|
||||
|
||||
if only_unattended:
|
||||
munkicommon.log("### End unattended installer session ###")
|
||||
else:
|
||||
munkicommon.log("### End managed installer session ###")
|
||||
|
||||
|
||||
munkicommon.savereport()
|
||||
|
||||
|
||||
# release our Power Manager assertion
|
||||
errcode = IOPMAssertionRelease(no_idle_sleep_assertion_id)
|
||||
|
||||
|
||||
return (removals_need_restart or installs_need_restart)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user