Skip to content

Instantly share code, notes, and snippets.

@vidrowan
Forked from jhuebsch/vm-management.sh
Created November 16, 2012 21:20
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save vidrowan/4091028 to your computer and use it in GitHub Desktop.
Save vidrowan/4091028 to your computer and use it in GitHub Desktop.
Control parallels VM via command line and mount remote users home dir as network share with sshfs
#!/bin/sh
# Parallels VM management
# start/pause/resume Parallels VM. When starting VM mounts VM users home dir (default) as
# network share on local machine using fuse4x and sshfs. When pausing VM, unmounts network
# share before pausing VM.
vmsb() { #Usage: vmsb <command:string [start|resume|pause|stop]>
#### Colors ####
txtrst='\\033[0m' # Text Reset
txtred='\\033[0\;31m' # Red
txtgrn='\\033[0\;32m' # Green
bldred='\\033[1\;31m' # BoldRed
bldcyn='\\033[1\;36m' # BoldCyan
bldwht='\\033[1\;37m' # BoldWhite
bldylw='\\033[1\;33m' # BoldYellow
bldred='\\033[1\;31m' # BoldRed
alias NORMAL="echo -en ${txtrst} > /dev/tty;"
alias SUCCESS="echo -en ${bldgrn} > /dev/tty;"
alias CMDINFO="echo -en ${bldcyn} > /dev/tty;"
alias INFO="echo -en ${bldwht} > /dev/tty;"
alias FEEDBACK="echo -en ${txtgrn} > /dev/tty;"
alias WARNING="echo -en ${bldylw} > /dev/tty;"
alias FAILURE="echo -en ${bldred} > /dev/tty;"
#### END Colors ####
#### Usage ####
usage()
{
cat << EOF
vmsb info.
Description:
This function start/pause/resume/stops a single pre-set Parallels VM.
When starting the VM, the script mounts the VM users home dir (default) as network share on local machine using fuse4x and sshfs.
When pausing the VM, the script unmounts network share before pausing VM.
OPTIONS:
-d - Debug Mode
-h - Help
-m - Machine name of the parallels VM you want to control, find availble names with "prlctl list -a"
-u - User name. The connection string for user on VM. i.e.: user@virtualmachine/ipaddress. You can look up the IP of the remote VM from the terminal in the VM: $ /sbin/ifconfig | grep "inet addr:"
-p - Mount Point Path. Absolute path "pwd -P" of a folder your user owns (not the home dir) that can be used as the mountpoint for the network share. Note: This directory will be temporarily "replaced" by the mounted remote drive; It will appear to be renamed in Finder, possibly something like; "fuse4x volume 0 (sshfs)"
ARGUMENTS:
command - (required) action the script should take: start|resume|pause|stop
USAGE EXAMPLES:
$ vmsb [-dh -m <string:"MachineName"> -u <string:"UserName@MachineAddress"> -p <string:"Mount Point Path">] <command:string [start|resume|pause|stop]>
Simple usage if VM vars are hardcoded:
$ vmsb start;
Complex usage if passing VM vars:
$ vmsb -d -m "Red Hat Enterprise Linux 6" -u "myUser@localhost" -p "/Applications/MAMP/htdocs/parallels_hds/" stop
$ vmsb -d -m "Red Hat Enterprise Linux 6" -u "myuser@10.1.1.1" -p "~/parallels_hd_mount/" start
EOF
}
#### END Usage ####
#### Options #### #ref: http://wiki.bash-hackers.org/howto/getopts_tutorial
OPTIND=1 #set the OPTIND to 1 before each use. Ref: http://ss64.com/bash/getopts.html "OPTIND is initialized to 1 each time the shell or a shell script is invoked." In this case (in a bash function) it's initialized once for each shell session so we need to reset it inside each function.
# (p)reset vars
HELP=0
DEBUG=0
# Check for options. (currently in a while loop and case statement for potential expansion)
while getopts ":dhm:u:p:" OPTION;
do
case $OPTION in
d) # DEBUG
DEBUG=1
INFO echo "Debuging mode" > /dev/tty; NORMAL
;;
h)
# Help
HELP=1
if (($DEBUG)) ; then
INFO echo "Debug msg: Setting HELP: $HELP" > /dev/tty; NORMAL
fi
break
;;
m) # MACHINE NAME
# parallels VM you want to control, find availble names with "prlctl list -a"
VM="$OPTARG"
if (($DEBUG)) ; then
INFO echo "Debug msg: Machine VM Name set with -m: $VM" > /dev/tty; NORMAL
fi
;;
u) # USER NAME
# connection string for user on $VM ie user@virtualmachine
CONNECT="$OPTARG"
if (($DEBUG)) ; then
INFO echo "Debug msg: Connection string for user on $VM ie user@virtualmachine -u: $CONNECT" > /dev/tty; NORMAL
fi
;;
p) # MOUNT POINT PATH
# Absolute path "pwd -P" of a folder your user owns (not the home dir) that can be used as the mountpoint for the network share
MNTPOINT="$OPTARG"
if (($DEBUG)) ; then
INFO echo "Debug msg: Absolute path 'pwd -P' of a folder your user owns (not the home dir) that can be used as the mountpoint for the network share; -p: $MNTPOINT" > /dev/tty; NORMAL
fi
;;
?) #if no option is given continue on
INFO echo "Unknown option: -$OPTARG" > /dev/tty; NORMAL
;;
esac
done
shift $((OPTIND-1)) #prepare OPTIND for the next option
#### END Options ####
#Set arg1 from non-option arguments
ARG1=$1
if (($DEBUG)) ; then
INFO echo "Debug msg: ARG1 = \$1: $ARG1" > /dev/tty; NORMAL
fi
#if there are no options then: arg1 = $1 if it doesn't start with '-'
if [ ! -n "$ARG1" ] && [[ -n "$1" ]] && [[ $1 != -* ]] && [[ $# -gt 0 ]] ; then
ARG1=$1
if (($DEBUG)) ; then
WARNING echo "Debug msg: No arguments passed. ARG1 = \$1: $ARG1" > /dev/tty; NORMAL
fi
fi
#check for --help
if [[ $1 == "--help" ]] ; then
HELP=1
fi
if (($HELP)) && (($DEBUG)) ; then
INFO echo "Debug msg: HELP: $HELP" > /dev/tty; NORMAL
fi
#Check for required vars: $VM, $CONNECT, $MNTPOINT & ARG1; if empty or ARG1 starts with a '-' then show usage, else execute script
if [ ! -n "$VM" ] || [ ! -n "$CONNECT" ] || [ ! -n "$MNTPOINT" ] || [ ! -n "$ARG1" ] || [[ "$ARG1" == -* ]] || (($HELP)) ; then
if (($DEBUG)) ; then
FAILURE echo "Debug msg: Failed to meet requirements or help was called: Check for required vars: VM ($VM), CONNECT ($CONNECT), MNTPOINT ($MNTPOINT) & ARG1 ($ARG1); if empty OR ARG1 starts with a '-' OR HELP = 1; then show usage, else execute script" > /dev/tty; NORMAL
fi
# Display Usage:
usage
else
#### Execute script ####
# Current running status of $VM
if (($DEBUG)) ; then
INFO echo "Debug msg: Setting VM Status: prlctl list \"$VM\" -o status --no-header" > /dev/tty; NORMAL
fi
VMSTATUS=`prlctl list "$VM" -o status --no-header`;
if (($DEBUG)) ; then
INFO echo "Debug msg: VM Status: $VMSTATUS" > /dev/tty; NORMAL
fi
# if starting vm, start vm then wait then mount network share
if [ "$ARG1" = "start" ] || [ "$ARG1" = "resume" ]
then
case "$VMSTATUS" in
"running" )
INFO echo "$VM is already running." > /dev/tty; NORMAL
;;
"stopped" )
INFO echo "prlctl start $VM" > /dev/tty; NORMAL
prlctl start "$VM";
;;
"paused" | "suspended")
INFO echo "prlctl resume $VM" > /dev/tty; NORMAL
prlctl resume "$VM";
;;
esac
# mount network share, only if it hasn't already been mounted
if [ ! -f "$MNTPOINT/.bash_logout" ]
then
# give time for vm to boot
COUNT=0
while [ $VMSTATUS != "running" ]
do
(( COUNT++ ))
INFO echo "Waiting for \"$VM\" to finish booting: $COUNT" > /dev/tty; NORMAL
sleep 1;
VMSTATUS=`prlctl list "$VM" -o status --no-header`;
done
FEEDBACK echo -en "Mounting network share:\n sshfs $CONNECT: $MNTPOINT \n" > /dev/tty; NORMAL
sshfs "$CONNECT": "$MNTPOINT";
fi
# if pausing or stopping vm, unmount mounted sshfs mounted network share then pause or stop VM
elif [ "$ARG1" = "pause" ] || [ "$ARG1" = "stop" ]
then
# no need to run pause if machine isn't running
if [ ! "$VMSTATUS" = "running" ]
then
FEEDBACK echo "$VM is not currently running, it is currently $VMSTATUS" > /dev/tty; NORMAL
else
# only unmount if network share is mounted
if [ -f "$MNTPOINT/.bash_logout" ]
then
FEEDBACK echo "Unmounting network share:" > /dev/tty; NORMAL
FEEDBACK echo "diskutil unmount $MNTPOINT" > /dev/tty; NORMAL
diskutil unmount "$MNTPOINT";
fi
# while for network share to unmount before continuing.
COUNT=0
while [ -f "$MNTPOINT/.bash_logout" ]
do
FEEDBACK echo "$COUNT" > /dev/tty; NORMAL
sleep 1;
(( COUNT++ ))
done
# Never stop as that is like unplugging the VM.
FEEDBACK echo "prlctl pause $VM" > /dev/tty; NORMAL
prlctl pause "$VM";
# give time for vm to pause
COUNT=0
while [ $VMSTATUS != "paused" ]
do
(( COUNT++ ))
INFO echo "Waiting for \"$VM\" to finish pausing: $COUNT" > /dev/tty; echo -en ${txtrst} > /dev/tty;
sleep 1;
VMSTATUS=`prlctl list "$VM" -o status --no-header`;
done
fi
else
FEEDBACK echo "prlctl $@ $VM" > /dev/tty; NORMAL
prlctl $@ "$VM";
fi
#### Next Steps ####
# give time for vm to pause
COUNT=0
while [ "$VMSTATUS" != "" ]
do
(( COUNT++ ))
INFO echo "Waiting for \"$VM\" to finish: $COUNT" > /dev/tty; echo -en ${txtrst} > /dev/tty;
sleep 1;
VMSTATUS=`prlctl list "$VM" -o status --no-header`;
done
INFO echo "Current Status: $VMSTATUS" > /dev/tty; NORMAL
INFO echo "Available Options: [start|resume|pause|stop]" > /dev/tty; NORMAL
case "$VMSTATUS" in
"running" )
CMDINFO echo "vmsb -m \"$VM\" -u \"$CONNECT\" -p \"$MNTPOINT\" pause" > /dev/tty; NORMAL
CMDINFO echo "vmsb -m \"$VM\" -u \"$CONNECT\" -p \"$MNTPOINT\" stop" > /dev/tty; NORMAL
;;
"stopped" )
CMDINFO echo "vmsb -m \"$VM\" -u \"$CONNECT\" -p \"$MNTPOINT\" start" > /dev/tty; NORMAL
;;
"paused" | "suspended" )
CMDINFO echo "vmsb -m \"$VM\" -u \"$CONNECT\" -p \"$MNTPOINT\" resume" > /dev/tty; NORMAL
;;
esac
#### END Next Steps ####
#### END Execute script ####
fi # end else -#If not ARG1 or ARG1 starts with a '-' then show usage, else execute script
shift $((OPTIND-1)) #prepare OPTIND for the next option
}
@vidrowan
Copy link
Author

Added help documentation. Shown when no var is passed to function or when --help is passed.

@vidrowan
Copy link
Author

Not tested.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment