Fusion Drive Script

Update 5/1/13: I cleaned up the way I posted the code so there won’t be any more mishaps when copying and pasting into a script file.

This is the entire script that I demonstrate in my “Fusion Drive and CoreStorage” video.  Use at your own risk, improve upon it if you feel you can and then share your results back!  Copy and paste this into your preferred text editor (I use TextWrangler) and save it in the .sh format.

(Note: the double ## is just my personal way of marking comments, single # does of course work just fine, don’t complain)

#!/bin/bash
clear
## These first blocks in the script are all functions that are constantly called on below.
## Using functions instead of in-sequence scripting allows us to perform error-check loops
## without lots of extra coding.  All of the functions must be passed through first so that
## the shell knows what they are and can call them.
## Before the script allows the user to begin inputting variables, if first checks for any
## available disk nodes to add to the new CoreStorage Logical Group and lists them.  If
## there are no available disks, or only one is available, then an error message with
## instructions is displayed and the script exits.
function devNodeList {
dID=0
echo "The following device nodes are available:"
diskCount=0
while True
do
     diskNode="disk${dID}"
     dnCK=$(diskutil list | grep -m 1 "${diskNode}" | awk -F/ '{print $3}')
     if [ -z "$dnCK" ]; then
          break
     fi

     csCheck=$(diskutil list | awk -F/ "/Apple_CoreStorage/ && /$diskNode/" | awk '{print $2}')
     if [ -z "$csCheck" ]; then
          csCheck=$(diskutil cs info "$diskNode" 2> /dev/null | awk '/Role:/ {print $2}')
          if [ "$csCheck" != "Logical" ]; then
               diskutil cs info "${diskNode}" 1> /dev/null
               diskCount=$((diskCount+1))
          fi
     fi
     dID=$((dID+1))
done
echo ""
if [ $diskCount -eq 0 ]; then
     echo "There are no available disks to create the CoreStorage Logical Group."
     echo "Run 'diskutil list' to see all disks with an 'Apple_CoreStorage'"
     echo "partition and 'diskutil cs list' to see the CoreStorage Logical Groups"
     echo "and use their UUIDs to delete them using 'diskutil cs delete lvgUUID'."
     echo ""
     exit 10
elif [ $diskCount -gt 0 -a $diskCount -lt 2 ]; then
     echo "There are not enough available disks to create the CoreStorage Logical"
     echo "Group. Run 'diskutil list' to see all disks with an 'Apple_CoreStorage'"
     echo "partition and 'diskutil cs list' to see the CoreStorage Logical Groups"
     echo "and use their UUIDs to delete them using 'diskutil cs delete lvgUUID'."
     echo ""
     exit 10
fi
}

## This function is the prompt for the first device node.  Note that the two variables that
## are set at the end are used in the "devNodeCheck" function to verify that the device node
## does not already belog to a CoreStorage Logical Group and to recall the "devNodeOne"
## function if it is invalid.

function devNodeOne {
echo "Please input the device node for the first disk (e.g. disk0):"
echo "(It is recommended that you set the SSD as the first disk)"
read "dnOne"
fncDN="$dnOne"
fncCall="devNodeOne"
devNodeCheck
}

## This function is identical to "devNodeOne" expect that it calls another function before the
## "devNodeCheck" to make sure the user did not enter the same device node twice.

function devNodeTwo {
echo "Please input the device node for the second disk (e.g. disk1):"
echo "(Your second disk should be your HDD)"
read "dnTwo"
fncDN="$dnTwo"
fncCall="devNodeTwo"
devNodeRepeat
devNodeCheck
}

## Here the device node entered by the user is checked to see if it is valid.  If not, then the
## user is prompted to enter another by calling the function that was passed in the variable.

function devNodeCheck {
dnCK=`diskutil list | grep -m 1 "$fncDN" | awk -F/ '{print $3}'`
if [ -z "$dnCK" ]; then
     echo ""
     echo "You have entered an invalid device node."
     echo ""
     $fncCall
fi
}

## This function is only called be devNodeTwo to ensure that the user hasn't entered the same
## one twice.  If they did, the user is returned to the devNodeTwo function to try again.

function devNodeRepeat {
if [ "$dnTwo" == "$dnOne" ]; then
     echo ""
     echo "You have already selected $dnOne for the CoreStorage Logical Volume Group."
     echo ""
     devNodeTwo
fi
}

## This function checks to see if the device node entered by the user belongs to a CoreStorage
## Logical Volume Group.  If it does, it is unusable for the purposes of this script and exits.

function coreStorageCheck {
csCK=`diskutil list | awk '/Apple_CoreStorage/ && /'$fncDN'/ {print $2}'`
if [ "$csCK" == "Apple_CoreStorage" ]; then
     echo ""
     echo "The entered device node belongs to a CoreStorage Logical Volume Group."
     echo "The script will now exit. Please use 'diskutil cs delete lvgUUID' to"
     echo "delete the CoreStorage Logical Volume Group from the disk."
     echo ""
     exit 20 ## Exits with error code 20
fi

csCK=`diskutil cs info "$fncDN" 2> /dev/null | awk '/Role:/ {print $2}'`
if [ "$csCK" == "Logical" ]; then
     echo ""
     echo "The entered device node is a CoreStorage Logical Volume. The script "
     echo "will now exit. Please use 'diskutil cs deleteVolume lvUUID' to delete"
     echo "the CoreStorage Logical Volume from the disk, and then delete the"
     echo "CoreStorage Logical Volume Group using 'diskutil cs delete lvgUUID'."
     echo ""
     exit 25 ## Exits with error code 25
fi
}

## If the device node did not pass the coreStorageCheck and the user agrees to delete the
## CoreStorage Logical Volume Group, this script will perform the task, list the available
## device nodes after the operation, and prompt the user to enter the first device node again.

## Not written yet.
## function deleteCoreStorageLVG {
## }

echo "#################################################################"
echo "#                                                               #"
echo "#  WARNING!!! This script is inherently dangerous. It will      #"
echo "#  destroy all existing data on the disks you specify when      #"
echo "#  creating the new CoreStorage Logical Volume Group.           #"
echo "#                                                               #"
echo "#  Before continuing, verify that no other CoreStorage Logical  #"
echo "#  Volume Groups are on the target drives. If there are, delete #"
echo "#  them using the command 'diskutil cs delete lvgUUID'          #"
echo "#                                                               #"
echo "#  How to best use this script: 1) target boot the Mac you      #"
echo "#  want to create the Fusion Drive on and connect to it, or     #"
echo "#  2) copy this script to another drive you can access while    #"
echo "#  running the OS X Mountain Lion Installer.  Mountain Lion is  #"
echo "#  required to create the CoreStorage Logical Group.            #"
echo "#                                                               #"
echo "#################################################################"
echo ""
echo "At any time press the [Cmd] + [.] keys to terminate the script."
echo "Press the Enter key to continue..."
read

devNodeList
devNodeOne
coreStorageCheck

echo ""

devNodeTwo
coreStorageCheck

echo ""
echo "Please input the label for the CoreStorage Logical Volume Group:"
read "csLVGname"

echo ""
echo "Please input the label for the CoreStorage Logical Volume (e.g. \"Macintosh HD\"):"
read "csLVname"

echo ""
echo "Creating the CoreStorage Logical Volume Group \"${csLVGname}\"."
diskutil cs create "${csLVGname}" $dnOne $dnTwo

## Grad the UUID of the just created CoreStorage Logical Volume Group.  Since these
## groups are always listed in order, the last result ('tail -1') will always be correct.

lvgUUID=`diskutil cs list | awk '/Logical Volume Group/ {print $5}' | tail -1`

echo ""
echo "Creating the CoreStorage Logical Volume \"${csLVname}\" with Mac OS Extended (Journaled)."
diskutil cs createVolume "${lvgUUID}" jhfs+ "${csLVname}" 100%

echo ""
echo "The Fusion Drive has been successfully created.  You may now install"
echo "or image OS X Mountain Lion onto the CoreStorage Logical Volume."
echo ""

exit 0
Advertisements

5 thoughts on “Fusion Drive Script

  1. If I try to use your script, the Terminal only says “/Users/Christian/Desktop/FusionDrive.sh: line 61: syntax error near unexpected token `(‘
    /Users/Christian/Desktop/FusionDrive.sh: line 61: `echo “Please input the device node for the first disk (e.g. disk0):”’
    can you help me to fix this problem?

    • If you’re copying and pasting this script be sure to use an appropriate editor like Text Wrangler so that no special formatting is preserved and you can save the script file with Unix (LF) line endings.

      • Ah, I replicated your problem. In Text Wrangler, after you paste the text, select all of it and go to the menu “Text > Straighten Quotes”. All of the quotes are “Educated” when you paste them in which causes the error.

  2. Hi, thanks for your script, I am having an issue at the “function devNodeCheck”, I enter disk0s2, which is correct for the SSD, and it says invalid node. When I run this line in Terminal: diskutil list | grep -m 1 “disk0s2” it works, so I’m not sure what the issue is. I’m going to do some testing. Any ideas would be helpful. Thanks

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 )

Google+ photo

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

Connecting to %s