Added support for blocking_applications that cause a forced_install or forced_uninstall to be skipped if any application in the list is running.

git-svn-id: http://munki.googlecode.com/svn/trunk@898 a4e17f2e-e282-11dd-95e1-755cbddbdd66
This commit is contained in:
Greg Neagle
2010-11-10 01:00:44 +00:00
parent 2e43d20cfb
commit 87036833e1
3 changed files with 97 additions and 5 deletions
+36 -4
View File
@@ -455,7 +455,7 @@ def removeCopiedItems(itemlist):
return retcode
def installWithInfo(dirpath, installlist):
def installWithInfo(dirpath, installlist, forced=False):
"""
Uses the installlist to install items in the
correct order.
@@ -463,6 +463,10 @@ def installWithInfo(dirpath, installlist):
restartflag = False
itemindex = 0
for item in installlist:
if forced and blockingApplicationsRunning(item):
munkicommon.display_detail(
"Skipping forced install of %s" % item['name'])
continue
if munkicommon.stopRequested():
return restartflag
if "installer_item" in item:
@@ -487,6 +491,7 @@ def installWithInfo(dirpath, installlist):
munkicommon.display_error("Installer item %s was not found." %
item["installer_item"])
return restartflag
installer_type = item.get("installer_type","")
if installer_type.startswith("Adobe"):
retcode = adobeutils.doAdobeInstall(item)
@@ -634,11 +639,15 @@ def installWithInfo(dirpath, installlist):
return restartflag
def processRemovals(removallist):
def processRemovals(removallist, forced=False):
'''processes removals from the removal list'''
restartFlag = False
index = 0
for item in removallist:
if forced and blockingApplicationsRunning(item):
munkicommon.display_detail(
"Skipping forced removal of %s" % item['name'])
continue
if munkicommon.stopRequested():
return restartFlag
if not item.get('installed'):
@@ -787,6 +796,27 @@ def removeItemFromSelfServeUninstallList(itemname):
FoundationPlist.writePlist(plist, selfservemanifest)
except FoundationPlist.FoundationPlistException:
pass
def blockingApplicationsRunning(pkginfoitem):
"""Returns true if any application in the
blocking_applications list is running or
any application in the installs list is running."""
appnames = [item.get('CFBundleName') or os.path.basename(item.get('path'))
for item in pkginfoitem.get('installs', [])
if item['type'] == 'application']
appnames.extend(pkginfoitem.get('blocking_applications',[]))
munkicommon.display_debug1("Checking for %s" % appnames)
running_apps = [appname for appname in appnames
if munkicommon.isAppRunning(appname)]
if running_apps:
munkicommon.display_detail(
"Blocking apps for %s are running:" % pkginfoitem['name'])
munkicommon.display_detail(
" %s" % running_apps)
return True
return False
def run(only_forced=False):
@@ -866,7 +896,8 @@ def run(only_forced=False):
# set indeterminate progress bar
munkistatus.percent(-1)
munkicommon.log("Processing removals")
removals_need_restart = processRemovals(removallist)
removals_need_restart = processRemovals(removallist,
forced=only_forced)
if "managed_installs" in installinfo:
if not munkicommon.stopRequested():
# filter list to items that need to be installed
@@ -892,7 +923,8 @@ def run(only_forced=False):
munkistatus.percent(-1)
munkicommon.log("Processing installs")
installs_need_restart = installWithInfo(installdir,
installlist)
installlist,
forced=only_forced)
else:
if not only_forced: # not need to log that no forced found.
+43
View File
@@ -1435,6 +1435,8 @@ def getAppData():
try:
plist = FoundationPlist.readPlist(plistpath)
iteminfo['bundleid' ] = plist.get('CFBundleIdentifier','')
iteminfo['CFBundleExecutable'] = \
plist.get('CFBundleExecutable','')
if 'CFBundleName' in plist:
iteminfo['name'] = plist['CFBundleName']
iteminfo['version'] = getExtendedVersion(pathname)
@@ -1446,6 +1448,47 @@ def getAppData():
# some utility functions
def isAppRunning(appname):
"""Tries to determine if the application in appname is currently
running"""
display_detail('Checking if %s is running...' % appname)
applist = getAppData()
executable_names = []
if appname.endswith('.app'):
# search by filename
executable_names = [item['CFBundleExecutable'] for item in applist
if 'CFBundleExecutable' in item and
item['path'].endswith(appname)]
else:
# check name and executable names
executable_names = [item['CFBundleExecutable'] for item in applist
if 'CFBundleExecutable' in item and
item['name'] == appname or
item['CFBundleExecutable'] == appname]
if executable_names:
# uniquify the list
executable_names = list(set(executable_names))
else:
# just use the appname as the executable name
executable_names = [appname]
display_debug1('Executable names: %s' % executable_names)
for executable in executable_names:
display_detail('Checking %s...' % executable)
retcode = subprocess.call(['/usr/bin/killall', '-s', executable],
shell=False, stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
if retcode == 0:
# executable is running!
display_debug1('%s is running!' % executable)
display_detail('%s is running!' % appname)
return True
# if we get here, we have no evidence that appname is running
return False
def getAvailableDiskSpace(volumepath='/'):
"""Returns available diskspace in KBytes."""
+18 -1
View File
@@ -1385,7 +1385,7 @@ def processInstall(manifestitem, cataloglist, installinfo):
if (not item_pl.get('requires') and not item_pl.get('update_for') and
not item_pl.get('RestartAction')):
iteminfo['forced_install'] = item_pl.get('forced_install', False)
iteminfo['forced_uninstall'] = item_pl.get('forced_uninstall', False)
#iteminfo['forced_uninstall'] = item_pl.get('forced_uninstall', False)
if not isInstalled(item_pl):
munkicommon.display_detail('Need to install %s' % manifestitemname)
@@ -1416,6 +1416,8 @@ def processInstall(manifestitem, cataloglist, installinfo):
'installer_type',
'adobe_package_name',
'package_path',
'blocking_applications',
'installs',
'items_to_copy', # used w/ copy_from_dmg
'copy_local'] # used w/ AdobeCS5 Updaters
@@ -1709,6 +1711,21 @@ def processRemoval(manifestitem, cataloglist, installinfo):
iteminfo['display_name'] = uninstall_item.get('display_name', '')
iteminfo['manifestitem'] = manifestitemname_withversion
iteminfo['description'] = 'Will be removed.'
# currently we will ignore the forced_install and forced_uninstall key if
# the item is part of a dependency graph or needs a restart or logout...
if (not uninstall_item.get('requires')
and not uninstall_item.get('update_for')
and not uninstall_item.get('RestartAction')):
iteminfo['forced_uninstall'] = uninstall_item.get(
'forced_uninstall', False)
if 'blocking_applications' in uninstall_item:
iteminfo['blocking_applications'] = \
uninstall_item['blocking_applications']
if 'installs' in uninstall_item:
iteminfo['installs'] = uninstall_item['installs']
if packagesToRemove:
# remove references for each package
packagesToReallyRemove = []