Skip to content

Commit

Permalink
Merge pull request #82 from jonanh/create_prepare_vdi_based_on_autodmg
Browse files Browse the repository at this point in the history
Support for installing macOS like AutoDMG
  • Loading branch information
timsutton authored Nov 16, 2017
2 parents fab0973 + d00d75e commit 76dce81
Show file tree
Hide file tree
Showing 12 changed files with 736 additions and 39 deletions.
38 changes: 38 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ The `prepare_iso.sh` script in this repo makes use of functionality Apple suppor

It may be possible to work around this by modifying the rc script directly with the contents of our postinstall script.

The `prepare_vdi.sh` script uses [AutoDMG](https://github.com/MagerValp/AutoDMG)'s approach running the installer's ```OSInstall.pkg``` creating a fresh install in a temporary DMG sparse disk image which is converted into a VDI disk image using VirtualBox's command line tools.

## Preparing the ISO

OS X's installer cannot be bootstrapped as easily as can Linux or Windows, and so exists the [prepare_iso.sh](https://github.com/timsutton/osx-vm-templates/blob/master/prepare_iso/prepare_iso.sh) script to perform modifications to it that will allow for an automated install and ultimately allow Packer and later, Vagrant, to have SSH access.
Expand Down Expand Up @@ -202,6 +204,42 @@ Vagrant.configure("2") do |config|
end
```

## Alternative method using ```prepare_vdi.sh```, ```prepare_ovf.sh``` and packer virtualbox-ovf

This approach requires VirtualBox and unfortunately almost 30GB of free space.

#### Installing and exporting to a VirtualBox virtual disk image.

The ```prepare_vdi.sh``` command will run the installer's ```OSInstall.pkg``` creating a fresh install in a temporary disk image which is converted into a VDI disk image.

```
cd packer
sudo ../prepare_iso/prepare_vdi.sh \
-D DISABLE_REMOTE_MANAGEMENT \
-o macOS_10.12.vdi \
/Applications/Install\ macOS\ Sierra.app/ \
.
```

#### Generating a VirtualBox machine and exporting it into packed virtual machine OVF

The ```prepare_ovf.sh``` command takes a virtual image disk and adds it into a temporary VirtualBox machine which is exported into a packed virtual machine using the OVF (Open Virtualization Format).

```
../prepare_iso/prepare_ovf.sh \
macOS_10.12.vdi
```

#### Generating a packer box using the virtualbox-ovf builder

Finally the virtualbox-ovf allows to use the previously generated exported virtual machine to generate the provisioned packer box.

```
packer build \
-var provisioning_delay=30 \
-var source_path=macOS_10.12.ovf \
template.json
```

## Box sizes

Expand Down
21 changes: 21 additions & 0 deletions packer/template.json
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,27 @@
["modifyvm", "{{.Name}}", "--vram", "128"],
["storagectl", "{{.Name}}", "--name", "IDE Controller", "--remove"]
]
},
{
"boot_wait": "2s",
"guest_additions_mode": "disable",
"source_path": "{{user `source_path`}}",
"shutdown_command": "echo '{{user `username`}}'|sudo -S shutdown -h now",
"ssh_port": 22,
"ssh_username": "{{user `username`}}",
"ssh_password": "{{user `password`}}",
"ssh_wait_timeout": "10000s",
"type": "virtualbox-ovf",
"vboxmanage": [
["modifyvm", "{{.Name}}", "--audiocontroller", "hda"],
["modifyvm", "{{.Name}}", "--chipset", "ich9"],
["modifyvm", "{{.Name}}", "--firmware", "efi"],
["modifyvm", "{{.Name}}", "--hpet", "on"],
["modifyvm", "{{.Name}}", "--keyboard", "usb"],
["modifyvm", "{{.Name}}", "--memory", "4096"],
["modifyvm", "{{.Name}}", "--mouse", "usbtablet"],
["modifyvm", "{{.Name}}", "--vram", "128"]
]
}
],
"min_packer_version": "0.7.0",
Expand Down
55 changes: 55 additions & 0 deletions prepare_iso/create_firstboot_pkg.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
#!/bin/bash

SCRIPT_DIR="$(cd "$(dirname "$0")"; pwd)"
SUPPORT_DIR="$SCRIPT_DIR/support"

# Parse the optional command line switches
USER="vagrant"
PASSWORD="vagrant"
IMAGE_PATH="$SUPPORT_DIR/vagrant.jpg"

# Flags
DISABLE_REMOTE_MANAGEMENT=0
DISABLE_SCREEN_SHARING=0
DISABLE_SIP=0

render_template() {
eval "echo \"$(cat "$1")\""
}

create_firstboot_pkg() {
# payload items
mkdir -p "$SUPPORT_DIR/pkgroot/private/var/db/dslocal/nodes/Default/users"
mkdir -p "$SUPPORT_DIR/pkgroot/private/var/db/shadow/hash"
BASE64_IMAGE=$(openssl base64 -in "$IMAGE_PATH")
ShadowHashData=$($SCRIPT_DIR/../scripts/support/generatehash.py "$PASSWORD")
# Replace USER and BASE64_IMAGE in the user.plist file with the actual user and image
render_template "$SUPPORT_DIR/user.plist" > "$SUPPORT_DIR/pkgroot/private/var/db/dslocal/nodes/Default/users/$USER.plist"
USER_GUID=$(/usr/libexec/PlistBuddy -c 'Print :generateduid:0' "$SUPPORT_DIR/user.plist")
# Generate a shadowhash from the supplied password
"$SUPPORT_DIR/generate_shadowhash" "$PASSWORD" > "$SUPPORT_DIR/pkgroot/private/var/db/shadow/hash/$USER_GUID"

# postinstall script
mkdir -p "$SUPPORT_DIR/tmp/Scripts"
cat "$SUPPORT_DIR/pkg-postinstall" \
| sed -e "s/__USER__PLACEHOLDER__/${USER}/" \
| sed -e "s/__DISABLE_REMOTE_MANAGEMENT__/${DISABLE_REMOTE_MANAGEMENT}/" \
| sed -e "s/__DISABLE_SCREEN_SHARING__/${DISABLE_SCREEN_SHARING}/" \
| sed -e "s/__DISABLE_SIP__/${DISABLE_SIP}/" \
> "$SUPPORT_DIR/tmp/Scripts/postinstall"
chmod a+x "$SUPPORT_DIR/tmp/Scripts/postinstall"

# build it
BUILT_COMPONENT_PKG="$SUPPORT_DIR/tmp/veewee-config-component.pkg"
BUILT_PKG="$SUPPORT_DIR/tmp/veewee-config.pkg"
pkgbuild --quiet \
--root "$SUPPORT_DIR/pkgroot" \
--scripts "$SUPPORT_DIR/tmp/Scripts" \
--identifier com.vagrantup.veewee-config \
--version 0.1 \
"$BUILT_COMPONENT_PKG"
productbuild \
--package "$BUILT_COMPONENT_PKG" \
"$BUILT_PKG"
rm -rf "$SUPPORT_DIR/pkgroot"
}
47 changes: 9 additions & 38 deletions prepare_iso/prepare_iso.sh
Original file line number Diff line number Diff line change
Expand Up @@ -74,10 +74,6 @@ msg_error() {
echo "\033[0;31m-- $1\033[0m"
}

render_template() {
eval "echo \"$(cat "$1")\""
}

if [ $# -eq 0 ]; then
usage
exit 1
Expand All @@ -86,6 +82,10 @@ fi
SCRIPT_DIR="$(cd "$(dirname "$0")"; pwd)"
SUPPORT_DIR="$SCRIPT_DIR/support"

# Import shared code to generate first boot pkgs
FIRST_BOOT_PKG_SCRIPT="$SCRIPT_DIR/create_firstboot_pkg.sh"
[ -f "$FIRST_BOOT_PKG_SCRIPT" ] && . "$FIRST_BOOT_PKG_SCRIPT"

# Parse the optional command line switches
USER="vagrant"
PASSWORD="vagrant"
Expand Down Expand Up @@ -217,40 +217,11 @@ fi

# Build our post-installation pkg that will create a user and enable ssh
msg_status "Making firstboot installer pkg.."

# payload items
mkdir -p "$SUPPORT_DIR/pkgroot/private/var/db/dslocal/nodes/Default/users"
mkdir -p "$SUPPORT_DIR/pkgroot/private/var/db/shadow/hash"
BASE64_IMAGE=$(openssl base64 -in "$IMAGE_PATH")
# Replace USER and BASE64_IMAGE in the user.plist file with the actual user and image
render_template "$SUPPORT_DIR/user.plist" > "$SUPPORT_DIR/pkgroot/private/var/db/dslocal/nodes/Default/users/$USER.plist"
USER_GUID=$(/usr/libexec/PlistBuddy -c 'Print :generateduid:0' "$SUPPORT_DIR/user.plist")
# Generate a shadowhash from the supplied password
"$SUPPORT_DIR/generate_shadowhash" "$PASSWORD" > "$SUPPORT_DIR/pkgroot/private/var/db/shadow/hash/$USER_GUID"

# postinstall script
mkdir -p "$SUPPORT_DIR/tmp/Scripts"
cat "$SUPPORT_DIR/pkg-postinstall" \
| sed -e "s/__USER__PLACEHOLDER__/${USER}/" \
| sed -e "s/__DISABLE_REMOTE_MANAGEMENT__/${DISABLE_REMOTE_MANAGEMENT}/" \
| sed -e "s/__DISABLE_SCREEN_SHARING__/${DISABLE_SCREEN_SHARING}/" \
| sed -e "s/__DISABLE_SIP__/${DISABLE_SIP}/" \
> "$SUPPORT_DIR/tmp/Scripts/postinstall"
chmod a+x "$SUPPORT_DIR/tmp/Scripts/postinstall"

# build it
BUILT_COMPONENT_PKG="$SUPPORT_DIR/tmp/veewee-config-component.pkg"
BUILT_PKG="$SUPPORT_DIR/tmp/veewee-config.pkg"
pkgbuild --quiet \
--root "$SUPPORT_DIR/pkgroot" \
--scripts "$SUPPORT_DIR/tmp/Scripts" \
--identifier com.vagrantup.veewee-config \
--version 0.1 \
"$BUILT_COMPONENT_PKG"
productbuild \
--package "$BUILT_COMPONENT_PKG" \
"$BUILT_PKG"
rm -rf "$SUPPORT_DIR/pkgroot"
create_firstboot_pkg
if [ -z "$BUILT_PKG" ] || [ ! -e "$BUILT_PKG" ]; then
msg_error "Failed building the firstboot installer pkg, exiting.."
exit 1
fi

# We'd previously mounted this to check versions
hdiutil detach "$MNT_BASE_SYSTEM"
Expand Down
69 changes: 69 additions & 0 deletions prepare_iso/prepare_ovf.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
#!/bin/sh -e

usage() {
cat <<EOF
Usage:
$(basename "$0") "/path/to/diskimage.vdi"
Description:
Creates and exports a machine image (OVF) from virtual disk image
EOF
}

cleanup() {
if [ -n "$VM" ] && VBoxManage list vms | grep -q "$VM"; then
# Detach the diskimage before deleting the virtual image
VBoxManage storageattach "$VM" --storagectl "SATA Controller" --port 0 --device 0 --type hdd --medium none
VBoxManage unregistervm "$VM" --delete || echo > /dev/null
fi
}

trap cleanup EXIT INT TERM

msg_status() {
echo "\033[0;32m-- $1\033[0m"
}

msg_error() {
echo "\033[0;31m-- $1\033[0m"
}

render_template() {
eval "echo \"$(cat "$1")\""
}

if [ ! -f "$1" ]; then
usage
exit 1
fi

TIMESTAMP=$(date +"%s")
VM="macOS_${TIMESTAMP}"
HARDDRIVE="$1"
OUTPUT="${HARDDRIVE%.vdi}.ovf"

msg_status "Creating new virtual machine"
VBoxManage createvm --name "$VM" --ostype "MacOS_64" --register

msg_status "Adding SATA Controller"
VBoxManage storagectl "$VM" --name "SATA Controller" --add sata --controller IntelAHCI

msg_status "Attaching vdi"
VBoxManage storageattach "$VM" --storagectl "SATA Controller" --port 0 --device 0 --type hdd --medium "$HARDDRIVE"

msg_status "Setting up virtual machine"
VBoxManage modifyvm "$VM" --audiocontroller "hda"
VBoxManage modifyvm "$VM" --chipset "ich9"
VBoxManage modifyvm "$VM" --firmware "efi"
VBoxManage modifyvm "$VM" --cpus "2"
VBoxManage modifyvm "$VM" --hpet "on"
VBoxManage modifyvm "$VM" --keyboard "usb"
VBoxManage modifyvm "$VM" --memory "4096"
VBoxManage modifyvm "$VM" --mouse "usbtablet"
VBoxManage modifyvm "$VM" --vram "128"

msg_status "Exporting the virtual machine"
VBoxManage export "$VM" --output "$OUTPUT"

msg_status "Done. Virtual machine export located at $OUTPUT."
Loading

0 comments on commit 76dce81

Please sign in to comment.