[OCI]Autonomous DatabaseからAutonomous Databaseを作成してみた

# はじめに
こちらの記事は、[Oracle Cloud Infrastructure Advent Calendar 2022](https://qiita.com/advent-calendar/2022/oci)のDay 15の記事として書いています。

アドベント・カレンダーの記事ということで、普段書かないような、そして誰も書かないような記事を書きたいと思い、「Autonomous DatabaseからAutonomous Databaseを作る」という内容にしました。

Autonomous DatabaseにはPL/SQLからREST APIをコールするためのDBMS_CLOUD.SEND_REQUESTというファンクションおよびプロシージャが用意されていますので、こちらを利用したPL/SQLプログラムを作成し、Autonomous DatabaseからAutonomous Databaseを作成してみます。

# 1. PL/SQLプログラムの作成
Autonomous Databaseに用意されているDBMS_CLOUD.SEND_REQUESTファンクションを利用して、Autonomous Databaseを作成するOCIのREST API （CreateAutonomousDatabase）をコールするPL/SQLプログラムを作成します。

今回は。何度か訪れたことがあるサンノゼのリージョンにAutonomous Databaseを作成します。
ちなみに、このPL/SQLプログラムを実行しているAutonomous Databaseは東京リージョンにあります。

ということで、作成したPL/SQLプログラムがこちらです。

おおまかな処理の流れは、以下の通りです。
1.payloadという変数にAutonomous Database作成時のパラメータをセット
2.DBMS_CLOUD.SEND_REQUESTでREST API（CreateAutonomousDatabase）をコール

詳細な内容は、コメントをご確認ください。
```sql
DECLARE
  -- Autonomous Databaseを作成するコンパートメントのOCIDの設定
  compartment_ocid  VARCHAR2(100) := 'ocid1.compartment.oc1..aaaaxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxdkq';
  -- Autonomous Databaseを作成するリージョンの設定
  region            VARCHAR2(100) := 'us-sanjose-1';

  payload           JSON_OBJECT_T := JSON_OBJECT_T('{}');
  states_array      DBMS_CLOUD_TYPES.wait_for_states_t;
  resp              DBMS_CLOUD_TYPES.resp;

BEGIN
  -- Autonomous Databaseを作成するコンパートメントのOCIDの設定
  payload.put('compartmentId', compartment_ocid );
  -- 作成するAutonomous Databaseの表示名の設定
  payload.put('displayName', 'ADB_created_by_ADB');
  -- 作成するAutonomous Databaseのデータベース名の設定
  payload.put('dbName', 'adbcreatedbyadb');
  -- 作成するAutonomous Databasaeのワークロード・タイプの設定
  -- DW or OLTP or AJD or APEX
  payload.put('dbWorkload', 'DW');
  -- 作成するAutonomous DatabasaeのOCPU数の設定
  payload.put('cpuCoreCount', 1);
  -- 作成するAutonomous DatabasaeのOCPU自動スケーリングの設定
  payload.put('isAutoScalingEnabled', 'TRUE');
  -- 作成するAutonomous Databasaeのストレージサイズ（TB）
  payload.put('dataStorageSizeInTBs', 1);
  -- 作成するAutonomous Databasaeのストレージ自動スケーリングの設定
  payload.put('isAutoScalingForStorageEnabled', 'TRUE');
  -- 作成するAutonomous Databasaeのadminユーザのパスワードの設定
  payload.put('adminPassword', 'Demo#1Demo#1');
  -- 作成するAutonomous Databasaeのライセンスタイプの設定
  -- LICENSE_INCLUDED or BRING_YOUR_OWN_LICENSE
  payload.put('licenseModel', 'LICENSE_INCLUDED');
  -- 作成するAutonomous Databasaeの連絡先の電子メールの設定
  payload.put('customerContacts', JSON_ARRAY_T('[{"email":"xxxxxxxx@xxxxxx.com"},{"email":zzzzzzzz@zzz.com"}]'));
  -- APIをコール後、どの状態が返されるのを待つかを設定
  states_array := DBMS_CLOUD_TYPES.wait_for_states_t('SUCCEEDED');
  -- デバッグ用出力
  dbms_output.put_line(payload.to_clob||CHR(10));
  dbms_output.put_line('Send Create Autonomous Database Request');
  --  Autonomous Databaseを作成するAPIをコール
  resp := DBMS_CLOUD.SEND_REQUEST(
                       -- 使用するクレデンシャル
                       credential_name    => 'OCI$RESOURCE_PRINCIPAL',
                       -- Autonomous Databaseを作成するAPIのURI
                       uri                => 'https://database.'||region||'.oraclecloud.com/20160918/autonomousDatabases',
                       -- Autonomous Databaseを作成するAPIのメソッド
                       method             => DBMS_CLOUD.METHOD_POST,
                       -- Autonomous Databaseを作成するAPIコールのボディ
                       body               => UTL_RAW.cast_to_raw(payload.to_clob),
                       -- 非同期リクエストURL
                       async_request_url  => 'https://iaas.'||region||'.oraclecloud.com/20160918/workRequests',
                       -- 待機する状態（SUCCEED)
                       wait_for_states    => states_array,
                       -- APIコールのタイムアウト設定
                       timeout            => 600
                  );
  -- デバッグ用出力             
  dbms_output.put_line('resp body: '||DBMS_CLOUD.get_response_text(resp));
  dbms_output.put_line('resp headers: '||DBMS_CLOUD.get_response_headers(resp).to_clob);
END;
/
```

# 2. 作成したPL/SQLプログラムの実行

OCIコンソールでサンノゼ・リージョンのAutonomous Databaseのリストを表示しておきます。
この時点ではサンノゼ・リージョンにはAutonomous Databaseはありません。
![スクリーンショット 2022-12-09 22.25.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784824/12be5c23-eebf-7aac-ed00-0ae6b75c544e.png)
では、早速作成したPL/SQLブロックを実行してみます。
```
SQL> set serverroutput on
SQL> DECLARE
  2    compartment_ocid  VARCHAR2(100) := 'ocid1.compartment.oc1..aaaaxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxdkq';
  3    region		 VARCHAR2(100) := 'us-sanjose-1';
  4  
  5    payload		 JSON_OBJECT_T := JSON_OBJECT_T('{}');
  6    states_array	 DBMS_CLOUD_TYPES.wait_for_states_t;
  7    resp		     DBMS_CLOUD_TYPES.resp;
  8  
  9  BEGIN
 10    payload.put('compartmentId', compartment_ocid );
 11    payload.put('displayName', 'ADB_created_by_ADB');
 12    payload.put('dbName', 'adbcreatedbyadb');
 13    payload.put('dbWorkload', 'DW');
 14    payload.put('cpuCoreCount', 1);
 15    payload.put('isAutoScalingEnabled', 'TRUE');
 16    payload.put('dataStorageSizeInTBs', 1);
 17    payload.put('isAutoScalingForStorageEnabled', 'TRUE');
 18    payload.put('adminPassword', 'Demo#1Demo#1');
 19    payload.put('licenseModel', 'LICENSE_INCLUDED');
 20    payload.put('customerContacts', JSON_ARRAY_T('[{"email":"xxxxxxxx@xxxxxx.com"},{"email":"zzzzzzzz@zzz.com"}]'));
 21    states_array := DBMS_CLOUD_TYPES.wait_for_states_t('SUCCEEDED');
 22  
 23    dbms_output.put_line(payload.to_clob||CHR(10));
 24    dbms_output.put_line('Send Create Autonomous Database Request');
 25  
 26    resp := DBMS_CLOUD.SEND_REQUEST(
 27  			    credential_name   => 'OCI$RESOURCE_PRINCIPAL',
 28  			    uri 	          => 'https://database.'||region||'.oraclecloud.com/20160918/autonomousDatabases',
 29  			    method	          => DBMS_CLOUD.METHOD_POST,
 30  			    body	          => UTL_RAW.cast_to_raw(payload.to_clob),
 31  			    async_request_url => 'https://iaas.'||region||'.oraclecloud.com/20160918/workRequests',
 32  			    wait_for_states   => states_array,
 33  			    timeout	          => 600
 34  		       );
 35    dbms_output.put_line('resp body: '||DBMS_CLOUD.get_response_text(resp));
 36    dbms_output.put_line('resp headers: '||DBMS_CLOUD.get_response_headers(resp).to_clob);
 37  END;
 38  /
```
OCIコンソールでAutonomous Databaseのリストを確認してみると、PL/SQLプログラムからAPIをコールして作成した新しいAutonomous Database「ADB_created_by_ADB」のプロビジョニングが始まりました！
![スクリーンショット 2022-12-09 22.34.58のコピー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784824/78011b39-7e4a-db4f-c5c3-5a3b2fa07fc0.png)
少し待つとAutonomous Database「ADB_created_by_ADB」が使用可能になりました。
Autonomous DatabaseからAutonomous Databaseが作成できました！
![スクリーンショット 2022-12-09 22.34.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784824/1b408dbc-60cb-402f-fcc2-900f7cdd02e2.png)

PL/SQLブロックの実行結果（ログ出力）を確認してみるとstatusがSUCCEEDEDとなっており、こちらでもAutonomous Databaseが正常に作成されたことがわかりました。
```
{"ocid1.compartment.oc1..aaaaxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxdkq","displayName":"ADB_created_by_ADB","dbName":"adbcreatedby
adb","dbWorkload":"DW","cpuCoreCount":1,"isAutoScalingEnabled":"TRUE","dataStora
geSizeInTBs":1,"isAutoScalingForStorageEnabled":"TRUE","adminPassword":"Demo#1De
mo#1","licenseModel":"LICENSE_INCLUDED","customerContacts":[{"email":"xxxxxxxx@xxxxxx.com"},{"email":"zzzzzzzz@zzz.com"}]}


Send Create Autonomous Database Request
resp body: {"operationType":"Create Autonomous
Database","status":"SUCCEEDED","id":"ocid1.coreservicesworkrequest.oc1.us-sanjos
e-1.abzxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxkcq","compartmentId
":"ocid1.compartment.oc1..aaaxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxdkq","resources":[{"actionType":"CREATED","entityType":"autonomousDatabase","
identifier":"ocid1.autonomousdatabase.oc1.us-sanjose-1.anzxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxdyq","entityUri":"/20160918/autonomousDatabases/
ocid1.autonomousdatabase.oc1.us-sanjose-1.anzxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxdyq"}],"percentComplete":100.0,"timeAccepted":"2022-12-09T13:
32:30.856Z","timeStarted":"2022-12-09T13:32:37.422Z","timeFinished":"2022-12-09T
13:33:50.599Z"}
resp headers: {"Connection":"close","Date":"Fri, 09 Dec 2022 13:34:38
GMT","opc-request-id":"/923XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXA7C","Vary":"Accept-Encoding","Content-Type":"application/json","X-Content
-Type-Options":"nosniff","Content-Length":"771"}

PL/SQLプロシージャが正常に完了しました。

SQL> 
```
「ADB_created_by_ADB」の詳細画面を確認してみます。
データベース名、OCPU数、OCPU自動スケーリング、ストレージサイズ、ストレージの自動スケーリング、ライセンス・タイプ等の項目が設定値通りになっていることが確認できました。
めでたし、めでたし。
![スクリーンショット 2022-12-09 22.36.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784824/776f42fb-475d-2ef3-597f-f23e896d0f17.png)

# まとめ
無事タイトル通りに「Autonomous DatabaseからAutonomous Databaseを作る」ことができました。

実際にこんなことをする人はいらっしゃらないかもしれませんが、Autonomous Databaseに用意されているDBMS_CLOUD.SEND_REQUESTファンクション/プロシージャを使用してOCIのREST APIをコールすることで、こんなことまでできるということがお分かりいただけたのではないでしょうか。

例えば、こんなことにも応用できるかもしれません。
・Autonomous Databaseからデータ出力用のオブジェクト・ストレージ・バケットを作成する
・Autonomous Databaseからインスタンス・プールのインスタンス数を増減する
・Autonomous Databaseから通知サービスをキックして通知を行う

みなさんもAutonomous Databaseを使って、様々なタスクを自動化してみてはいかがでしょうか。

# 参考資料
・[DBMS_CLOUD.SEND_REQUESTファンクションおよびプロシージャ](https://docs.oracle.com/cd//E83857_01/paas/autonomous-database/adbsa/dbms-cloud-subprograms.html#GUID-B063870D-6C1F-4F33-B354-885B73C81D37)
・[API Reference and Endpoints：CreateAutonomousDatabase](https://docs.oracle.com/en-us/iaas/api/#/en/database/20160918/AutonomousDatabase/CreateAutonomousDatabase)
・[JSON用のPL/SQLオブジェクト型の使用](https://docs.oracle.com/cd/E96517_01/adjsn/using-PLSQL-object-types-for-JSON.html#GUID-F0561593-D0B9-44EA-9C8C-ACB6AA9474EE)