VMware ESXi 自動でスナップショットを取る方法

# 対象バージョン
　VMware ESXi 5.5.0　フリーライセンス版
　※他のバージョンでは動作未確認です。

# 概要
　VMをコマンドで操作する「vim-cmd」を使用します。
　cronを利用して、自前で作成したスクリプトの実行をスケジューリングし、
　定期的にスナップショットを取ります。
　※ESXiにcrontabコマンドは存在しないためこの方法をとります。

# 手順
１．シェルスクリプトファイルを、サーバーから参照出来る場所(データストア)にアップします。

２．SSHで接続し、以下のコマンドを実行して、ファイルを実行可能にします。
　chmod +x /vmfs/volumes/データストア名/ファイル名

３．local.shファイルを変更しスケジューリングしていきます。
　vi /etc/rc.local.d/local.sh

４．以下4行を、local.shファイル内の「exit 0」という行の直前に入力します。
　時間の指定は、日本時間のマイナス9時間で設定します。ESXiホストは、UTC表記であるため。
　/bin/kill $(cat /var/run/crond.pid)
　/bin/echo "時間(分) 時間(時) * * * /vmfs/volumes/データストア名/ファイル名 [仮想マシンのVMID] [ログの出力先] [最後に仮想マシンを起動するか(0：起動しない、1：起動する)]" \
　>> /var/spool/cron/crontabs/root
　/bin/crond

５．ESXi本体を再起動します。
　再起動することにより、うえで修正したlocal.shが動き
　「/var/spool/cron/crontabs/root」に設定されます。

６．以下のコマンドで変更が反映されていることを確認します。
　cat /var/spool/cron/crontabs/root


# スナップショットを取るスクリプトファイル
```shell:sample.sh
##################################################
# 名称：仮想マシンのスナップショット取得
# 
# 引数：第1 仮想マシンのVMID(※)
# 引数：第2 ログの出力先ストレージ
#       (例：/vmfs/volumes/vm-install)
# 引数：第3 最後に仮想マシンを起動するか
#       (0：起動しない(デフォルト)、1：起動する)
# --------------------------------------------
# ※VMIDは仮想マシンごとに一意に割り振られるID
# IDを調べるには以下のコマンドを使用して下さい
# vim-cmd vmsvc/getallvms
##################################################

##変数定義###############

##管理する世代数を指定(世代管理しない場合には-1を指定する)
ROTATION_COUNT=3

##ログの出力先
LOG_DIRECTORY=$2"/log/"

LOG_FILE="snapshotLog-`date +%Y%m%d%H%M`.log"

LOG_OUTPUT=${LOG_DIRECTORY}${LOG_FILE}

##スナップショット作成時の名前
SNAPSHOT_NAME="日次スナップショット_"`date +%Y%m%d%H%M`

##スナップショット作成時の説明
SNAPSHOT_DISP="日次で取得しているスナップショットです"

##仮想マシンの起動オプション
START_VM_FLAG=$3

##ログ出力処理###############

logger() {
  echo $1 >> ${LOG_OUTPUT}
}

##メイン処理#############
ORIG_IFS=${IFS}

##1.引数チェックを行う
#引数の数が正しいこと
if [ $# -lt 2 ]; then
  echo "引数が正しく指定されていません"
  exit 1
fi

#ログ出力先ディレクトリが無ければ作成する
if [ ! -e $LOG_DIRECTORY ]; then
  mkdir -p $LOG_DIRECTORY
fi

logger "****処理開始 "`date +%Y%m%d%H%M`"****************************************************************"

logger "対象の仮想マシンは、VMID[ "$1" ]です"
logger "ログの出力先は、[ "$LOG_OUTPUT" ]です"

#文字列がスプリットされないように一時的に環境変数を切り替える
IFS="####"
VMID=$1

##2.仮想マシンの状態を確認する。仮想マシンが起動されている場合には処理しない
VM_STATE=`vim-cmd vmsvc/power.getstate ${VMID}`
logger `echo "仮想マシンの状態 -> "${VM_STATE}`

ON="Powered on"

if [ `echo "${VM_STATE}" | grep "${ON}"` ]; then
  logger "仮想マシンが起動しているため、処理を中断します"
  IFS=${ORIG_IFS}
  exit 1
fi

##3.スナップショットの履歴からスナップショットIDを取得する
IFS=$'\n'
SNAPSHOT_INFOS=`vim-cmd vmsvc/snapshot.get ${VMID}`
SNAPSHOT_IDS=""
SNAPSHOT_COUNT=0

for SNAPSHOT_INFO in ${SNAPSHOT_INFOS}; do

  #スナップショットIDが記述されている行のみ対象とする
  if [ `echo ${SNAPSHOT_INFO} | grep 'Snapshot Id        : '` ]; then

    #後方から:までの文字列を抜き取る
    SNAPSHOT_ID=${SNAPSHOT_INFO##*:}

    #文字列の前後にある空白を取り除く
    SNAPSHOT_ID=`echo ${SNAPSHOT_ID} | sed -e "s/ //g"`

    #カンマ区切りで1つの文字列として結合する
    SNAPSHOT_IDS=`echo ${SNAPSHOT_IDS}${SNAPSHOT_ID}","`

    let SNAPSHOT_COUNT=${SNAPSHOT_COUNT}+1

  fi

done

#文字列の最後にあるカンマを除去する
SNAPSHOT_IDS=`echo ${SNAPSHOT_IDS} | sed -e "s/,\$//g"`

logger "Snapshot count -> "${SNAPSHOT_COUNT}

##4.管理する世代以上にスナップショットがある場合にはスナップショットを削除する

if [ ${ROTATION_COUNT} -ne -1 ]; then
  if [ ${SNAPSHOT_COUNT} -ge ${ROTATION_COUNT} ]; then
    IFS=$','

    for SNAPID in ${SNAPSHOT_IDS}; do

      if [ ${SNAPSHOT_COUNT} -ge ${ROTATION_COUNT} ]; then

        logger `vim-cmd vmsvc/snapshot.remove ${VMID} ${SNAPID}`
        let SNAPSHOT_COUNT=${SNAPSHOT_COUNT}-1

      fi

    done

    logger "****削除処理完了****"
  fi
fi

##5.新しくスナップショットを作成する
logger `vim-cmd vmsvc/snapshot.create ${VMID} ${SNAPSHOT_NAME} ${SNAPSHOT_DISP}`
logger "****作成処理完了****"

##6.仮想マシンを起動する
logger "仮想マシンの起動オプション(0：起動しない、1：起動する) -> "$3
if [ ${START_VM_FLAG} -eq 1 ]; then
  logger `vim-cmd vmsvc/power.on ${VMID}`
  logger "****仮想マシン起動完了****"
fi

IFS=${ORIG_IFS}

logger "****処理終了 "`date +%Y%m%d%H%M`"****************************************************************"

```