[OCI]Always FreeのAutonomous Databaseのみを使用してDBCSインスタンスの自動起動/停止をスケジューリングしてみた

# はじめに
PL/SQL SDKとDBMS_SCHEDULERによるジョブの自動実行を組み合わせて、Always FreeのAutonomous Databaseのみを使用してDatabase Cloud Serviceの自動起動/停止をスケジューリングしてみました。

こちらの手順では、リソース・プリンシパルを使用していますので、[こちら](https://docs.oracle.com/cd/E83857_01/paas/autonomous-database/adbsa/resource-principal-use.html#GUID-EE5C24AD-34A5-4474-9B6A-9F606AABBA98)のドキュメントを参考にして、あらかじめadminユーザーに対して、Autonomous Databaseインスタンスのリソース・プリンシパルを有効にしておく必要があります。

また、こちらの内容はあくまで検証のため、エラーハンドリング等は行っておりません。
本番環境で行う際はきちんとエラーハンドリング、リトライ処理を実装されることをお勧めします。
# 1.自動起動/停止の対象となるDBノードの情報を格納するテーブルの作成

自動起動/停止の対象となるDBノードの情報を格納するテーブル"dbnode_list"を作成します。

```sql:
SQL> CREATE TABLE dbnode_list
  2  (
  3  	dbnode_ocid VARCHAR2(128),
  4  	enable_flg NUMBER NOT NULL,
  5  	PRIMARY KEY (dbnode_ocid)
  6   );

表が作成されました。

SQL>
```
# 2.自動起動/停止の対象となるDBノードの情報をテーブルに追加
対象となるDBノードのOCIDをdbnode_listテーブルに追加します。

DBCS（DBシステム VM）の場合、DBノードのOCIDを指定して起動/停止を行います。
自動起動/停止の対象となるDBノードのOCIDをコピーし、メモしておきます。
![スクリーンショット 2022-02-14 8.37.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784824/16e8232e-602e-e24e-3c2a-eb2511151d75.png)

dbnode_ocid列に自動起動/停止の対象となるDBノードのOCIDを、enable_flgに1をセットします。
※enable_flgに0を入れると、レコードを削除せずに自動起動/停止の対象から外せるようにしています。

```sql:
SQL> INSERT INTO dbnode_list VALUES ('ocid1.dbnode.oc1.ap-tokyo-1.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',1);

1行が作成されました。

SQL> INSERT INTO dbnode_list VALUES ('ocid1.dbnode.oc1.ap-tokyo-1.yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy',1);

1行が作成されました。

SQL> COMMIT;

コミットが完了しました。

SQL> 
```
以上で準備が整いました。

# 3.対象DBノードを起動/停止するPL/SQLブロックの作成

dbnode_listテーブルから起動対象となるDBノードのOCIDのリストを取得し、行数分だけループしてDBノードを起動するPL/SQLブロックを作成しました。

```sql:
SQL> set serveroutput on
SQL> DECLARE
  2   response_body	dbms_cloud_oci_database_db_node_t;
  3   response		dbms_cloud_oci_db_database_db_node_action_response_t;
  4  
  5   CURSOR target_ocid_cur IS SELECT * FROM dbnode_list WHERE enable_flg = 1;
  6   target_ocid target_ocid_cur%ROWTYPE;
  7  
  8  BEGIN
  9   OPEN target_ocid_cur;
 10    LOOP
 11     FETCH target_ocid_cur into target_ocid;
 12     EXIT WHEN target_ocid_cur%NOTFOUND;
 13  
 14      DBMS_OUTPUT.PUT_LINE('OCID:'||target_ocid.dbnode_ocid);
 15  
 16      response := DBMS_CLOUD_OCI_DB_DATABASE.db_node_action (
 17       db_node_id => target_ocid.dbnode_ocid,
 18       action => 'START',
 19       region => 'ap-tokyo-1',
 20       credential_name => 'OCI$RESOURCE_PRINCIPAL'
 21      );
 22    END LOOP;
 23   CLOSE target_ocid_cur;
 24  END;
 25  /
OCID:ocid1.dbnode.oc1.ap-tokyo-1.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
OCID:ocid1.dbnode.oc1.ap-tokyo-1.yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy

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

SQL> 
```
問題なく実行されました。
コンソールでDBノードの状態を確認してみます。
![スクリーンショット 2022-02-14 8.44.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784824/524d2db5-08be-9959-e4ed-e81516b91432.png)
![スクリーンショット 2022-02-14 8.44.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784824/414f445b-ea8d-27c7-31e6-6d7f7786b28e.png)
DBノードの状態が「起動中」になりました。

少し待つと、DBノードの状態が「使用可能」になりました。
![スクリーンショット 2022-02-14 8.45.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784824/3ffa5290-13ff-f825-31ad-e7e6e821f3ed.png)
![スクリーンショット 2022-02-14 8.45.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784824/13fa49fe-4943-5775-2c96-9b27e1b546fa.png)

同様に、dbnode_listテーブルから停止対象となるDBノードのOCIDのリストを取得し、行数分だけループしてDBノードを停止するPL/SQLブロックを作成しました。

```sql:
SQL> DECLARE
  2   response_body	dbms_cloud_oci_database_db_node_t;
  3   response		dbms_cloud_oci_db_database_db_node_action_response_t;
  4  
  5   CURSOR target_ocid_cur IS SELECT * FROM dbnode_list WHERE enable_flg = 1;
  6   target_ocid target_ocid_cur%ROWTYPE;
  7  
  8  BEGIN
  9   OPEN target_ocid_cur;
 10    LOOP
 11     FETCH target_ocid_cur into target_ocid;
 12     EXIT WHEN target_ocid_cur%NOTFOUND;
 13  
 14      DBMS_OUTPUT.PUT_LINE('OCID:'||target_ocid.dbnode_ocid);
 15  
 16      response := DBMS_CLOUD_OCI_DB_DATABASE.db_node_action (
 17       db_node_id => target_ocid.dbnode_ocid,
 18       action => 'STOP',
 19       region => 'ap-tokyo-1',
 20       credential_name => 'OCI$RESOURCE_PRINCIPAL'
 21      );
 22    END LOOP;
 23   CLOSE target_ocid_cur;
 24  END;
 25  /
OCID:ocid1.dbnode.oc1.ap-tokyo-1.anxhiljrssl65iqastfccxy7uy7jhsbew5kie2dcd32lrra
sjhw2fk7sf3ba
OCID:ocid1.dbnode.oc1.ap-tokyo-1.anxhiljrssl65iqaqh34fzzskhnmkazprirl42wuuift7ca
grfg5rqo5nsga

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

SQL>
```
問題なく実行されました。
コンソールでDBノードの状態を確認してみます。
![スクリーンショット 2022-02-14 8.34.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784824/5510efa7-1bc3-3560-2f4d-7f93f0a9586a.png)
![スクリーンショット 2022-02-14 8.34.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784824/1e6f1906-e131-f388-0214-1ce3adc20a6e.png)
DBノードの状態が「停止中」になりました。

少し待つと、DBノードの状態が「停止済」になりました。
![スクリーンショット 2022-02-14 9.08.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784824/6fc1811a-f9b4-1ab8-a356-b0c216a6ea1f.png)
![スクリーンショット 2022-02-14 9.08.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784824/58689219-8c8c-8be5-1f5e-6eabe9a826eb.png)

# 4.対象DBノードを起動/停止するストアド・プロシージャの作成
対象のDBノードを起動するストアド・プロシージャ "start_dbnode" を作成します。

```sql:
SQL> CREATE OR REPLACE PROCEDURE start_dbnode
  2  IS
  3   response_body	dbms_cloud_oci_database_db_node_t;
  4   response		dbms_cloud_oci_db_database_db_node_action_response_t;
  5   CURSOR target_ocid_cur IS SELECT * FROM dbnode_list WHERE enable_flg = 1;
  6   target_ocid target_ocid_cur%ROWTYPE;
  7  
  8  BEGIN
  9   OPEN target_ocid_cur;
 10    LOOP
 11     FETCH target_ocid_cur into target_ocid;
 12     EXIT WHEN target_ocid_cur%NOTFOUND;
 13  
 14      response := DBMS_CLOUD_OCI_DB_DATABASE.db_node_action (
 15       db_node_id => target_ocid.dbnode_ocid,
 16       action => 'START',
 17       region => 'ap-tokyo-1',
 18       credential_name => 'OCI$RESOURCE_PRINCIPAL'
 19      );
 20    END LOOP;
 21   CLOSE target_ocid_cur;
 22  END;
 23  /

プロシージャが作成されました。

SQL>
```
ストアド・プロシージャstart_dbnodeを実行してみます。

```sql:
SQL> EXECUTE start_dbnode;

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

SQL>
```
問題なく実行されました。
コンソールでDBノードが起動されたかを確認してみます。
![スクリーンショット 2022-02-14 8.44.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784824/e7ece1ff-1eb4-ce30-3615-daf59e1bbedc.png)
![スクリーンショット 2022-02-14 8.44.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784824/b145d9af-e055-5b24-4fd1-04e6d9bad79d.png)
対象のDBノードが起動されていることが確認できました。

同様に、対象のDBノードを停止するストアド・プロシージャ "stop_dbnode" を作成します。

```sql:
SQL> CREATE OR REPLACE PROCEDURE stop_dbnode
  2  IS
  3   response_body	dbms_cloud_oci_database_db_node_t;
  4   response		dbms_cloud_oci_db_database_db_node_action_response_t;
  5  
  6   CURSOR target_ocid_cur IS SELECT * FROM dbnode_list WHERE enable_flg = 1;
  7   target_ocid target_ocid_cur%ROWTYPE;
  8  
  9  BEGIN
 10   OPEN target_ocid_cur;
 11    LOOP
 12     FETCH target_ocid_cur into target_ocid;
 13     EXIT WHEN target_ocid_cur%NOTFOUND;
 14  
 15      response := DBMS_CLOUD_OCI_DB_DATABASE.db_node_action (
 16       db_node_id => target_ocid.dbnode_ocid,
 17       action => 'STOP',
 18       region => 'ap-tokyo-1',
 19       credential_name => 'OCI$RESOURCE_PRINCIPAL'
 20      );
 21    END LOOP;
 22   CLOSE target_ocid_cur;
 23  END;
 24  /

プロシージャが作成されました。

SQL>
```
ストアド・プロシージャstop_dbnodeを実行してみます。

```sql:
SQL> EXECUTE stop_dbnode;

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

SQL>
```
問題なく実行されました。

コンソールで対象のDBノードが停止されたかを確認してみます。
![スクリーンショット 2022-02-14 8.34.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784824/f34cc72a-884a-5d28-3436-1b1507ffba1e.png)
![スクリーンショット 2022-02-14 8.34.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784824/46f9b27f-b758-fe67-7123-5f58b033040e.png)
対象のDBノードが停止されていることが確認できました。

# 5.DBMS_SCHEDULERジョブの作成

作成したストアド・プロシージャをDBMS_SCHEDULERのジョブとして登録します。

DBノードを起動するストアド・プロシージャstart_dbnodeを毎日日本時間8:00に実行するジョブ"start_dbnode_job"を作成します。

```sql
SQL> BEGIN
  2    DBMS_SCHEDULER.CREATE_JOB (
  3     job_name           =>  'START_DBNODE_JOB',
  4     job_type           =>  'STORED_PROCEDURE',
  5     job_action         =>  'ADMIN.START_DBNODE', -- ストアド・プロシージャ名
  6     start_date         =>  TO_TIMESTAMP_TZ('2022-02-13 08:00:00 +9:00','YYYY-MM-DD HH24:MI:SS TZH:TZM'), -- 初回実行日時（日本時間2022/2/13 8:00を指定）
  7     repeat_interval    =>  'FREQ=DAILY;INTERVAL=1', -- 実行頻度（毎日実行）
  8     auto_drop          =>  FALSE,
  9     enabled            =>  TRUE
 10     );
 11  END;
 12  /

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

SQL>
```

同様に、DBノードを停止するストアド・プロシージャstop_dbnodeを毎日日本時間18:00に実行するジョブ"stop_dbnode_job"を作成します。

```sql
SQL> BEGIN
  2    DBMS_SCHEDULER.CREATE_JOB (
  3     job_name           =>  'STOP_DBNODE_JOB',
  4     job_type           =>  'STORED_PROCEDURE',
  5     job_action         =>  'ADMIN.STOP_DBNODE', -- ストアド・プロシージャ名
  6     start_date         =>  TO_TIMESTAMP_TZ('2022-02-13 18:00:00 +9:00','YYYY-MM-DD HH24:MI:SS TZH:TZM'), -- 初回実行日時（日本時間2022/2/13 18:00を指定）
  7     repeat_interval    =>  'FREQ=DAILY;INTERVAL=1', -- 実行頻度（毎日実行）
  8     auto_drop          =>  FALSE,
  9     enabled            =>  TRUE
 10     );
 11  END;
 12  /

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

SQL>
```

以上で、Autonomous Databaseを使用してDBノードの自動起動/停止をスケジューリングすることができました。

# 参考情報

[DBMS_CLOUDでのリソース・プリンシパルの使用](https://docs.oracle.com/cd/E83857_01/paas/autonomous-database/adbsa/resource-principal-use.html#GUID-EE5C24AD-34A5-4474-9B6A-9F606AABBA98)
[DBMS_CLOUD_OCI_DB_DATABASE.DB_NODE_ACTIONファンクション](https://docs.oracle.com/en-us/iaas/pl-sql-sdk/doc/dbms_cloud_oci_db_database.html#ADSDK-GUID-F44F533F-B283-4FA3-ACEA-4A70C3B33D44)
[DBMS_SCHEDULER.CREATE_JOBプロシージャ](https://docs.oracle.com/cd/F19136_01/arpls/DBMS_SCHEDULER.html#GUID-7E744D62-13F6-40E9-91F0-1569E6C38BBC)