Glue Python ShellからRDS for Oracleを接続を試して断念

目的/やったこと

先にまとめ

  • Oracle ClientのLibraryをzip化&S3にアップロードし、Glue Python Shell から参照できるようにした
  • しかし、下記のエラーが発生し、対処法が特定できないためこの検証をストップした
    • DatabaseError: Error while trying to retrieve text for error ORA-01804
  • 2023/5/2 追記

試したことまとめ

  • 参考サイトに記載されている手順に従いzipファイルを作成
    • Oracle Client Libraryをダウンロード
    • libclntsh.soのrename
    • rpathの書き換え
    • libaio.so.1の生成
  • zipファイルをS3にアップロードし、glue の参照ライブラリ設定Referenced files pathに設定
  • Glue jobの処理に下記を追加
    • zipファイルが配置されているpathを突き止める
    • zipファイルを解凍
    • cx_Oracleにclient libraryのpathを設定
  • 正常に動作しなかったのでその他の方法を試した
    • client libraryのversionを変更
    • cx_Oracle.init_oracle_client(lib_dir='/xxx/xxxx/')を使用せずに、os.environ['ORACLE_HOME'] = '/tmp/oracle'でlibのpathを設定する
  • 結果エラーは変わらず断念

特にハマった箇所

rpathの書き換え

rpathとは wiki Rpath

rpathは、実行可能ファイルまたはライブラリにハードコードされた実行時検索パスを指定します。ダイナミックリンクローダーは、rpathを使用して必要なライブラリを検索します。 具体的には、共有ライブラリへのパスを実行可能ファイルのヘッダーにエンコードします

wikipedia.org/wiki/Rpath

ざっくり「参照する実行するファイルがどこに存在するかを設定しておくもの」ととりあえず認識しました

当初このrpathの書き換え作業をmac PCで実行していました(最終的にはCodeBuildで実行するようにした)

$brew install patchelf
$patchelf --set-rpath /tmp/libs/instantclient_21_9 libclntsh.so

ですが、正常にrpathが変更されたかを確認する術が不明でした

  • いくつかのライブラリ(readelfなど)を使ってみたけど正常に動かなった
  • さらにmacでは正常にrpathを書き換えられていない、との記事を見かけて更に不信感が募る

mac PCではなくAWS Cloud Shellで試そうとしたけど、oracle clientのzipをダウンロードして解凍する時点でDiskエラーが発生したためこちらも断念

その後、検証用に立てているEC2 instanceで試してなんとかrpathの設定ができた(rpathを書き換えたファイルをダウンロードするためにCloud ShellからSCPで接続して持ってきた)

最初からCodeBuildでやっておけばよかった….

libaio.so.1の生成

libaio.so.1を生成するために下記の手順が必要だったため、macで試したけどmake prefix=pwd/usr installの実行でエラーになった

なのでこちらもEC2で実行、後にCodeBuildで実行するようにした

glue の参照ライブラリが配置されるpathは実行毎に変わる

Reference file path で設定したファイルはGlue 実行時/tmp/glue-python-libs-xxxxxに配置される
pathのxxxxxの部分はランダム文字列で実行毎に違う値が入る

なので下記のような処理でどこに参照ファイル(今回はOracle ClientのLibrary)があるかを探す(面倒臭え..)

def get_referenced_filepath():
    for dir_name in sys.path:
        if dir_name.startswith('/tmp/glue-python-libs-'):
            return dir_name
    return ''

目的のzipを見つけた後、解凍する(面倒臭え..)

filename = 'instantclient-basic-linuxx64_patched.zip'
files = glob.glob(dir_name + "/" + filename)
with zipfile.ZipFile(files[0], 'r') as f:
    Path(dir_name + '/tmp').mkdir()
    f.extractall(dir_name + '/tmp')

感想

せっかく時間をとって調査したので、個人的につまった箇所を残しておきたく投稿しました

Stack Overflow unable-to-connect-oracle-database-using-cx-oracle-from-aws-glue の投稿を見つけた瞬間気持ちは「絶対Glue Python ShellからOracle繋げる!」気持ちになってしまい、諦めるタイミングが見極められず長々と奮闘してました

同じ境遇でなかなか諦めがつかない方にこの記事が見つかると良いな…

あと個人的に最近Cloud Shellに期待しがちになっていた…

Linuxコマンドの前処理が必要なケースで、サクッとlocalできなかったら、次はサクッとCodeBuildに移ろう…