mirror of
https://github.com/munki/munki.git
synced 2026-04-23 21:40:25 -05:00
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:
@@ -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.
|
||||
|
||||
@@ -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."""
|
||||
|
||||
@@ -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 = []
|
||||
|
||||
Reference in New Issue
Block a user