Tag Archives: mac

Analysis of the OS X Mountain Lion pre-install checks

There are a number of checks that are run by “Install OS X Mountain Lion.app” before it allows the installation to begin. This post is about those checks and how we (as sysadmins) can make sure that a client machine is compatible with Mountain Lion before trying to install it. These pre-install checks can be found in the distribution file of the OSInstall.mpkg file. Usually this is located in /Applications/Install OS X Mountain Lion.app/Contents/SharedSupport/OSInstall.mpkg. It’s a flat package so it needs to be expanded with pkgutil or Flat Package Editor.app before we can see the contents.

installCheckScript

The first thing to check is whether the current CPU is 64 bit capable. The machine might be running i386 kernel when the install process is started but Mountain Lion runs a 64 bit kernel. The 64 bit capability is determined by looking at the hw.cpu64bit_capable kernel parameter. This information can be looked up with sysctl command:

sysctl -n hw.cpu64bit_capable

The next check is to compare the motherboard id of the current system to a list of Apple approved id’s. The full list of compatible board id’s is stored in platformSupportValues array. The motherboard id of the current system can be found in I/O Kit registry. A command line tool ioreg provides access to these values:

ioreg -p IODeviceTree -r -n / -d 1

The above command gives a lot of other information too but we’re only interested about the “board-id” value. So grep and sed to the rescue:

ioreg -p IODeviceTree -r -n / -d 1 | grep board-id | sed 's/.*<\"\(.*\)\">/\1/'

The final important check is to make sure the machine has enough RAM. Mountain Lion requires at least 2GB of it. The installCheckScript uses hw.memsize kernel parameter to determine the amount of installed memory and compares it to 2048 * 1024 * 1024 (which is of course 2GB converted to bytes). To get the amount of installed memory from command line:

sysctl -n hw.memsize

volCheckScript

This script runs a few simpler checks and the most important ones are:

  1. Whether a Backups.backupdb directory exists on the root of a volume. This of course means that installing on top of your Time Machine backup disk is not allowed.
  2. Machine should not be running something newer than 10.8
  3. Machine should be running at least Mac OS X 10.6.6

Automated way

I’ve compiled the checks described here to a python script which looks at the machine it runs on and provides details about Mountain Lion compatibility. The script reports compatibility with exit codes (0 for supported, 1 for not supported) and prints something like this for the administrator:

./check-mountainlion-compatibility.py
Board ID: Mac-F2238BAE                    [OK]
Memory: 16 GB physical memory installed   [OK]
CPU: 64 bit capable                       [OK]
System: Mac OS X 10.8.2                   [Failed]

As usual, I’ve posted the script on GitHub:  https://github.com/hjuutilainen/adminscripts/blob/master/check-mountainlion-compatibility.py

Enjoy!

Working with Google Chrome’s automatic updates

Before we get started

First of all, this post is not about the general deployment of Google Chrome. See Nick McSpadden’s excellent Deploying and Managing Google Chrome: The Rough Guide at krypted.com for that. There’s also a Google Help page which has instructions for changing the frequency of the automatic updates and disabling them all together: Managing updates in Google Software Update. This post will mainly focus on the situation where you want Google Chrome to update itself automatically.

If you are deploying Google Chrome to centrally managed client machines, you really do not want your users to see any of this:

But instead you want your users to know that they are using the latest Google Chrome and it’s automatically updated:

Enabling automatic updates, the technical version

The first thing to do to enable Chrome automatic updates is to install and register the Google Software Update (Keystone) itself. This is done with the KeystoneRegistration.framework and specifically KeystoneRegistration.framework/Resources/install.py script. The script itself has some other options (see ./install.py --help) but we only need the system wide install. Every copy of Chrome has at least one version of this framework inside the application bundle. So if my version of Chrome is 22.0.1229.79, a demonstration command to install Keystone would be:

cd "/Applications/Google Chrome.app/Contents/Versions/22.0.1229.79/Google Chrome Framework.framework/Frameworks/KeystoneRegistration.framework/Resources/"
sudo ./install.py --install=Keystone.tbz --root=/ --force

This will install and configure Google Software Update which lives in /Library/Google/GoogleSoftwareUpdate/GoogleSoftwareUpdate.bundle after the above command.

The second part (and the trickier one) is to register Chrome with Keystone. This is done with /Library/Google/GoogleSoftwareUpdate/GoogleSoftwareUpdate.bundle/Contents/MacOS/ksadmin command line application which comes from the initial Keystone install. You can view the currently registered tickets with -p option and looking at the output of manually configured system reveals what Chrome should look like once registered:

./ksadmin -p

ksadmin requires at least 4 arguments to register an application with Keystone but looking at the ksadmin output it’s clear that Chrome wants some more. This is also confirmed by looking at the Chromium source code and its keystoneParameters method. This all results in a monster command which you would need to check every time a new version of Chrome is released:

./ksadmin --register --preserve-tttoken --productid com.google.Chrome --version 22.0.1229.79 --xcpath "/Applications/Google Chrome.app" --url https://tools.google.com/service/update2 --tag-path "/Applications/Google Chrome.app/Contents/Info.plist" --tag-key KSChannelID --brand-path "/Library/Google/Google Chrome Brand.plist" --brand-key KSBrandID --version-path "/Applications/Google Chrome.app/Contents/Info.plist" --version-key KSVersion

That’s not practical.

Enabling automatic updates, the easy version

I’ve compiled all of this in to a python script that works without customization on any recent version of Chrome. It first checks what version is installed in “/Applications/Google Chrome.app” and then setups the automatic updates accordingly. The result of running the script is that the “Setup automatic updates” button is gone from the About window and Chrome successfully updates itself.

You can get the latest version of the script here: https://github.com/hjuutilainen/adminscripts/blob/master/chrome-enable-autoupdates.py

Disabling automatic updates, the technical version

Once we get Google Chrome installed and the automatic updates configured there’s always the need to be able to uninstall it. After doing all of the above, it’s not enough to just delete Google Chrome from /Applications and be done with it. You need to consider the following two ways of uninstalling the automatic updates:

  1. Remove Chrome registration from ticket store but leave Keystone installed. This might be desired if you have some other Google products installed.
  2. Remove the whole Keystone and the ticket store (effectively removing Chrome registration too).

The Chrome registration ticket can be removed with the same ksadmin command that was used earlier to register it. For example:

cd "/Library/Google/GoogleSoftwareUpdate/GoogleSoftwareUpdate.bundle/Contents/MacOS/"
sudo ./ksadmin --delete --productid com.google.Chrome

The Keystone itself can be removed with the Keystone install script. For example:

cd "/Applications/Google Chrome.app/Contents/Versions/22.0.1229.79/Google Chrome Framework.framework/Frameworks/KeystoneRegistration.framework/Resources/"
sudo ./install.py --nuke

The --nuke option removes Keystone files and the ticket store. Note that there’s also the --uninstall option but that leaves the ticket store on disk.

Disabling automatic updates, the easy version

Fortunately I’ve wrapped the uninstall procedure to a python script. The script can easily be configured to remove just the Chrome registration or to nuke everything.

You can get the latest version of the script here: https://github.com/hjuutilainen/adminscripts/blob/master/chrome-disable-autoupdates.py

Final words

My deployment method for Google Chrome is Munki. Chrome is listed as an optional install so that users can install it if they need to. I’m running the chrome-enable-autoupdates.py script as a post install script. If the user decides to uninstall Chrome using Munki, I’m running the chrome-disable-autoupdates.py script as a post uninstall script. This has worked very well since Chrome 18.

Thanks for reading!