Exemple #1
0
def downloadAvailableUpdates():
    '''Downloads the available Apple updates using our local
    filtered sucatalog. Returns True if successful, False otherwise.'''
    msg = "Downloading available Apple Software Updates..."
    if munkicommon.munkistatusoutput:
        munkistatus.message(msg)
        munkistatus.detail("")
        munkistatus.percent(-1)
        munkicommon.log(msg)
    else:
        munkicommon.display_status(msg)

    # use our filtered local catalog
    catalogpath = os.path.join(swupdCacheDir(),
        'content/catalogs/local_download.sucatalog')
    if not os.path.exists(catalogpath):
        munkicommon.display_error(
            'Missing local Software Update catalog at %s', catalogpath)
        return False

    catalogURL = 'file://localhost' + urllib2.quote(catalogpath)
    # get the OS version
    osvers = int(os.uname()[2].split('.')[0])
    if osvers == 9:
        retcode = leopardDownloadAvailableUpdates(catalogURL)
    else:
        retcode = run_softwareupdate(['--CatalogURL', catalogURL, '-d', '-a'])

    if retcode:
        # there was an error
        munkicommon.display_error("softwareupdate error: %s" % retcode)
        return False
    return True
Exemple #2
0
def downloadAvailableUpdates():
    '''Downloads the available Apple updates using our local
    filtered sucatalog. Returns True if successful, False otherwise.'''
    msg = "Downloading available Apple Software Updates..."
    if munkicommon.munkistatusoutput:
        munkistatus.message(msg)
        munkistatus.detail("")
        munkistatus.percent(-1)
        munkicommon.log(msg)
    else:
        munkicommon.display_status(msg)

    # use our filtered local catalog
    catalogpath = os.path.join(swupdCacheDir(),
                               'content/catalogs/local_download.sucatalog')
    if not os.path.exists(catalogpath):
        munkicommon.display_error(
            'Missing local Software Update catalog at %s', catalogpath)
        return False

    catalogURL = 'file://localhost' + urllib2.quote(catalogpath)
    # get the OS version
    osvers = int(os.uname()[2].split('.')[0])
    if osvers == 9:
        retcode = leopardDownloadAvailableUpdates(catalogURL)
    else:
        retcode = run_softwareupdate(['--CatalogURL', catalogURL, '-d', '-a'])

    if retcode:
        # there was an error
        munkicommon.display_error("softwareupdate error: %s" % retcode)
        return False
    return True
Exemple #3
0
def getpathstoremove(pkgkeylist):
    """
    Queries our database for paths to remove.
    """
    pkgkeys = tuple(pkgkeylist)

    # open connection and cursor to our database
    conn = sqlite3.connect(packagedb)
    curs = conn.cursor()

    # set up some subqueries:
    # all the paths that are referred to by the selected packages:
    if len(pkgkeys) > 1:
        in_selected_packages = \
          "select distinct path_key from pkgs_paths where pkg_key in %s" % \
           str(pkgkeys)
    else:
        in_selected_packages = \
          "select distinct path_key from pkgs_paths where pkg_key = %s" % \
           str(pkgkeys[0])

    # all the paths that are referred to by every package
    # except the selected packages:
    if len(pkgkeys) > 1:
        not_in_other_packages = \
        "select distinct path_key from pkgs_paths where pkg_key not in %s" % \
         str(pkgkeys)
    else:
        not_in_other_packages = \
        "select distinct path_key from pkgs_paths where pkg_key != %s" % \
         str(pkgkeys[0])

    # every path that is used by the selected packages and no other packages:
    combined_query = \
        "select path from paths where " + \
        "(path_key in (%s) and path_key not in (%s))" % \
                                (in_selected_packages, not_in_other_packages)

    munkicommon.display_status_minor(
        'Determining which filesystem items to remove')
    if munkicommon.munkistatusoutput:
        munkistatus.percent(-1)

    curs.execute(combined_query)
    results = curs.fetchall()
    curs.close()
    conn.close()

    removalpaths = []
    for item in results:
        removalpaths.append(item[0])

    return removalpaths
