mirror of
https://github.com/munki/munki.git
synced 2026-01-24 07:59:19 -06:00
Add support for uninstall scripts embedded into pkginfo.
git-svn-id: http://munki.googlecode.com/svn/trunk@925 a4e17f2e-e282-11dd-95e1-755cbddbdd66
This commit is contained in:
@@ -657,6 +657,60 @@ def installWithInfo(dirpath, installlist, only_forced=False):
|
||||
return (restartflag, skipped_installs)
|
||||
|
||||
|
||||
def writefile(stringdata, path):
|
||||
'''Writes string data to path.
|
||||
Returns the path on success, empty string on failure.'''
|
||||
try:
|
||||
fileobject = open(path, mode='w', buffering=1)
|
||||
print >> fileobject, stringdata.encode('UTF-8')
|
||||
fileobject.close()
|
||||
return path
|
||||
except (OSError, IOError):
|
||||
munkicommon.display_error("Couldn't write %s" % stringdata)
|
||||
return ""
|
||||
|
||||
|
||||
def runUninstallScript(name, path):
|
||||
if munkicommon.munkistatusoutput:
|
||||
munkistatus.message("Running uninstall script "
|
||||
"for %s..." % name)
|
||||
munkistatus.detail("")
|
||||
# set indeterminate progress bar
|
||||
munkistatus.percent(-1)
|
||||
|
||||
uninstalleroutput = []
|
||||
proc = subprocess.Popen(path, shell=False, bufsize=1,
|
||||
stdin=subprocess.PIPE,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE)
|
||||
|
||||
while (proc.poll() == None):
|
||||
msg = proc.stdout.readline().decode('UTF-8')
|
||||
# save all uninstaller output in case there is
|
||||
# an error so we can dump it to the log
|
||||
uninstalleroutput.append(msg)
|
||||
msg = msg.rstrip("\n")
|
||||
munkicommon.display_info(msg)
|
||||
|
||||
retcode = proc.poll()
|
||||
if retcode:
|
||||
munkicommon.display_error(
|
||||
"Uninstall of %s failed." % name)
|
||||
munkicommon.display_error("-"*78)
|
||||
for line in uninstalleroutput:
|
||||
munkicommon.display_error("\t%s" % line.rstrip("\n"))
|
||||
munkicommon.display_error("-"*78)
|
||||
else:
|
||||
munkicommon.log("Uninstall of %s was "
|
||||
"successful." % name)
|
||||
|
||||
if munkicommon.munkistatusoutput:
|
||||
# clear indeterminate progress bar
|
||||
munkistatus.percent(0)
|
||||
|
||||
return retcode
|
||||
|
||||
|
||||
def processRemovals(removallist, only_forced=False):
|
||||
'''processes removals from the removal list'''
|
||||
restartFlag = False
|
||||
@@ -735,50 +789,38 @@ def processRemovals(removallist, only_forced=False):
|
||||
"info missing from %s" %
|
||||
name)
|
||||
|
||||
elif uninstallmethod[0] == "uninstall_script":
|
||||
uninstall_script = item.get('uninstall_script')
|
||||
if uninstall_script:
|
||||
scriptpath = os.path.join(munkicommon.tmpdir,
|
||||
"uninstallscript")
|
||||
if writefile(uninstall_script, scriptpath):
|
||||
cmd = ['/bin/chmod', '-R', 'o+x', scriptpath]
|
||||
retcode = subprocess.call(cmd)
|
||||
if retcode:
|
||||
munkicommon.display_error("Error setting mode "
|
||||
"for %s" % scriptpath)
|
||||
else:
|
||||
retcode = runUninstallScript(name, scriptpath)
|
||||
if (retcode == 0 and item.get(
|
||||
'RestartAction') == "RequireRestart"):
|
||||
restartFlag = True
|
||||
os.unlink(scriptpath)
|
||||
else:
|
||||
munkicommon.display_error("Cannot write uninstall "
|
||||
"script for %s" % name)
|
||||
else:
|
||||
munkicommon.display_error("Uninstall script missing "
|
||||
"from %s" % name)
|
||||
|
||||
elif os.path.exists(uninstallmethod[0]) and \
|
||||
os.access(uninstallmethod[0], os.X_OK):
|
||||
# it's a script or program to uninstall
|
||||
if munkicommon.munkistatusoutput:
|
||||
munkistatus.message("Running uninstall script "
|
||||
"for %s..." % name)
|
||||
munkistatus.detail("")
|
||||
# set indeterminate progress bar
|
||||
munkistatus.percent(-1)
|
||||
|
||||
if item.get('RestartAction') == "RequireRestart":
|
||||
retcode = runUninstallScript(name, uninstallmethod[0])
|
||||
if (retcode == 0 and
|
||||
item.get('RestartAction') == "RequireRestart"):
|
||||
restartFlag = True
|
||||
|
||||
cmd = uninstallmethod
|
||||
uninstalleroutput = []
|
||||
proc = subprocess.Popen(cmd, shell=False, bufsize=1,
|
||||
stdin=subprocess.PIPE,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.STDOUT)
|
||||
|
||||
while (proc.poll() == None):
|
||||
msg = proc.stdout.readline().decode('UTF-8')
|
||||
# save all uninstaller output in case there is
|
||||
# an error so we can dump it to the log
|
||||
uninstalleroutput.append(msg)
|
||||
msg = msg.rstrip("\n")
|
||||
munkicommon.display_info(msg)
|
||||
|
||||
retcode = proc.poll()
|
||||
if retcode:
|
||||
munkicommon.display_error(
|
||||
"Uninstall of %s failed." % name)
|
||||
munkicommon.display_error("-"*78)
|
||||
for line in uninstalleroutput:
|
||||
munkicommon.display_error("\t%s" % line.rstrip("\n"))
|
||||
munkicommon.display_error("-"*78)
|
||||
else:
|
||||
munkicommon.log("Uninstall of %s was "
|
||||
"successful." % name)
|
||||
|
||||
if munkicommon.munkistatusoutput:
|
||||
# clear indeterminate progress bar
|
||||
munkistatus.percent(0)
|
||||
|
||||
else:
|
||||
munkicommon.log("Uninstall of %s failed because "
|
||||
"there was no valid uninstall "
|
||||
|
||||
@@ -758,7 +758,6 @@ def getAllItemsWithName(name, cataloglist):
|
||||
if itemlist:
|
||||
# sort so latest version is first
|
||||
itemlist.sort(compare_item_versions)
|
||||
|
||||
return itemlist
|
||||
|
||||
|
||||
@@ -1070,16 +1069,8 @@ def evidenceThisIsInstalled(item_pl):
|
||||
This is used when determining if we can remove the item, thus
|
||||
the attention given to the uninstall method.
|
||||
"""
|
||||
if item_pl.get('uninstall_method') == 'removepackages':
|
||||
# we're supposed to use receipt info to remove
|
||||
# this, so we should check for relevent receipts
|
||||
if item_pl.get('receipts'):
|
||||
if PKGDATA == {}:
|
||||
# build our database of installed packages
|
||||
analyzeInstalledPkgs()
|
||||
if item_pl['name'] in PKGDATA['installed_names']:
|
||||
return True
|
||||
elif 'installs' in item_pl:
|
||||
if ('installs' in item_pl and
|
||||
item_pl.get('uninstall_method') != 'removepackages'):
|
||||
installitems = item_pl['installs']
|
||||
foundallinstallitems = True
|
||||
for item in installitems:
|
||||
@@ -1092,6 +1083,12 @@ def evidenceThisIsInstalled(item_pl):
|
||||
foundallinstallitems = False
|
||||
if foundallinstallitems:
|
||||
return True
|
||||
if item_pl.get('receipts'):
|
||||
if PKGDATA == {}:
|
||||
# build our database of installed packages
|
||||
analyzeInstalledPkgs()
|
||||
if item_pl['name'] in PKGDATA['installed_names']:
|
||||
return True
|
||||
|
||||
# if we got this far, we failed all the tests, so the item
|
||||
# must not be installed (or we dont't have the right info...)
|
||||
@@ -1643,9 +1640,14 @@ def processRemoval(manifestitem, cataloglist, installinfo):
|
||||
|
||||
installEvidence = False
|
||||
for item in infoitems:
|
||||
munkicommon.display_debug2('Considering item %s-%s for removal info'
|
||||
% (item['name'], item['version']))
|
||||
if evidenceThisIsInstalled(item):
|
||||
installEvidence = True
|
||||
break
|
||||
else:
|
||||
munkicommon.display_debug2('%s-%s not installed.'
|
||||
% (item['name'], item['version']))
|
||||
|
||||
if not installEvidence:
|
||||
munkicommon.display_detail('%s doesn\'t appear to be installed.' %
|
||||
@@ -1673,9 +1675,9 @@ def processRemoval(manifestitem, cataloglist, installinfo):
|
||||
elif uninstallmethod.startswith('Adobe'):
|
||||
# Adobe CS3/CS4/CS5 product
|
||||
uninstall_item = item
|
||||
elif uninstallmethod == 'remove_copied_items':
|
||||
uninstall_item = item
|
||||
elif uninstallmethod == 'remove_app':
|
||||
elif uninstallmethod in ['remove_copied_items',
|
||||
'remove_app',
|
||||
'uninstall_script']:
|
||||
uninstall_item = item
|
||||
else:
|
||||
# uninstall_method is a local script.
|
||||
@@ -1824,6 +1826,8 @@ def processRemoval(manifestitem, cataloglist, installinfo):
|
||||
elif uninstallmethod == 'remove_app':
|
||||
if uninstall_item.get('installs', None):
|
||||
iteminfo['remove_app_info'] = uninstall_item['installs'][0]
|
||||
elif uninstallmethod == 'uninstall_script':
|
||||
iteminfo['uninstall_script'] = item.get('uninstall_script','')
|
||||
|
||||
# before we add this removal to the list,
|
||||
# check for installed updates and add them to the
|
||||
|
||||
Reference in New Issue
Block a user