mirror of
https://github.com/munki/munki.git
synced 2026-04-23 04:59:17 -05:00
munkilib.py:
- changes to pythonScriptRunning() to allow the tools to detect if another instance of themselves is running - updated getBundlePackageInfo() to handle pre-dist style .mpkgs removepackages.py: - changes to handle multiple receipts with the same packageid installcheck: - removed random sleep option - this will move to another tool so we don't have installcheck itself sleeping; this prevented the other tools from running if you happened to, say, call managedinstaller while installcheck was sleeping. - installcheck checks to see if another instance of itself is running and exits if so - suppress errors when getting the primary manifest and trying long hostname, then short hostname, then "site_default". makecatalogs: - don't try to process ._ files or .DS_Store files. makepkginfo: - try to generate a better installer_item_location if the path has "/pkgs" in it git-svn-id: http://munki.googlecode.com/svn/trunk@110 a4e17f2e-e282-11dd-95e1-755cbddbdd66
This commit is contained in:
+29
-21
@@ -369,12 +369,15 @@ def getInstalledVersion(pl):
|
||||
Attempts to determine the currently installed version of the item
|
||||
described by pl
|
||||
"""
|
||||
|
||||
if 'receipts' in pl:
|
||||
if len(pl['receipts']) == 1:
|
||||
pkgid = pl['receipts'][0]['packageid']
|
||||
installedvers = munkilib.getInstalledPackageVersion(pkgid)
|
||||
if installedvers:
|
||||
return installedvers
|
||||
maxversion = "0.0.0.0.0"
|
||||
for receipt in pl['receipts']:
|
||||
pkgvers = munkilib.getInstalledPackageVersion(receipt['packageid'])
|
||||
if compareVersions(pkgvers, maxversion) == 2:
|
||||
# version is higher
|
||||
maxversion = pkgvers
|
||||
return maxversion
|
||||
|
||||
if 'installs' in pl:
|
||||
for install_item in pl['installs']:
|
||||
@@ -1118,6 +1121,7 @@ def getPrimaryManifest(alternate_id):
|
||||
"""
|
||||
Gets the client manifest from the server
|
||||
"""
|
||||
global errors
|
||||
managedinstallprefs = munkilib.prefs()
|
||||
manifesturl = managedinstallprefs['ManifestURL']
|
||||
clientidentifier = managedinstallprefs.get('ClientIdentifier','')
|
||||
@@ -1134,18 +1138,21 @@ def getPrimaryManifest(alternate_id):
|
||||
# no client identifier specified, so use the hostname
|
||||
hostname = os.uname()[1]
|
||||
manifest = getmanifest(manifesturl + hostname)
|
||||
if manifest:
|
||||
return manifest
|
||||
else:
|
||||
if not manifest:
|
||||
# try the short hostname
|
||||
manifest = getmanifest(manifesturl + hostname.split('.')[0])
|
||||
if manifest:
|
||||
return manifest
|
||||
else:
|
||||
if not manifest:
|
||||
# last resort - try for the site_default manifest
|
||||
manifesturl = manifesturl + "site_default"
|
||||
|
||||
return getmanifest(manifesturl)
|
||||
|
||||
if not manifest:
|
||||
manifest = getmanifest(manifesturl)
|
||||
if manifest:
|
||||
# clear out any errors we got while try to find
|
||||
# the primary manifest
|
||||
errors = ""
|
||||
|
||||
return manifest
|
||||
|
||||
|
||||
def getInstallCount(installinfo):
|
||||
@@ -1289,8 +1296,6 @@ p.add_option('--id', '-i', default='',
|
||||
help='Alternate identifier for catalog retreival')
|
||||
p.add_option('--quiet', '-q', action='store_true',
|
||||
help='Quiet mode. Logs messages, but nothing to stdout.')
|
||||
p.add_option('--randomsleep', '-r', type='int', default=0,
|
||||
help='Randomly sleeps up to the given number of seconds before checking.')
|
||||
p.add_option('--verbose', '-v', action='count', default=0,
|
||||
help='More verbose output. May be specified multiple times.')
|
||||
options, arguments = p.parse_args()
|
||||
@@ -1323,17 +1328,20 @@ def main():
|
||||
exit(-1)
|
||||
log("### Beginning managed software check ###")
|
||||
|
||||
if options.randomsleep:
|
||||
randomsleepseconds = random.randrange(options.randomsleep+1)
|
||||
printandlog("Sleeping %i seconds..." % randomsleepseconds)
|
||||
time.sleep(randomsleepseconds)
|
||||
|
||||
if munkilib.pythonScriptRunning("managedinstaller"):
|
||||
# managedinstaller is running, so we should quit
|
||||
printandlog("managedinstaller is running. Exiting.")
|
||||
log("### End managed software check ###")
|
||||
exit(0)
|
||||
|
||||
# check to see if another instance of this script is running
|
||||
myname = os.path.basename(sys.argv[0])
|
||||
if munkilib.pythonScriptRunning(myname):
|
||||
# another instance of this script is running, so we should quit
|
||||
printandlog("Another instance of %s is running. Exiting." % myname)
|
||||
log("### End managed software check ###")
|
||||
exit(0)
|
||||
|
||||
mainmanifestpath = getPrimaryManifest(options.id)
|
||||
if not mainmanifestpath:
|
||||
logerror("Could not retreive managed install primary manifest.")
|
||||
@@ -1342,7 +1350,7 @@ def main():
|
||||
# logging to a local file isn't really sufficient.
|
||||
reporterrors()
|
||||
exit(-1)
|
||||
|
||||
|
||||
# initialize our installinfo record
|
||||
installinfo = {}
|
||||
installinfo['managed_installs'] = []
|
||||
|
||||
+19
-18
@@ -52,24 +52,25 @@ def makeCatalogs(repopath):
|
||||
for dirpath, dirnames, filenames in os.walk(pkgsinfopath):
|
||||
subdir = dirpath[len(pkgsinfopath):]
|
||||
for name in filenames:
|
||||
filepath = os.path.join(dirpath,name)
|
||||
if validPlist(filepath):
|
||||
#if it's a valid plist, assume it's a pkginfo file
|
||||
pkginfo = plistlib.readPlist(filepath)
|
||||
#simple sanity checking
|
||||
if 'installer_item_location' in pkginfo:
|
||||
installeritempath = os.path.join(repopath, "pkgs", pkginfo['installer_item_location'])
|
||||
if os.path.exists(installeritempath):
|
||||
catalogs['all'].append(pkginfo)
|
||||
for catalogname in pkginfo.get("catalogs",[]):
|
||||
if not catalogname in catalogs:
|
||||
catalogs[catalogname] = []
|
||||
catalogs[catalogname].append(pkginfo)
|
||||
print "Adding %s to %s..." % (filepath[len(pkgsinfopath)+1:], catalogname)
|
||||
else:
|
||||
print >>sys.stderr, "WARNING: Info file %s refers to missing installer item: %s" % (filepath[len(pkgsinfopath)+1:], pkginfo['installer_item_location'])
|
||||
else:
|
||||
print >>sys.stderr, "WARNING: file %s is not a valid plist" % filepath
|
||||
if not name.startswith("._") and name != ".DS_Store":
|
||||
filepath = os.path.join(dirpath,name)
|
||||
if validPlist(filepath):
|
||||
#if it's a valid plist, assume it's a pkginfo file
|
||||
pkginfo = plistlib.readPlist(filepath)
|
||||
#simple sanity checking
|
||||
if 'installer_item_location' in pkginfo:
|
||||
installeritempath = os.path.join(repopath, "pkgs", pkginfo['installer_item_location'])
|
||||
if os.path.exists(installeritempath):
|
||||
catalogs['all'].append(pkginfo)
|
||||
for catalogname in pkginfo.get("catalogs",[]):
|
||||
if not catalogname in catalogs:
|
||||
catalogs[catalogname] = []
|
||||
catalogs[catalogname].append(pkginfo)
|
||||
print "Adding %s to %s..." % (filepath[len(pkgsinfopath)+1:], catalogname)
|
||||
else:
|
||||
print >>sys.stderr, "WARNING: Info file %s refers to missing installer item: %s" % (filepath[len(pkgsinfopath)+1:], pkginfo['installer_item_location'])
|
||||
else:
|
||||
print >>sys.stderr, "WARNING: file %s is not a valid plist" % filepath
|
||||
|
||||
# clear out old catalogs
|
||||
path = os.path.join(repopath, "catalogs")
|
||||
|
||||
+15
-2
@@ -217,8 +217,21 @@ def main():
|
||||
print >>sys.stderr, "Item %s doesn't exist. Skipping." % fitem
|
||||
catinfo['installs'] = installs
|
||||
|
||||
name = os.path.split(item)[1]
|
||||
catinfo['installer_item_location'] = name
|
||||
# try to generate the correct item location
|
||||
temppath = item
|
||||
location = ""
|
||||
while len(temppath) > 4:
|
||||
if temppath.endswith('/pkgs'):
|
||||
location = item[len(temppath)+1:]
|
||||
break
|
||||
else:
|
||||
temppath = os.path.dirname(temppath)
|
||||
|
||||
if not location:
|
||||
#just the filename
|
||||
location = os.path.split(item)[1]
|
||||
catinfo['installer_item_location'] = location
|
||||
|
||||
if minosversion:
|
||||
catinfo['minimum_os_version'] = minosversion
|
||||
else:
|
||||
|
||||
@@ -416,6 +416,15 @@ def main():
|
||||
log("installcheck is running. Exiting.")
|
||||
log("### End managed installer session ###")
|
||||
exit(0)
|
||||
|
||||
# check to see if another instance of this script is running
|
||||
myname = os.path.basename(sys.argv[0])
|
||||
if munkilib.pythonScriptRunning(myname):
|
||||
# another instance of this script is running, so we should quit
|
||||
print "Another instance of %s is running. Exiting." % myname
|
||||
log("Another instance of %s is running. Exiting." % myname)
|
||||
log("### End managed installer session ###")
|
||||
exit(0)
|
||||
|
||||
installinfo = os.path.join(managedinstallbase, 'InstallInfo.plist')
|
||||
if os.path.exists(installinfo):
|
||||
|
||||
+89
-45
@@ -70,18 +70,21 @@ def getconsoleuser():
|
||||
|
||||
|
||||
def pythonScriptRunning(scriptname):
|
||||
cmd = ['/bin/ps', '-eo', 'command=']
|
||||
cmd = ['/bin/ps', '-eo', 'pid=,command=']
|
||||
p = subprocess.Popen(cmd, shell=False, bufsize=1, stdin=subprocess.PIPE,
|
||||
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
(out, err) = p.communicate()
|
||||
mypid = os.getpid()
|
||||
lines = out.splitlines()
|
||||
for line in lines:
|
||||
(pid, proc) = line.split(None,1)
|
||||
# first look for Python processes
|
||||
if line.find("MacOS/Python ") != -1:
|
||||
if line.find(scriptname) != -1:
|
||||
return True
|
||||
if proc.find("MacOS/Python ") != -1:
|
||||
if proc.find(scriptname) != -1:
|
||||
if int(pid) != int(mypid):
|
||||
return pid
|
||||
|
||||
return False
|
||||
return 0
|
||||
|
||||
|
||||
# dmg helpers
|
||||
@@ -233,19 +236,22 @@ def getExtendedVersion(bundlepath):
|
||||
pl = {}
|
||||
if os.path.exists(versionPlist):
|
||||
pl = plistlib.readPlist(versionPlist)
|
||||
elif os.path.exists(infoPlist):
|
||||
if pl:
|
||||
shortVers = "0.0.0"
|
||||
sourceVers = "0"
|
||||
buildVers = "0"
|
||||
if "CFBundleShortVersionString" in pl:
|
||||
shortVers = padVersionString(pl["CFBundleShortVersionString"],3)
|
||||
if "SourceVersion" in pl:
|
||||
sourceVers = padVersionString(pl["SourceVersion"],1)
|
||||
if "BuildVersion" in pl:
|
||||
buildVers = padVersionString(pl["BuildVersion"],1)
|
||||
return shortVers + "." + sourceVers + "." + buildVers
|
||||
|
||||
if os.path.exists(infoPlist):
|
||||
pl = plistlib.readPlist(infoPlist)
|
||||
if pl:
|
||||
shortVers = "0.0.0"
|
||||
sourceVers = "0"
|
||||
buildVers = "0"
|
||||
if "CFBundleShortVersionString" in pl:
|
||||
shortVers = padVersionString(pl["CFBundleShortVersionString"],3)
|
||||
if "SourceVersion" in pl:
|
||||
sourceVers = padVersionString(pl["SourceVersion"],1)
|
||||
if "BuildVersion" in pl:
|
||||
buildVers = padVersionString(pl["BuildVersion"],1)
|
||||
return shortVers + "." + sourceVers + "." + buildVers
|
||||
return padVersionString(pl["CFBundleShortVersionString"],5)
|
||||
else:
|
||||
return "0.0.0.0.0"
|
||||
|
||||
@@ -314,27 +320,36 @@ def getFlatPackageInfo(pkgpath):
|
||||
return infoarray
|
||||
|
||||
|
||||
def getOnePackageInfo(pkgpath):
|
||||
pkginfo = {}
|
||||
plistpath = os.path.join(pkgpath, "Contents", "Info.plist")
|
||||
if os.path.exists(plistpath):
|
||||
pkginfo['filename'] = os.path.basename(pkgpath)
|
||||
pl = plistlib.readPlist(plistpath)
|
||||
|
||||
if "CFBundleIdentifier" in pl:
|
||||
pkginfo['id'] = pl["CFBundleIdentifier"]
|
||||
else:
|
||||
pkginfo['id'] = os.path.basename(pkgpath)
|
||||
|
||||
if "CFBundleName" in pl:
|
||||
pkginfo['name'] = pl["CFBundleName"]
|
||||
|
||||
if "IFPkgFlagInstalledSize" in pl:
|
||||
pkginfo['installed_size'] = pl["IFPkgFlagInstalledSize"]
|
||||
|
||||
pkginfo['version'] = getExtendedVersion(pkgpath)
|
||||
return pkginfo
|
||||
|
||||
|
||||
def getBundlePackageInfo(pkgpath):
|
||||
infoarray = []
|
||||
pkginfo = {}
|
||||
|
||||
|
||||
if pkgpath.endswith(".pkg"):
|
||||
plistpath = os.path.join(pkgpath, "Contents", "Info.plist")
|
||||
if os.path.exists(plistpath):
|
||||
pl = plistlib.readPlist(plistpath)
|
||||
if debug:
|
||||
for key in pl:
|
||||
print key, "=>", pl[key]
|
||||
|
||||
if "CFBundleIdentifier" in pl:
|
||||
pkginfo['id'] = pl["CFBundleIdentifier"]
|
||||
|
||||
if "IFPkgFlagInstalledSize" in pl:
|
||||
pkginfo['installed_size'] = pl["IFPkgFlagInstalledSize"]
|
||||
|
||||
pkginfo['version'] = getExtendedVersion(pkgpath)
|
||||
infoarray.append(pkginfo)
|
||||
return infoarray
|
||||
pkginfo = getOnePackageInfo(pkgpath)
|
||||
if pkginfo:
|
||||
infoarray.append(pkginfo)
|
||||
return infoarray
|
||||
|
||||
bundlecontents = os.path.join(pkgpath, "Contents")
|
||||
if os.path.exists(bundlecontents):
|
||||
@@ -343,7 +358,27 @@ def getBundlePackageInfo(pkgpath):
|
||||
filename = os.path.join(bundlecontents, item)
|
||||
infoarray = parsePkgRefs(filename)
|
||||
return infoarray
|
||||
|
||||
|
||||
# no .dist file found, look for packages in subdirs
|
||||
dirsToSearch = []
|
||||
plistpath = os.path.join(pkgpath, "Contents", "Info.plist")
|
||||
if os.path.exists(plistpath):
|
||||
pl = plistlib.readPlist(plistpath)
|
||||
if 'IFPkgFlagComponentDirectory' in pl:
|
||||
dirsToSearch.append(pl['IFPkgFlagComponentDirectory'])
|
||||
|
||||
if dirsToSearch == []:
|
||||
dirsToSearch = ['Contents', 'Contents/Packages', 'Contents/Resources', 'Contents/Resources/Packages']
|
||||
for subdir in dirsToSearch:
|
||||
searchdir = os.path.join(pkgpath, subdir)
|
||||
if os.path.exists(searchdir):
|
||||
for item in os.listdir(searchdir):
|
||||
itempath = os.path.join(searchdir, item)
|
||||
if os.path.isdir(itempath) and itempath.endswith(".pkg"):
|
||||
pkginfo = getOnePackageInfo(itempath)
|
||||
if pkginfo:
|
||||
infoarray.append(pkginfo)
|
||||
|
||||
return infoarray
|
||||
|
||||
|
||||
@@ -401,6 +436,7 @@ def getInstalledPackageVersion(pkgid):
|
||||
receiptsdir = "/Library/Receipts"
|
||||
if os.path.exists(receiptsdir):
|
||||
installitems = os.listdir(receiptsdir)
|
||||
highestversion = "0"
|
||||
for item in installitems:
|
||||
if item.endswith(".pkg"):
|
||||
info = getBundlePackageInfo(os.path.join(receiptsdir, item))
|
||||
@@ -409,7 +445,11 @@ def getInstalledPackageVersion(pkgid):
|
||||
foundbundleid = infoitem['id']
|
||||
foundvers = infoitem['version']
|
||||
if pkgid == foundbundleid:
|
||||
return foundvers
|
||||
if version.LooseVersion(foundvers) > version.LooseVersion(highestversion):
|
||||
highestversion = foundvers
|
||||
|
||||
if highestversion != "0":
|
||||
return highestversion
|
||||
|
||||
# If we got to this point, we haven't found the pkgid yet.
|
||||
# Now check new (Leopard) package database
|
||||
@@ -492,20 +532,22 @@ def getPackageMetaData(pkgitem):
|
||||
|
||||
installerinfo = getInstallerPkgInfo(pkgitem)
|
||||
info = getPkgInfo(pkgitem)
|
||||
|
||||
name = os.path.split(pkgitem)[1]
|
||||
shortname = os.path.splitext(name)[0]
|
||||
metaversion = getExtendedVersion(pkgitem)
|
||||
if metaversion == "0.0.0.0.0":
|
||||
metaversion = nameAndVersion(shortname)[1]
|
||||
|
||||
highestpkgversion = "0.0"
|
||||
for infoitem in info:
|
||||
if version.LooseVersion(infoitem['version']) > version.LooseVersion(highestpkgversion):
|
||||
highestpkgversion = infoitem['version']
|
||||
if "installed_size" in infoitem:
|
||||
# note this is in KBytes
|
||||
installedsize += infoitem['installed_size']
|
||||
|
||||
name = os.path.split(pkgitem)[1]
|
||||
shortname = os.path.splitext(name)[0]
|
||||
metaversion = nameAndVersion(shortname)[1]
|
||||
if not len(metaversion):
|
||||
# there is no version number in the filename
|
||||
if "installed_size" in infoitem:
|
||||
# note this is in KBytes
|
||||
installedsize += infoitem['installed_size']
|
||||
|
||||
if metaversion == "0.0.0.0.0":
|
||||
metaversion = highestpkgversion
|
||||
elif len(info) == 1:
|
||||
# there is only one package in this item
|
||||
@@ -531,6 +573,8 @@ def getPackageMetaData(pkgitem):
|
||||
cataloginfo['receipts'] = []
|
||||
for infoitem in info:
|
||||
pkginfo = {}
|
||||
if 'filename' in infoitem:
|
||||
pkginfo['filename'] = infoitem['filename']
|
||||
pkginfo['packageid'] = infoitem['id']
|
||||
pkginfo['version'] = infoitem['version']
|
||||
cataloginfo['receipts'].append(pkginfo)
|
||||
|
||||
@@ -614,15 +614,17 @@ def getpkgkeys(pkgnames):
|
||||
pkgkeyslist = []
|
||||
for pkg in pkgnames:
|
||||
t = (pkg, )
|
||||
pkg_key = c.execute('select pkg_key from pkgs where pkgname = ?', t).fetchone()
|
||||
if pkg_key is None:
|
||||
pkg_keys = c.execute('select pkg_key from pkgs where pkgname = ?', t).fetchall()
|
||||
if not pkg_keys:
|
||||
# try pkgid
|
||||
pkg_key = c.execute('select pkg_key from pkgs where pkgid = ?', t).fetchone()
|
||||
if pkg_key is None:
|
||||
pkg_keys = c.execute('select pkg_key from pkgs where pkgid = ?', t).fetchall()
|
||||
if not pkg_keys:
|
||||
display_error("%s not found in database." % pkg)
|
||||
pkgerror = True
|
||||
else:
|
||||
pkgkeyslist.append(pkg_key[0])
|
||||
for row in pkg_keys:
|
||||
# only want first column
|
||||
pkgkeyslist.append(row[0])
|
||||
if pkgerror:
|
||||
pkgkeyslist = []
|
||||
c.close
|
||||
|
||||
Reference in New Issue
Block a user