def getpathstoremove(pkgkeylist):
    """
    Queries our database for paths to remove.
    """
    pkgkeys = tuple(pkgkeylist)

    # open connection and cursor to our database
    conn = sqlite3.connect(packagedb)
    curs = conn.cursor()

    # set up some subqueries:
    # all the paths that are referred to by the selected packages:
    if len(pkgkeys) > 1:
        in_selected_packages = \
          "select distinct path_key from pkgs_paths where pkg_key in %s" % \
           str(pkgkeys)
    else:
        in_selected_packages = \
          "select distinct path_key from pkgs_paths where pkg_key = %s" % \
           str(pkgkeys[0])

    # all the paths that are referred to by every package
    # except the selected packages:
    if len(pkgkeys) > 1:
        not_in_other_packages = \
        "select distinct path_key from pkgs_paths where pkg_key not in %s" % \
         str(pkgkeys)
    else:
        not_in_other_packages = \
        "select distinct path_key from pkgs_paths where pkg_key != %s" % \
         str(pkgkeys[0])

    # every path that is used by the selected packages and no other packages:
    combined_query = \
        "select path from paths where " + \
        "(path_key in (%s) and path_key not in (%s))" % \
                                (in_selected_packages, not_in_other_packages)

    munkicommon.display_status_minor(
        'Determining which filesystem items to remove')
    if munkicommon.munkistatusoutput:
        munkistatus.percent(-1)

    curs.execute(combined_query)
    results = curs.fetchall()
    curs.close()
    conn.close()

    removalpaths = []
    for item in results:
        removalpaths.append(item[0])

    return removalpaths
Exemple #5
0
def getAvailableUpdates():
    '''Returns a list of product IDs of available Apple updates'''
    msg = "Checking for available Apple Software Updates..."
    if munkicommon.munkistatusoutput:
        munkistatus.message(msg)
        munkistatus.detail("")
        munkistatus.percent(-1)
        munkicommon.log(msg)
    else:
        munkicommon.display_status(msg)

    applicable_updates = os.path.join(swupdCacheDir(),
                                      'ApplicableUpdates.plist')
    if os.path.exists(applicable_updates):
        # remove any old item
        try:
            os.unlink(applicable_updates)
        except (OSError, IOError):
            pass

    # use our locally-cached Apple catalog
    catalogpath = os.path.join(swupdCacheDir(),
                               'content/catalogs/apple_index.sucatalog')
    catalogURL = 'file://localhost' + urllib2.quote(catalogpath)
    su_options = ['--CatalogURL', catalogURL, '-l', '-f', applicable_updates]

    retcode = run_softwareupdate(su_options)
    if retcode:
        # there was an error
        osvers = int(os.uname()[2].split('.')[0])
        if osvers == 9:
            # always a non-zero retcode on Leopard
            pass
        else:
            munkicommon.display_error("softwareupdate error: %s" % retcode)
            return []

    if os.path.exists(applicable_updates):
        try:
            updatelist = FoundationPlist.readPlist(applicable_updates)
            if updatelist:
                results_array = updatelist.get('phaseResultsArray', [])
                return [
                    item['productKey'] for item in results_array
                    if 'productKey' in item
                ]
        except FoundationPlist.NSPropertyListSerializationException:
            return []
    return []
