Home > create_vmware_osx_install_dmg, Mac administration, Mac OS X, Scripting, VMware, VMware ESXi > create_vmware_osx_install_dmg script updated with Mavericks support

create_vmware_osx_install_dmg script updated with Mavericks support

I’ve updated the create_vmware_osx_install_dmg.sh script that I had previously posted about here. The script now includes support for Mavericks, so the script can now be run on 10.7 – 10.9 to create custom OS X 10.7.x, 10.8.x and 10.9.x installers for VMware Fusion and VMware ESXi. See below the jump for the details.

See below an example of running the script on 10.8.x to create custom OS X 10.9.x installers disk images for both Fusion and ESXi:

Screen Shot 2013-10-22 at 10.09.59 PM

Screen Shot 2013-10-22 at 10.12.19 PM

Once the run completes, you should have two disk images. One will be a .dmg for use with VMware Fusion and an .iso for use with VMware ESXi.

Screen Shot 2013-10-22 at 10.20.46 PM

For more details on configuring and running the script, see the previous posts that I’ve made about this script. The updated script is below and has also been posted to my GitHub repo.


#!/bin/sh
#
# Preparation script for a customized OS X installer for use with VWware Fusion and ESXi
#
# What the script does, in more detail:
#
# 1. Mounts the InstallESD.dmg using a shadow file, so the original DMG is left
# unchanged.
# 2. minstallconfig.xml is also copied, which is looked for by the installer environment's
# rc.* files that first load with the system. This allows us to never actually modify the
# BaseSystem.dmg and only drop in these extra files.
# 3. Additional installer packages can be added using First Boot Package Install.pkg,
# which is added to the OS X install by way of the OSInstall.collection file. The instructions
# on how to use this package are documented here:
# https://github.com/rtrouton/First-Boot-Package-Install
# 4. If desired, a second disk image in .iso format can be generated for use with VMware ESXi
# servers running on Apple hardware.
#
# Original script written by Tim Sutton:
# https://github.com/timsutton/osx-vm-templates/tree/master/prepare_iso
#
# Thanks: (brought over from Tim's original script)
# Idea and much of the implementation thanks to Pepijn Bruienne, who's also provided
# some process notes here: https://gist.github.com/4542016. The sample minstallconfig.xml,
# use of OSInstall.collection and readme documentation provided with Greg Neagle's
# createOSXInstallPkg tool also proved very helpful. (http://code.google.com/p/munki/wiki/InstallingOSX)
# User creation via package install method also credited to Greg, and made easy with Per
# Olofsson's CreateUserPkg (http://magervalp.github.io/CreateUserPkg)
usage() {
cat <<EOF
Usage:
$(basename "$0") "/path/to/InstallESD.dmg" /path/to/output/directory
$(basename "$0") "/path/to/Install OS X Mavericks / Mountain Lion / Lion.app" /path/to/output/directory
Description:
Converts a 10.7/10.8/10.9 installer image to a new image that contains components
used to perform an automated installation. The new image will be named
'OSX_InstallESD_[osversion].dmg.'
EOF
}
msg_status() {
echo "\033[0;32m– $1\033[0m"
}
msg_error() {
echo "\033[0;31m– $1\033[0m"
}
if [ $# -eq 0 ]; then
usage
exit 1
fi
if [ $(id -u) -ne 0 ]; then
msg_error "This script must be run as root, as it saves a disk image with ownerships enabled."
exit 1
fi
ESD="$1"
if [ ! -e "$ESD" ]; then
msg_error "Input installer image $ESD could not be found! Exiting.."
exit 1
fi
if [ -d "$ESD" ]; then
# we might be an install .app
if [ -e "$ESD/Contents/SharedSupport/InstallESD.dmg" ]; then
ESD="$ESD/Contents/SharedSupport/InstallESD.dmg"
else
msg_error "Can't locate an InstallESD.dmg in this source location $ESD!"
fi
fi
SCRIPT_DIR="$(cd $(dirname "$0"); pwd)"
DEFINITION_DIR="$(cd $SCRIPT_DIR/..; pwd)"
if [ "$2" == "" ]; then
msg_error "Currently an explicit output directory is required as the second argument."
exit 1
else
OUT_DIR="$2"
fi
if [ ! -d "$OUT_DIR" ]; then
msg_status "Destination dir $OUT_DIR doesn't exist, creating.."
mkdir -p "$OUT_DIR"
fi
if [ -e "$ESD.shadow" ]; then
msg_status "Removing old shadow file.."
rm "$ESD.shadow"
fi
# Script will prompt user if they want an additional image in .iso
# format for use with a VMware ESXi server.
echo "Do you also want an ISO disk image for use with VMware ESXi?"
select yn in "Yes" "No"; do
case $yn in
Yes) ISO=1; break;;
No ) msg_error "ISO disk image will not be created. Proceeding.."; break;;
esac
done
MNT_ESD=$(/usr/bin/mktemp -d /tmp/vmware-osx-esd.XXXX)
SHADOW_FILE=$(/usr/bin/mktemp /tmp/vmware-osx-shadow.XXXX)
rm "$SHADOW_FILE"
msg_status "Attaching input OS X installer image with shadow file.."
hdiutil attach "$ESD" -mountpoint "$MNT_ESD" -shadow "$SHADOW_FILE" -nobrowse -owners on
if [ $? -ne 0 ]; then
[ ! -e "$ESD" ] && msg_error "Could not find $ESD in $(pwd)"
msg_error "Could not mount $ESD on $MNT_ESD"
exit 1
fi
msg_status "Mounting BaseSystem.."
BASE_SYSTEM_DMG="$MNT_ESD/BaseSystem.dmg"
MNT_BASE_SYSTEM=$(/usr/bin/mktemp -d /tmp/vmware-osx-basesystem.XXXX)
[ ! -e "$BASE_SYSTEM_DMG" ] && msg_error "Could not find BaseSystem.dmg in $MNT_ESD"
hdiutil attach "$BASE_SYSTEM_DMG" -mountpoint "$MNT_BASE_SYSTEM" -nobrowse -owners on
if [ $? -ne 0 ]; then
msg_error "Could not mount $BASE_SYSTEM_DMG on $MNT_BASE_SYSTEM"
exit 1
fi
SYSVER_PLIST_PATH="$MNT_BASE_SYSTEM/System/Library/CoreServices/SystemVersion.plist"
DMG_OS_VERS=$(/usr/libexec/PlistBuddy -c 'Print :ProductVersion' "$SYSVER_PLIST_PATH")
DMG_OS_VERS_MAJOR=$(echo $DMG_OS_VERS | awk -F "." '{print $2}')
DMG_OS_VERS_MINOR=$(echo $DMG_OS_VERS | awk -F "." '{print $3}')
DMG_OS_BUILD=$(/usr/libexec/PlistBuddy -c 'Print :ProductBuildVersion' "$SYSVER_PLIST_PATH")
msg_status "OS X version detected: 10.$DMG_OS_VERS_MAJOR.$DMG_OS_VERS_MINOR, build $DMG_OS_BUILD"
OUTPUT_DMG="$OUT_DIR/OSX_InstallESD_${DMG_OS_VERS}_${DMG_OS_BUILD}.dmg"
if [ -e "$OUTPUT_DMG" ]; then
msg_error "Output file $OUTPUT_DMG already exists! We're not going to overwrite it, exiting.."
# hdiutil detach "$MNT_ESD"
hdiutil detach -force "$MNT_ESD"
exit 1
fi
SUPPORT_DIR="$SCRIPT_DIR/support"
# Add First Boot Package Install.pkg to the OS X installer
FIRSTBOOT_PKG="$SUPPORT_DIR/First Boot Package Install.pkg"
# We'd previously mounted this to check versions
hdiutil detach "$MNT_BASE_SYSTEM"
BASE_SYSTEM_DMG_RW="$(/usr/bin/mktemp /tmp/vmware-osx-basesystem-rw.XXXX).dmg"
msg_status "Converting BaseSystem.dmg to a read-write DMG located at $BASE_SYSTEM_DMG_RW.."
# hdiutil convert -o will actually append .dmg to the filename if it has no extn
hdiutil convert -format UDRW -o "$BASE_SYSTEM_DMG_RW" "$BASE_SYSTEM_DMG"
if [[ $DMG_OS_VERS_MAJOR -ge 9 ]]; then
msg_status "Growing new BaseSystem.."
hdiutil resize -size 6G "$BASE_SYSTEM_DMG_RW"
fi
msg_status "Mounting new BaseSystem.."
hdiutil attach "$BASE_SYSTEM_DMG_RW" -mountpoint "$MNT_BASE_SYSTEM" -nobrowse -owners on
if [[ $DMG_OS_VERS_MAJOR -ge 9 ]]; then
rm "$MNT_BASE_SYSTEM/System/Installation/Packages"
msg_status "Moving 'Packages' directory from the ESD to BaseSystem.."
mv -v "$MNT_ESD/Packages" "$MNT_BASE_SYSTEM/System/Installation/"
PACKAGES_DIR="$MNT_BASE_SYSTEM/System/Installation/Packages"
else
PACKAGES_DIR="$MNT_ESD/Packages"
fi
# Adding a custom rc.cdrom.local that will automatically erase the VM's
# boot drive. Also adding our auto-setup files: minstallconfig.xml and
# OSInstall.collection
msg_status "Adding automated components.."
CDROM_LOCAL="$MNT_BASE_SYSTEM/private/etc/rc.cdrom.local"
echo "diskutil eraseDisk jhfs+ \"Macintosh HD\" GPTFormat disk0" > "$CDROM_LOCAL"
chmod a+x "$CDROM_LOCAL"
mkdir "$PACKAGES_DIR/Extras"
cp "$SUPPORT_DIR/minstallconfig.xml" "$PACKAGES_DIR/Extras/"
cp "$SUPPORT_DIR/OSInstall.collection" "$PACKAGES_DIR/"
#cp "$SUPPORT_DIR/PartitionInfo.plist" "$PACKAGES_DIR/Extras/"
#cp -R "$AUTOPART_TOOL" "$PACKAGES_DIR/Extras/AutoPartition.app"
cp -r "$FIRSTBOOT_PKG" "$PACKAGES_DIR/"
rm -rf "$SUPPORT_DIR/tmp"
msg_status "Unmounting BaseSystem.."
hdiutil detach "$MNT_BASE_SYSTEM"
if [ $DMG_OS_VERS_MAJOR -lt 9 ]; then
msg_status "Pre-Mavericks we save back the modified BaseSystem to the root of the ESD."
rm "$MNT_ESD/BaseSystem.dmg"
# msg_status "Removing original BaseSystem.dmg.."
# rm "$MNT_ESD/BaseSystem.dmg"
hdiutil convert -format UDZO -o "$MNT_ESD/BaseSystem.dmg" "$BASE_SYSTEM_DMG_RW"
fi
msg_status "Unmounting.."
hdiutil detach "$MNT_ESD"
msg_status "Converting to .dmg disk image.."
if [ $DMG_OS_VERS_MAJOR -ge 9 ]; then
msg_status "On Mavericks the entire modified BaseSystem is our output dmg."
hdiutil convert -format UDZO -o "$OUTPUT_DMG" "$BASE_SYSTEM_DMG_RW"
else
msg_status "Pre-Mavericks we're modifying the original ESD file."
hdiutil convert -format UDZO -o "$OUTPUT_DMG" -shadow "$SHADOW_FILE" "$ESD"
fi
rm -rf "$MNT_ESD" "$SHADOW_FILE"
if [[ $ISO = 1 ]]; then
OUTPUT_ISO="$OUT_DIR/OSX_InstallESD_${DMG_OS_VERS}_${DMG_OS_BUILD}.iso"
msg_status "Converting to .iso disk image…."
/usr/bin/hdiutil convert "$OUTPUT_DMG" -format UDTO -o "$OUTPUT_ISO"
/bin/mv $OUT_DIR/OSX_InstallESD_${DMG_OS_VERS}_${DMG_OS_BUILD}.iso.cdr "$OUTPUT_ISO"
fi
if [ -n "$SUDO_UID" ] && [ -n "$SUDO_GID" ]; then
msg_status "Fixing permissions.."
chown -R $SUDO_UID:$SUDO_GID "$OUT_DIR"
fi
msg_status "Checksumming .dmg disk image.."
MD5=$(md5 -q "$OUTPUT_DMG")
msg_status "MD5: $MD5"
msg_status "Built .dmg disk image is located at $OUTPUT_DMG."
if [ -f "$OUTPUT_ISO" ]; then
msg_status "Checksumming .iso disk image.."
MD5=$(md5 -q "$OUTPUT_ISO")
msg_status "MD5: $MD5"
msg_status "Built .iso disk image is located at $OUTPUT_ISO."
fi
msg_status "Build process finished."

