前提
どうしてもansibleでOracleDBにimpdpをしなくてはいけなくなった
ご存知の通りansibleにはOracleのモジュールが圧倒的に少ないため、泣く泣くwin_shellでimpdpコマンドを直接実行することになった
問題
なぜか結果が全く帰ってこない。
impdp自体は3分ぐらいで終わるのだが、winrmのタイムアウトをいくら設定しなおしても結果が帰ってこない
失敗にもならない
どうしたか
しょうがないのでimpdpのログをtailすることに
- name: execute impdp itself
win_shell: "impdp system/manager directory={{ DIRECTORY_NAME }} dumpfile=dmp.dmp table_exists_action=append logfile=dmp.log"
async: 20
poll: 0
- name: watch impdp log until it is over
win_shell: "Get-Content -Path {{ DUMP_PATH }}\\dmp.log -Tail 1"
register: tail
until: tail.stdout.find('正常に完了') != -1
retries: 40
delay: 30
各taskの解説
impdp
# 非同期にしたい処理
async: # 任意の秒数
poll: 0
で、fire and forget(非同期処理を一回発火させ、無視して次に進む)が実現できる
pollに1以上の値を入れるとその回数だけ結果をチェックするようになるが、
結果が「帰ってこない」というのが問題なのでチェックしても意味が無い
tail
# 何かの同期処理
register: tail
until: tail.stdout # 任意の判定
retries: # 任意の回数
delay: # 任意の秒数
で、同期処理によりその瞬間のステータスを好きな方法で取得できる
untilにregisterした変数のstdoutプロパティに対する判定を適当に書けばOK
untilの中身がtrueになった時点で成功になり、次の処理に向かうようになる
retriesはリトライする回数、delayはリトライ間隔を指定できる
今回は40 * 30 = 1200 (20分)ぐらいがマックスの時間になる
最後までuntilのプレディケートを満たさなかった場合はfailとなる
最後に
こんなのやらないほうがいい
冪等性ないし