Exemple #6
0
def getAvailableUpdates():
    '''Returns a list of product IDs of available Apple updates'''
    msg = "Checking for available Apple Software Updates..."
    if munkicommon.munkistatusoutput:
        munkistatus.message(msg)
        munkistatus.detail("")
        munkistatus.percent(-1)
        munkicommon.log(msg)
    else:
        munkicommon.display_status(msg)

    applicable_updates = os.path.join(swupdCacheDir(),
                                      'ApplicableUpdates.plist')
    if os.path.exists(applicable_updates):
        # remove any old item
        try:
            os.unlink(applicable_updates)
        except (OSError, IOError):
            pass

    # use our locally-cached Apple catalog
    catalogpath = os.path.join(swupdCacheDir(),
        'content/catalogs/apple_index.sucatalog')
    catalogURL = 'file://localhost' + urllib2.quote(catalogpath)
    su_options = ['--CatalogURL', catalogURL, '-l', '-f', applicable_updates]

    retcode = run_softwareupdate(su_options)
    if retcode:
        # there was an error
        osvers = int(os.uname()[2].split('.')[0])
        if osvers == 9:
            # always a non-zero retcode on Leopard
            pass
        else:
            munkicommon.display_error("softwareupdate error: %s" % retcode)
            return []

    if os.path.exists(applicable_updates):
        try:
            updatelist = FoundationPlist.readPlist(applicable_updates)
            if updatelist:
                results_array = updatelist.get('phaseResultsArray', [])
                return [item['productKey'] for item in results_array
                        if 'productKey' in item]
        except FoundationPlist.NSPropertyListSerializationException:
            return []
    return []
Exemple #7
0
def installAppleUpdates():
    '''Uses /usr/sbin/softwareupdate to install previously
    downloaded updates. Returns True if a restart is needed
    after install, False otherwise.'''
    msg = "Installing available Apple Software Updates..."
    if munkicommon.munkistatusoutput:
        munkistatus.message(msg)
        munkistatus.detail("")
        munkistatus.percent(-1)
        munkicommon.log(msg)
    else:
        munkicommon.display_status(msg)
    restartneeded = restartNeeded()
    # use our filtered local catalog
    catalogpath = os.path.join(swupdCacheDir(),
                               'content/catalogs/local_install.sucatalog')
    if not os.path.exists(catalogpath):
        munkicommon.display_error(
            'Missing local Software Update catalog at %s', catalogpath)
        # didn't do anything, so no restart needed
        return False

    installlist = getSoftwareUpdateInfo()
    installresults = {'installed': [], 'download': []}

    catalogURL = 'file://localhost' + urllib2.quote(catalogpath)
    retcode = run_softwareupdate(['--CatalogURL', catalogURL, '-i', '-a'],
                                 mode='install',
                                 results=installresults)

    if not 'InstallResults' in munkicommon.report:
        munkicommon.report['InstallResults'] = []

    for item in installlist:
        rep = {}
        rep['name'] = item.get('display_name')
        rep['version'] = item.get('version_to_install', '')
        rep['applesus'] = True
        rep['productKey'] = item.get('productKey', '')
        message = "Apple Software Update install of %s-%s: %s"
        if rep['name'] in installresults['installed']:
            rep['status'] = 0
            install_status = 'SUCCESSFUL'
        elif rep['name'] in installresults['download']:
            rep['status'] = -1
            install_status = 'FAILED due to missing package.'
            munkicommon.display_warning(
                'Apple update %s, %s failed. A sub-package was missing '
                'on disk at time of install.' %
                (rep['name'], rep['productKey']))
        else:
            rep['status'] = -2
            install_status = 'FAILED for unknown reason'
            munkicommon.display_warning(
                'Apple update %s, %s failed to install. No record of '
                'success or failure.' % (rep['name'], rep['productKey']))

        munkicommon.report['InstallResults'].append(rep)
        log_msg = message % (rep['name'], rep['version'], install_status)
        munkicommon.log(log_msg, "Install.log")

    if retcode:
        # there was an error
        munkicommon.display_error("softwareupdate error: %s" % retcode)
    # clean up our now stale local cache
    cachedir = os.path.join(swupdCacheDir())
    if os.path.exists(cachedir):
        unused_retcode = subprocess.call(['/bin/rm', '-rf', cachedir])
    # remove the now invalid appleUpdatesFile
    try:
        os.unlink(appleUpdatesFile())
    except OSError:
        pass
    # Also clear our pref value for last check date. We may have
    # just installed an update which is a pre-req for some other update.
    # Let's check again soon.
    munkicommon.set_pref('LastAppleSoftwareUpdateCheck', None)

    return restartneeded
Exemple #8
0
     except ValueError:
         percent = -1
     munkicommon.display_percent_done(percent, 100)
 elif output.startswith('Software Update Tool'):
     # don't display this
     pass
 elif output.startswith('Copyright 2'):
     # don't display this
     pass
 elif output.startswith('Installing ') and mode == 'install':
     item = output[11:]
     if item:
         if munkicommon.munkistatusoutput:
             munkistatus.message(output)
             munkistatus.detail("")
             munkistatus.percent(-1)
             munkicommon.log(output)
         else:
             munkicommon.display_status(output)
 elif output.startswith('Installed '):
     # 10.6 / 10.7. Successful install of package name.
     if mode == 'install':
         munkicommon.display_status(output)
         results['installed'].append(output[10:])
     else:
         pass
         # don't display.
         # softwareupdate logging "Installed" at the end of a
         # successful download-only session is odd.
 elif output.startswith('Done '):
     # 10.5. Successful install of package name.
Exemple #9
0
def updateAcrobatPro(dmgpath):
    """Uses the scripts and Resources inside the Acrobat Patch application
    bundle to silently update Acrobat Pro and related apps
    Why oh why does this use a different mechanism than the other Adobe
    apps?"""

    if munkicommon.munkistatusoutput:
        munkistatus.percent(-1)

    #first mount the dmg
    munkicommon.display_status_minor(
        'Mounting disk image %s' % os.path.basename(dmgpath))
    mountpoints = mountAdobeDmg(dmgpath)
    if mountpoints:
        installroot = mountpoints[0]
        pathToAcrobatPatchApp = findAcrobatPatchApp(installroot)
    else:
        munkicommon.display_error("No mountable filesystems on %s" % dmgpath)
        return -1

    if not pathToAcrobatPatchApp:
        munkicommon.display_error("No Acrobat Patch app at %s" %
                                   pathToAcrobatPatchApp)
        munkicommon.unmountdmg(installroot)
        return -1

    # some values needed by the patching script
    resourcesDir = os.path.join(pathToAcrobatPatchApp,
                                "Contents", "Resources")
    ApplyOperation = os.path.join(resourcesDir, "ApplyOperation.py")
    callingScriptPath = os.path.join(resourcesDir, "InstallUpdates.sh")

    appList = []
    appListFile = os.path.join(resourcesDir, "app_list.txt")
    if os.path.exists(appListFile):
        fileobj = open(appListFile, mode='r', buffering=1)
        if fileobj:
            for line in fileobj.readlines():
                appList.append(line)
            fileobj.close()

    if not appList:
        munkicommon.display_error("Did not find a list of apps to update.")
        munkicommon.unmountdmg(installroot)
        return -1

    payloadNum = -1
    for line in appList:
        payloadNum = payloadNum + 1
        if munkicommon.munkistatusoutput:
            munkistatus.percent(getPercent(payloadNum + 1, len(appList) + 1))

        (appname, status) = line.split("\t")
        munkicommon.display_status_minor('Searching for %s' % appname)
        # first look in the obvious place
        pathname = os.path.join("/Applications/Adobe Acrobat 9 Pro", appname)
        if os.path.exists(pathname):
            item = {}
            item['path'] = pathname
            candidates = [item]
        else:
            # use system_profiler to search for the app
            candidates = [item for item in munkicommon.getAppData()
                          if item['path'].endswith('/' + appname)]

        # hope there's only one!
        if len(candidates) == 0:
            if status == "optional":
                continue
            else:
                munkicommon.display_error("Cannot patch %s because it "
                                          "was not found on the startup "
                                          "disk." % appname)
                munkicommon.unmountdmg(installroot)
                return -1

        if len(candidates) > 1:
            munkicommon.display_error("Cannot patch %s because we found "
                                      "more than one copy on the "
                                      "startup disk." % appname)
            munkicommon.unmountdmg(installroot)
            return -1

        munkicommon.display_status_minor('Updating %s' % appname)
        apppath = os.path.dirname(candidates[0]["path"])
        cmd = [ApplyOperation, apppath, appname, resourcesDir,
               callingScriptPath, str(payloadNum)]

        # figure out the log file path
        #patchappname = os.path.basename(pathToAcrobatPatchApp)
        #logfile_name = patchappname.split('.')[0] + str(payloadNum) + '.log'
        #homePath = os.path.expanduser("~")
        #logfile_dir = os.path.join(homePath, "Library", "Logs",
        #                                    "Adobe", "Acrobat")
        #logfile_path = os.path.join(logfile_dir, logfile_name)

        proc = subprocess.Popen(cmd, shell=False, bufsize=1,
                                stdin=subprocess.PIPE,
                                stdout=subprocess.PIPE,
                                stderr=subprocess.STDOUT)
        while (proc.poll() == None):
            time.sleep(1)
            #loginfo = getAcrobatPatchLogInfo(logfile_path)
            #if loginfo:
            #    print loginfo

        # run of patch tool completed
        retcode = proc.poll()
        if retcode != 0:
            munkicommon.display_error("Error patching %s: %s" %
                                       (appname, retcode))
            break
        else:
            munkicommon.display_status_minor(
                'Patching %s complete.' % appname)

    munkicommon.display_status_minor('Done.')
    if munkicommon.munkistatusoutput:
        munkistatus.percent(100)

    munkicommon.unmountdmg(installroot)
    return retcode