view raw

gistfile1.sh

hosted with ❤ by GitHub

  1. doxinho
    October 25, 2013 at 12:15 pm

    Thanks for your hard work on this script. I keep getting this error: http://i.imgur.com/NaG4lTb.png

    Do you have any idea what I am doing wrong? Any help is appreciated.

    • October 25, 2013 at 12:41 pm

      When you’re using the script, are the script and the “support” directory both located in the same location?

      For example, if the script is located in /Users/username/foo, the “support” directory and all of its contents also need to be in stored in /Users/username/foo.

      • doxinho
        October 25, 2013 at 1:11 pm

        Thanks for the quick response. The script “create_vmware_osx_install.dmg.sh” is located in the /create_osx_vm_install_dmg folder and /support/ is a subdirectory of the /create_osx_vm_install_dmg folder. I cloned it directly from GitHub so I am assuming that is correct. Let me know if I am wrong!

      • October 25, 2013 at 1:23 pm

        It sounds like the directory structure is OK. Did you unzip the First Boot Package Install zip file and then configure First Boot Package Install with your additional installers?

  2. doxinho
    October 25, 2013 at 6:43 pm

    Once again, I’d just like to say many thanks for your development as I really appreciate the work you have put in… it’s nearly mind blowing to me coming from a non-programming background. I did not extract the .zip at first, but after my first try the .dmg/.iso only came out to ~1.5GB. I tried the script again and voila- everything worked flawlessly and I am now installing OS X on my ESXi host. I didn’t put any additional installers in yet because I just wanted to learn the basics from the start. Again, thanks very much for your time!

  3. Régis Duchesne
    July 21, 2014 at 6:11 pm

    “updated with Mavericks support”: I believe installing from the media your script creates will result in a Mavericks installation which lacks the Recovery HD partition, and hence a Mavericks installation in which FileVault 2 (and other things) do not work.

    So for now I would stick with VMware’s recommended way (Guest OS Install Guide) to install Mavericks in a VM on ESXi: Install Mountain Lion in the VM, then upgrade the VM to Mavericks using Software Update.

    • July 21, 2014 at 7:28 pm

      Régis,

      I hadn’t noticed that before, but it appears that you’re correct. I’ll see if there’s a way to fix that. As a workaround, it appears that this can be addressed via using Per Olafsson’s Create Recovery Partition Installer to generate an installer that can install the missing recovery partition:

      Create Recovery Partition Installer is available from here on GitHub:

      https://github.com/MagerValp/Create-Recovery-Partition-Installer

      Unfortunately, that installer would be too large to include as part of First Boot Package Install’s payload (available space is around 350 MBs, the Recovery Partition installer is around 485 MBs.)

  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: