ZFSスナップショットを管理するPythonスクリプト
Pythonの勉強がてら作ってみました。
前提条件
該当Solaris11サーバは日次で全ZFSのスナップショットを取得しており、書式は
[ZFS名]@YYYYmmddHHMMSS
とする。
また、Pythonのバージョンは
3.5.1
とする。
使い方
Usage: ./rotate_zfs_snapshot.py [ZFS name] [age_date]
ZFS「bata64/data」の、30日経過したスナップショットを削除したい場合は
./rotate_zfs_snapshot.py bata64/data 30
とすればよい。
なお、スーパユーザ権限が必要です。
ソースコード
初めて作ったのでくどいほどコメントを入れてみました。
#!/usr/bin/env python import sys import datetime import subprocess import re ## プログラム実行時の引数を取得 param = sys.argv ## 引数の数を取得(コマンド名+引数の数値が取得される) check_params = len(param) ## 引数の数が2でない場合は使用例出して異常終了 if check_params != 3: print ("Usage: " + param[0] + " [ZFS name] [age_date]") sys.exit(1) ## 第一引数で渡された値を取得(ZFS名) snapshot_name = param[1] ## 第二引数で渡された値を取得(エージング期間) age_date = int ( param[2] ) ## datetimeモジュールで現時刻を取得 date_now = datetime.datetime.now() ## datetimeモジュールで今から○日前の日付を、しきい値として取得 date_threshold = date_now - datetime.timedelta( days = age_date ) ## zfs list -H -t snapshotを実行してスナップショット一覧を取得 cmd_zfs_list = subprocess.Popen([ 'zfs', 'list', '-H', '-t', 'snapshot' ], stdout=subprocess.PIPE) ### 実行結果がbyte型で渡されたので、文字型として扱うためにデコードして変数へ代入 out_zfs_list = cmd_zfs_list.communicate()[0].decode('utf-8') cmd_zfs_list.stdout.close() ## zfs list実行結果を1行ずつ(改行区切り)でリストに格納 list_zfs_list = out_zfs_list.split('\n') ## zfs list実行結果を解釈するための正規表現を定義。Perlだと /^(ZFS名@([0-9]{14}))\s/ という感じ text_re = r'^'+ r'(' + snapshot_name + r'@' + r'(' + r'[0-9]{14}' + r')' + r')' + r'\s' ## 正規表現パターンをコンパイル p = re.compile( text_re ) ## zfs list実行結果が入ったリストをfor文で1個ずつ処理 for line in list_zfs_list: ## zfs list実行結果を正規表現パターンで判定 matchOB = p.match( line ) ## 正規表現パターンにマッチしていたら処理実行 if matchOB: ## 正規表現グループ化によってスナップショット名の@より右側(取得日時)を取得 date_snapshot = matchOB.group( 2 ) ## 正規表現グループ化によってスナップショット名(取得日時)を取得 name_snapshot = matchOB.group( 1 ) ## スナップショット取得日時をdatetimeモジュールで日時データへ変換 date_snapshot_datetime = datetime.datetime.strptime(date_snapshot, '%Y%m%d%H%M%S') ## スナップショット取得日時がしきい値より古い場合処理実行 if date_snapshot_datetime <= date_threshold: ## zfs destroyコマンド実行 status_zfs_destroy = subprocess.call([ 'zfs', 'destroy', name_snapshot ], stdout=subprocess.PIPE) ## コマンド応答ステータスが0であれば成功した旨出力 if status_zfs_destroy == 0: print ( "destroy " + name_snapshot + " SUCCESS." ) ## コマンド応答ステータスが0以外であれば失敗した旨と応答ステータスを出力 else: print ( "destroy " + name_snapshot + " FAIL. CODE = " + str ( status_zfs_destroy ) )
では。