Exemple #10
0
def runAdobeInstallTool(cmd, number_of_payloads=0, killAdobeAIR=False):
    '''An abstraction of the tasks for running Adobe Setup,
    AdobeUberInstaller, AdobeUberUninstaller, AdobeDeploymentManager, etc'''
    if munkicommon.munkistatusoutput and not number_of_payloads:
        # indeterminate progress bar
        munkistatus.percent(-1)

    proc = subprocess.Popen(cmd, shell=False, bufsize=1,
                            stdin=subprocess.PIPE,
                            stdout=subprocess.PIPE, stderr=subprocess.STDOUT)

    old_payload_completed_count = 0
    payloadname = ""
    while (proc.poll() == None):
        time.sleep(1)
        (payload_completed_count, payloadname) = \
             getAdobeInstallProgressInfo(old_payload_completed_count,
                                                                payloadname)
        if payload_completed_count > old_payload_completed_count:
            old_payload_completed_count = payload_completed_count
            if payloadname:
                payloadinfo = " - " + payloadname
            else:
                payloadinfo = ""
            if number_of_payloads:
                munkicommon.display_status_minor(
                    'Completed payload %s of %s%s' %
                    (payload_completed_count, number_of_payloads,
                     payloadinfo))
            else:
                munkicommon.display_status_minor('Completed payload %s%s' %
                                       (payload_completed_count, payloadinfo))
            if munkicommon.munkistatusoutput:
                munkistatus.percent(getPercent(payload_completed_count,
                                                          number_of_payloads))

        # Adobe AIR Installer workaround/hack
        # CSx installs at the loginwindow hang when Adobe AIR is installed.
        # So we check for this and kill the process. Ugly.
        # Hopefully we can disable this in the future.
        if killAdobeAIR:
            if (not munkicommon.getconsoleuser() or
                   munkicommon.getconsoleuser() == u"loginwindow"):
                # we're at the loginwindow.
                killStupidProcesses()

    # run of tool completed
    retcode = proc.poll()

    #check output for errors
    output = proc.stdout.readlines()
    for line in output:
        line = line.rstrip("\n")
        if line.startswith("Error"):
            munkicommon.display_error(line)
        if line.startswith("Exit Code:"):
            if retcode == 0:
                try:
                    retcode = int(line[11:])
                except (ValueError, TypeError):
                    retcode = -1

    if retcode != 0 and retcode != 8:
        munkicommon.display_error("Adobe Setup error: %s: %s" %
                                   (retcode, adobeSetupError(retcode)))
    else:
        if munkicommon.munkistatusoutput:
            munkistatus.percent(100)
        munkicommon.display_status_minor('Done.')

    return retcode
Exemple #11
0
def installAppleUpdates():
    '''Uses /usr/sbin/softwareupdate to install previously
    downloaded updates. Returns True if a restart is needed
    after install, False otherwise.'''
    msg = "Installing available Apple Software Updates..."
    if munkicommon.munkistatusoutput:
        munkistatus.message(msg)
        munkistatus.detail("")
        munkistatus.percent(-1)
        munkicommon.log(msg)
    else:
        munkicommon.display_status(msg)
    restartneeded = restartNeeded()
    # use our filtered local catalog
    catalogpath = os.path.join(swupdCacheDir(),
        'content/catalogs/local_install.sucatalog')
    if not os.path.exists(catalogpath):
        munkicommon.display_error(
            'Missing local Software Update catalog at %s', catalogpath)
        # didn't do anything, so no restart needed
        return False

    installlist = getSoftwareUpdateInfo()
    installresults = {'installed':[], 'download':[]}

    catalogURL = 'file://localhost' + urllib2.quote(catalogpath)
    retcode = run_softwareupdate(['--CatalogURL', catalogURL, '-i', '-a'],
                                 mode='install', results=installresults)

    if not 'InstallResults' in munkicommon.report:
        munkicommon.report['InstallResults'] = []

    for item in installlist:
        rep = {}
        rep['name'] = item.get('display_name')
        rep['version'] = item.get('version_to_install', '')
        rep['applesus'] = True
        rep['productKey'] = item.get('productKey', '')
        message = "Apple Software Update install of %s-%s: %s"
        if rep['name'] in installresults['installed']:
            rep['status'] = 0
            install_status = 'SUCCESSFUL'
        elif rep['name'] in installresults['download']:
            rep['status'] = -1
            install_status = 'FAILED due to missing package.'
            munkicommon.display_warning(
                'Apple update %s, %s failed. A sub-package was missing '
                'on disk at time of install.'
                % (rep['name'], rep['productKey']))
        else:
            rep['status'] = -2
            install_status = 'FAILED for unknown reason'
            munkicommon.display_warning(
                'Apple update %s, %s failed to install. No record of '
                'success or failure.' % (rep['name'],rep['productKey']))

        munkicommon.report['InstallResults'].append(rep)
        log_msg = message % (rep['name'], rep['version'], install_status)
        munkicommon.log(log_msg, "Install.log")

    if retcode:
        # there was an error
        munkicommon.display_error("softwareupdate error: %s" % retcode)
    # clean up our now stale local cache
    cachedir = os.path.join(swupdCacheDir())
    if os.path.exists(cachedir):
        unused_retcode = subprocess.call(['/bin/rm', '-rf', cachedir])
    # remove the now invalid appleUpdatesFile
    try:
        os.unlink(appleUpdatesFile())
    except OSError:
        pass
    # Also clear our pref value for last check date. We may have
    # just installed an update which is a pre-req for some other update.
    # Let's check again soon.
    munkicommon.set_pref('LastAppleSoftwareUpdateCheck', None)

    return restartneeded
Exemple #12
0
     except ValueError:
         percent = -1
     munkicommon.display_percent_done(percent, 100)
 elif output.startswith('Software Update Tool'):
     # don't display this
     pass
 elif output.startswith('Copyright 2'):
     # don't display this
     pass
 elif output.startswith('Installing ') and mode == 'install':
     item = output[11:]
     if item:
         if munkicommon.munkistatusoutput:
             munkistatus.message(output)
             munkistatus.detail("")
             munkistatus.percent(-1)
             munkicommon.log(output)
         else:
             munkicommon.display_status(output)
 elif output.startswith('Installed '):
     # 10.6 / 10.7. Successful install of package name.
     if mode == 'install':
         munkicommon.display_status(output)
         results['installed'].append(output[10:])
     else:
         pass
         # don't display.
         # softwareupdate logging "Installed" at the end of a
         # successful download-only session is odd.
 elif output.startswith('Done '):
     # 10.5. Successful install of package name.