# VMware Skyline Health Diagnostics(SHD)使用 - Part4: API 使用
###### tags: `skyline` `vmware`
:::success
用人力做試誤測試,叫做**浪費時間**。但是透過電腦做同樣的事,卻是**機器學習**?
:::
先說 VMware 官方並未提供 SHD 的 API 相關資訊。發現 SHD 的 API 真的是**無心之過**!
:::danger
**以下 API 相關操作並非按照由官方文件,僅作為類研究性質**。或許下個版本官方會出說明文件。
:::
[toc]
# 從日誌紀錄開始
在研究 SHD 安裝時發現,SHD 將相關程式及服務都放在目錄 **`/opt/vmware-shd/vmware-shd/`** 中,以下是目錄結構。
![080.png](https://i.imgur.com/W0fEMjf.png)
另外,相關 SHD 的系統日誌及分析報告紀錄都放在 **`/opt/vmware-shd/vmware-shd/log`**。
![081.png](https://i.imgur.com/Tn2tdV2.png)
至於目錄裡有哪些日誌紀錄,請自行研究。有關 **`vmware-shd-task-{TASK_ID}.log`** 的紀錄都是診斷報告產生的,若想了解執行診斷報告時的過程,或是發生什麼問題無法產出報告,都可根據 **`TASK ID`** 找到對應的日誌紀錄查詢。
其他的日誌內容從檔名也可大致**猜**出用途。這邊就不浪費時間研究了。
回到不小心發現 API 的日誌檔是 **access.log**。這應該是 Nginx 網頁伺服器的存取紀錄。
![082.png](https://i.imgur.com/OzbG7wr.png)
從以上的截圖可以看到,從我的筆電(10.7.30.98)向 SHD 設備(Nginx)進行請求 **`GET`** 呼叫,回覆狀態碼為 `200`,後面接著就是 API 的 URI?
另外在目錄 **`/opt/vmware-shd/vmware-shd/app/apiserver`** 發現以下檔案?
![083.png](https://i.imgur.com/F3XIgBn.png)
:::success
當然使用瀏覽器提供的開發者檢測(Inspect)工具,也是不錯的選擇。
![109.png](https://i.imgur.com/yh7etTG.png)
不過,這次就從日誌紀錄文件簡單開始吧!?
:::
# 觀察日誌紀錄
大概方向就按照上述模式,使用以下兩種界面同時進行觀察。
- 使用瀏覽器連線 SHD 管理界面,正常登入並進行界面操作。
- 使用 SSH 連線 SHD 終端界面,並即時監控 **`/opt/vmware-shd/vmware-shd/log/access.log`**。
```bash
tail -f access.log
```
![084.png](https://i.imgur.com/pI35Bdr.png)
## 登入界面
從登入紀錄查看,當成功登入 SHD 管理界面時,會從以下動作開始:
**POST `/api/v1/token/get`**
看來要先取得**授權金鑰**。接著管理界面會進入 **Analyze** 頁面,並進行不同的 API 呼叫取得相關資訊,並正確顯示於 UI 界面。
其中,UI 界面下方會顯示分析報告的任務狀態,看來是透過以下 API 請求達成:
**GET `/api/v1/task/status/<TASK_ID>`**
就以上述已知的資訊,先透過 API 的好伴侶 **Postman** 進行初步的簡易呼叫測試吧。
## 取得授權金鑰
撰寫 Postman 的部份就不贅述了,套用先前使用 Postman 的經驗,完成請求設定。
:::info
**資訊**
- API: **POST | `https://{{SHD_IP}}/api/v1/token/get`**
- Request Body:
```json
{
"username": "{{shd_username}}",
"password": "{{shd_password}}"
}
```
:::
![085.png](https://i.imgur.com/rWDMFb3.png)
- 使用 Test 腳本,將授權金鑰儲存成環境變數。
```javascript=
let res = pm.response.json();
let message = res.message;
pm.environment.set("refresh_token", res.refresh_token);
pm.environment.set("access_token", res.access_token);
console.log(message);
```
![086.png](https://i.imgur.com/kyLzFVo.png)
- 執行請求,確認測試狀態。
![087.png](https://i.imgur.com/FUiNL64.png)
- 完成後同時將授權金鑰寫入環境變數,以便後續請求使用。
![088.png](https://i.imgur.com/O2baqq6.png)
# 任務摘要資訊
在 **Analyze** 界面中下方提供任務(Tasks)執行摘要資訊。從日誌紀錄顯示與 **`GET /api/v1/task/list`** 有關。
:::info
**資訊**
- API: **GET | `https://{{SHD_IP}}/api/v1/task/list/{{limit}}`**
- 其中 {{limit}} 應是顯示限制,預設值為 **`10`**。可以是任意正整數,但必須存在。
:::
- 撰寫簡單請求。
![089.png](https://i.imgur.com/FY0RwOu.png)
- 取得任務資訊。
![090.png](https://i.imgur.com/7m2iBxo.png)
- 從 Postman Console 就能快速得到訊息。
![091.png](https://i.imgur.com/4t7dFG0.png)
# 更新資訊
既然基本操作模式已經確認,就在 SHD 的管理 UI 界面任意逛逛吧。
## 工具升級
選擇 **Settings** > **Upgrade & History** > **Tool Update**。目前 SHD 為最新版本,所以並無更新紀錄。若要更新 SHD ,可點擊 **CHECK TOOL UPDATES**。
![103.png](https://i.imgur.com/a4mVPrV.png)
:::info
**資訊**
- **`GET /api/v1/manage/update/upgrades/5`**
- **`GET /api/v1/manage/update/downloads/5`**
- **`5`** 是預設的顯示限制。
- **`POST /api/v1/manage/update/test`**
- **`GET /api/v1/manage/update/check`**
:::
為了完成以上一系列的 API 動作,可以執行 Postman 的 **Run Collection**。先將上述的請求設定完成,然後透過 **Run Collection**,便能進行整個流程的呼叫操作。
### 請求設定
以下是摘要截圖紀錄。
- Collection: Tool Update
![092.png](https://i.imgur.com/kC88gwD.png)
- Request: Refresh Token
![093.png](https://i.imgur.com/5OL88NH.png)
> 全部請求的認證方式都採用 **Bearer Token**。
![094.png](https://i.imgur.com/ZGJAhQE.png)
- Request: Get Upgrade History Summary
![095.png](https://i.imgur.com/PsWBVzd.png)
- Reuqest: Get Download History Summary
![096.png](https://i.imgur.com/dKDKdDa.png)
- Request: Test Tool Update Respository
![097.png](https://i.imgur.com/gEW0Dcw.png)
- Request: Check Tool Updates
![098.png](https://i.imgur.com/3hAMUSi.png)
### 執行集合請求
選擇建立的集合(Collection),點擊 **Run collection**。
![099.png](https://i.imgur.com/6cnPvie.png)
選擇集合中所有請求設定,若有需要可調整執行順序。預設重複執行次數為 **`1`** 次。確認後點擊藍色按鈕執行。
![100.png](https://i.imgur.com/sJ8Aige.png)
執行完成後,點擊橘色 **View Summary** 可查看執行摘要。每個請求都似乎執行成功!
![101.png](https://i.imgur.com/aYaSMF9.png)
再從 Console 視窗檢視透過 Test 腳本所取得的資訊是否符合。
![102.png](https://i.imgur.com/DynTs1v.png)
:+1: 看起來還可以喔。
:::info
關於更新日誌可檢視 **`/opt/vmware-shd/vmware-shd/log/vmware-shd-update.log`** 內容。
:::
:::success
透過簡單的 API 請求呼叫,就可以不用透過 UI 界面完成所需作業。
:::
## VCG 升級
選擇 **Settings** > **Upgrade & History** > **VCG Update**。若要更新資料 ,可點擊 **UPDATE VCG DATABASE**。
![104.png](https://i.imgur.com/RdbKhWC.png)
:::info
**資訊**
- **`GET /api/v1/extentions/vcg/status`**
- **`POST /api/v1/extentions/vcg/check`**
- **`POST /api/v1/extentions/vcg/update`**
:::
完成以上系列動作,便能進行 VCG 資料庫更新,並取得目前更新後狀態資訊。
![104.png](https://i.imgur.com/ZBEpwnz.png)
### 執行!
按照先前的模式及架構完成請求設定,執行集合請求。流程正常並無錯誤訊息。
![105.png](https://i.imgur.com/I7jEk9i.png)
從 Console 視窗顯示 Test 腳本執行結果。看來使用 API 請求可以正確執行 VCG 資料庫更新作業。
![106.png](https://i.imgur.com/5a071Bv.png)
從 **`/opt/vmware-shd/vmware-shd/log/access.log`** 紀錄中比對執行的 API 行為。
![107.png](https://i.imgur.com/drv3TDr.png)
關於 VCG 更新的日誌紀錄,可查詢 **`/opt/vmware-shd/vmware-shd/log/vmware-shd-vcgupdate.log`**。
![108.png](https://i.imgur.com/SFHgHKx.png)
# 報告排程
報告排程似乎也可以!選擇上方功能 **Scheduler**。
## 查詢排程資訊
:::info
- **`GET /api/v1/manage/scheduler/schedule`**
:::
![110.png](https://i.imgur.com/S99qdQ1.png)
![111.png](https://i.imgur.com/R8hiA4y.png)
## 查詢排程功能選項
:::info
- **`GET /api/v1/manage/scheduler/options`**
:::
![112.png](https://i.imgur.com/6DnMB8c.png)
![113.png](https://i.imgur.com/ZPlR8sD.png)
## 查詢排程功能狀態
:::info
- **`GET /api/v1/extentions/enc/state`**
:::
![115.png](https://i.imgur.com/J6lmGya.png)
![116.png](https://i.imgur.com/IU4Umj6.png)
## 關閉排程功能
:::info
- **`DELETE /api/v1/extentions/enc/state`**
:::
![114.png](https://i.imgur.com/P9NQVgB.png)
使用集合請求,執行關閉排程後檢查排程狀態。
![117.png](https://i.imgur.com/75lFXf7.png)
![118.png](https://i.imgur.com/545y9di.png)
## 開啟排程功能
:::info
- **`POST /api/v1/extentions/enc/state`**
:::
<font color=red>**目前這個功能實際用法無法得知,僅能知道使用何種請求方式**</font>。還記得要(重新)啟用排程功能時,需要設定一組密碼?所以需要引入相關參數,不過因為沒有 **VMware 官方說明**且能力限制,並無法確實知道其帶入參數及引用方式,如果之後原廠願意釋出 API 說明再說吧!殘念! :cry: :no_good:
:::danger
能透過 API 使用軟體,對於不太習慣 UI 方式或需要客製化時,還真的方便不少。目前原廠對於 SHD 有關 API 的資訊並不太多!
:::
有點喪氣,再看看其他幾個地方吧。
# 設備資訊
選擇上方功能選單 **Settings** > **About**。
![119.png](https://i.imgur.com/VQ7dPtX.png)
這裡的 **Tool Details** 和 **Resource Utilization** 可透過以下 API 請求取得。
:::info
- **`GET /api/v1`**
- **`GET /api/v1/manage/osstats`**
:::
- 取得 SHD 工具資訊
![120.png](https://i.imgur.com/IXIyAmw.png)
- 顯示 SHD 使用資源
![121.png](https://i.imgur.com/YX1NIHh.png)
- Postman Console 結果
![122.png](https://i.imgur.com/o6zcmDL.png)
# CEIP 設定
選擇上方功能選單 **Settings** > **Customer Experience Improvement Program**。
![123.png](https://i.imgur.com/2VG9dKV.png)
可透過以下方式進行。
:::info
- **`GET /api/v1/manage/ceip`**
- **`POST /api/v1/manage/ceip?ceip=1`**
- **`POST /api/v1/manage/ceip?ceip=0`**
- **`GET /api/v1/manage/ceipsample`**
:::
## 取得 CEIP 狀態
![124.png](https://i.imgur.com/LJJ6Ez7.png)
## 加入 CEIP
![125.png](https://i.imgur.com/Qy8jiRI.png)
## 退出 CEIP
![126.png](https://i.imgur.com/PcfvUCl.png)
## 顯示 CEIP 傳送的資料範本
![127.png](https://i.imgur.com/UU2Ktzf.png)
# 驗證主機進行分析
應該這是惡搞 API 使用的最後部份了,基本上還是以查看報告資訊為主。
在進行查看報告部份之前,讓我們先回到檢視任務狀態。選擇 **Analyze** > **Connect and Analyze**,界面中間下方顯示任務執行列表。
其中 **任務編號(ID)** 也是在檢視報告時會利用的 **報告編號(ID)**。而 **Bundle Name** 就是報告名稱。
![128.png](https://i.imgur.com/iJPvmyZ.png)
![131.png](https://i.imgur.com/KtBUu4S.png)
## 驗證 vCenter
從以下任務狀態截圖,可得知一個排程報告任務(Schedule Task)進行時發生問題,原因是 **Task Failed - This Target is not part of Trusted List**。
![132.png](https://i.imgur.com/UiZEqQ4.png)
所以在執行診斷報告或日常排程報告之前,SHD 都必須先將要進行分析的主機或是 vCenter/SDDC Manager 完成連線驗證,並加入至**信任清單(Trusted List)**。這部份的動作需要透過以下的 **Check Connection** 來達成。而且**沒有完成連結,是沒有辦法執行診斷分析的**。
![133.png](https://i.imgur.com/GwAC5sJ.png)
![134.png](https://i.imgur.com/ez6ZrXR.png)
## 查詢信任清單
可以透過以下來查詢主機是否存在於信任清單中。
:::info
- **`GET /api/v1/extentions/trust/entry?target={HOSTNAMW | HOST_IP}`**
:::
vCenter 主機驗證並非在信任清單中。
![135.png](https://i.imgur.com/La4NE6D.png)
![136.png](https://i.imgur.com/xfmOXMt.png)
## 信任清單新增紀錄
若要增加紀錄於信任清單,可使用以下請求完成。
:::info
- **`POST /api/v1/extentions/trust/entry`**
- Request Body:
```json
{
"target": "{{target}}",
"issuer": "{{traget_issuer}}",
"thumbprint": "{{traget_thumbprint}}"
}
```
> 以上 **Body** 是測試過可以成功的。
:::
![137.png](https://i.imgur.com/qjjBdg3.png)
![138.png](https://i.imgur.com/dv5booW.png)
## 確認 API 連結
可以透過以下方式進行。目前這個請求應該只是用 vCenter/ESXi 主機。SDDC Manager 的部份沒有環境無法測試,應該也差不多吧。
:::info
- **`POST /api/v1/extentions/vcenter/check`**
- Request Body:
```json
{
"target": "{{target}}",
"username": "{{target_user}}",
"password": "{{target_pass}}"
}
```
> Body 內容需要提供對應驗證主機的登錄資訊。
:::
指揮挺組合!
![139.png](https://i.imgur.com/I9o3jqg.png)
若要一次完成上列動作,可以將相關請求放在同一個資料夾執行。
![140.png](https://i.imgur.com/r8bim49.png)
![141.png](https://i.imgur.com/1dygCe5.png)
![142.png](https://i.imgur.com/v8UCWch.png)
:::warning
**注意**
在沒有將主機加入至信任清單前,是無法成功結合的!也表示無法透過該主機進行分析診斷。
![143.png](https://i.imgur.com/vvmhwqt.png)
:::
## 信任清單刪除紀錄
若要在信任清單中刪除紀錄,可使用以下請求完成。
:::info
- **`DELETE /api/v1/extentions/trust/entry`**
- Request Body:
```json
{
"target": "{{target}}"
}
```
:::
![144.png](https://i.imgur.com/WSYWRpX.png)
# 報告檢視
檢視報告前必須要建立診斷報告,可以使用手動或定期排程的方式產生。還記得手動產生報告需要選擇要執行的插件(Plugins)和詳細目錄(Inventory)。
![145.png](https://i.imgur.com/y2ssTrs.png)
另外還可指定標籤(Tag)和日誌天數。
![146.png](https://i.imgur.com/cfncpiH.png)
## 產生報告
先說結果:<font color=red>**目前還是無法透過 API 產生分析報告!**</font> 沒有原廠的 API 應用指南,能力有限的我沒法測試出對應的請求參數。
雖然如此,還是找到幾個可以利用的 API URI。
:::info
- **`POST /api/v1/extentions/vcenter/inventory`**
- **`GET /api/v1/analyze/limitdays`**
- **`POST /api/v1/extentions/vcenter/rundiag`**
:::
- 取得欲診斷的詳細目錄。
![150.png](https://i.imgur.com/02gwaZo.png)
- 取得診斷的日誌限制天數設定。<font color=red>目前找不到該如何組態日誌限制天數</font>!
![151.png](https://i.imgur.com/VmPpX9O.png)
- 執行診斷分析。<font color=red>目前可以啟動診斷報告流程,但可能缺少關鍵的參數,所以請求的診斷都會失敗!</font>
![152.png](https://i.imgur.com/zVjZrAV.png)
從請求本體(Request Body)需要提供診斷需要執行的插件(plugincats)。
另外撰寫 Test 腳本可以在 Consloe 畫面顯示:
- 目前報告執行狀態。
- 任務編號。
- 檢視任務的 URI 位置。
![153.png](https://i.imgur.com/0FOH8St.png)
:::warning
- 目前執行診斷報告這部份算是沒有幫助。若有進一步官方提供的 API 資訊的話,應該就不是問題了!對於自動化需求應該還是需要使用 API 請求的方式。
- 或許解答在這!這邊沒能力浪費時間了。
![154.png](https://i.imgur.com/LyuJrmd.png)
- 還是覺得有點可惜!
:::
## 檢視報告製作流程
但如果這部份暫時先從 UI 執行診斷報告,還是可以透過請求的方式來檢視出一些有用的資訊。
執行診斷報告時,會產生一組任務編號(Task ID),使用先前介紹的請求檢視指定報告編號的執行狀態。
:::info
- **`GET /api/v1/task/status/{TASK_ID}`**
:::
從截圖可得知任務編號(`45e9d1a77f9ff872`)相關資訊:
- 執行狀態(Status)
- 狀態訊息(Message)
- 執行總步驟(Steps)及數量(Totalsteps)
- 目前執行步驟(Currentstep)
![147.png](https://i.imgur.com/jkXxLpf.png)
在 Console 畫面也可透過 Test 腳本直接顯示訊息。
![148.png](https://i.imgur.com/HRbgbAo.png)
與 UI 界面顯示內容比較。在下圖 UI 界面右上方的 **REFRESH TASKS** 按鈕,在報告執行診斷階段時點擊可刷新執行狀態。使用 API 請求就是重複執行請求即可。
![149.png](https://i.imgur.com/gNMTQM6.png)
## 檢視報告
### 顯示報告摘要
當診斷報告執行完成,會在任務狀態中顯示報告執行摘要。可以根據任務編號(Task ID)選擇,點擊 **`SHOW SUMMARY`** 檢視報告執行摘要。
![155.png](https://i.imgur.com/Vibwyq1.png)
或是點擊 **`SHOW REPORT`** 檢視報告。便會轉至 **Show Reports** 功能頁面。UI 界面中因為有指定任務編號(即報告編號)所以只會顯示該報告,如果想要看目前所有的報告清單,點擊左側 **`All reports`**,便會顯示目前**成功完成**的診斷報告列表。
![156.png](https://i.imgur.com/2hjjkHV.png)
檢視報告可使用以下請求達成。
:::info
- **`GET /api/v1/task/list/10`**
- **`GET /api/v1/extentions/vcenter/diagsummary/{TASK_ID}`**
- **`GET /api/v1/summary/latest/50`**
- 報告清單預設顯示最近的 **`50`** 筆報告紀錄。不過,在 API 請求中將顯示筆記調整 **> 50**,似乎也沒有問題。
:::
先檢視目前成功完成的診斷報告清單。
![157.png](https://i.imgur.com/YmSHacj.png)
![158.png](https://i.imgur.com/DYbC24Z.png)
指定任務編號 **`25c090df291aa236`** 進行檢視。首先使用任務狀態請求,查詢報告相關資訊。其中可以發現**報告編號(Bundle ID)其實與任務編號(Task ID)是相同一致的**。
![159.png](https://i.imgur.com/Ha6ThKQ.png)
檢視診斷報告的摘要資訊。
![160.png](https://i.imgur.com/8cCsMls.png)
與 UI 界面比較。
![161.png](https://i.imgur.com/kCwzgl2.png)
### 查看指定報告
選擇顯示報告後,點擊報告名稱(Bundle Name)左側 **`>>`** 圖示,將會在右側區域展開報告中所有的日誌紀錄資訊(Log)。以下表示該報告包含 **5** 組日誌紀錄。其中每組日誌紀錄會顯示發現的問題數量(No of Issues)。
![162.png](https://i.imgur.com/ZHcpZ0p.png)
點選各個日誌紀錄名稱(Log Name)左側 **`>`** 圖示,可顯示該日誌發現出問題的描述說明。
![163.png](https://i.imgur.com/wKE4GIh.png)
可用以下請求達成。
:::info
- **`GET /api/v1/summary/bundle/{BUNDLE_ID}`**
:::
回覆訊息大致可了解:
- Pluginsrun: 診斷插件執行數量。
- Pluginsmatched: 診斷插件執行符合數量。符合表示有問題!
- Pluginsfailed: 診斷插件執行失敗數量。
- records: 表示該報告中包含的日誌分析紀錄數量。
> 其他部份可憑參數名稱臆測。
![164.png](https://i.imgur.com/WpkfEel.png)
透過 Test 腳本撰寫,可將請求回覆訊息快速整理。另外,每個紀錄都會有對應的編號(ID)。
![165.png](https://i.imgur.com/85oGHdm.png)
若要進一步了解該日誌訊息,可指定該紀錄編號進行請求。
:::info
- **`GET /api/v1/summary/log/{LOG_ID}`**
:::
![166.png](https://i.imgur.com/9POjwp6.png)
透過 Test 腳本撰寫可以整理請求回覆訊息。可與先前 UI 界面顯示比較。
![167.png](https://i.imgur.com/O7GHdk2.png)
其實產生的診斷分析報告便是依照 **Bundle Name(ID)** > **Log Name(ID)** > **Plugin Name(ID)** 逐層建構的,所以只要從最上層的 **Task ID(等同 Bundle ID)** 查詢對應的 Log ID/Plugin ID,便能透過對應的 API 請求獲取對應的資訊。
![168.png](https://i.imgur.com/FL3oGaV.png)
透過以上找出來的 API 應用一下,就可以找出對應關係。
![173.png](https://i.imgur.com/l3AVoRu.png)
從 **bundle id** 找出對應的 **log id**。這邊可以知道診斷報告目前有 **`7`** 份(**Bundle Count = 7**)。每個報告裡包含的 **[Log 數量]** 就是對應的分析目標的日誌項目。
![172.png](https://i.imgur.com/AhBLVVP.png)
然後每個 **Log Report** 裡包含執行符合的 **Plugin 數量**,就是診斷出有問題的數量。
![171.png](https://i.imgur.com/3EDeteg.png)
透過迴圈執行就可以將所有的編號取出!
![169.png](https://i.imgur.com/dN82AMw.png)
![170.png](https://i.imgur.com/46PjGX0.png)
## 下載報告和線上檢視報告
成功完成的報告都可以下載和線上檢視。
![174.png](https://i.imgur.com/WFL8JfR.png)
![175.png](https://i.imgur.com/JXrBWWa.png)
也可以透過以下方式進行操作。
:::info
- **`GET /api/v1/report/bundle/{BUNDLE_ID}?plugincats=DIAGNOSTICS,VMSA_SCAN,VSAN_SCAN,VCG_CHECK,VC_HEALTH`**
- **`GET /api/v1/report/log/{LOG_ID}`**
- **`GET /api/v1/report/plugin/{PLUGIN_ID}`**
:::
不過透過這種方式下載或顯示的 HTML 檔案,<font color=red>頁面並沒有顯示很正確</font>。不知道還要套用什麼格式,這部份就真的不知道了!
![176.png](https://i.imgur.com/9Dc0ynG.png)
![177.png](https://i.imgur.com/5GPs6Ck.png)
## 刪除報告
終於,剩下最後的清除部份。只要知道 **bundle id** 就可以使用以下操作刪除整份報告。若要進行刪除多筆報告(Delete Multiple Bundles),就是執行多次動作即可。
:::info
- **`POST /api/v1/summary/delete/{BUNDLE_ID}`**
:::
![178.png](https://i.imgur.com/5HgTNSC.png)
---
:::success
- 雖然浪費了一些時間,但每次透過這樣的 API 測試操作,往往都會對於該功能進一步的了解,多少還是有所幫助的。
- 這套產品對於離線使用環境的管理者,還是能增加對於管理環境的問題取得一定程度的掌握程度,還是可以利用的。
- 如果可以,原廠還是把 API 文件補齊吧!
:::
---
- [Part1: 安裝及界面](https://hackmd.io/@farmer87/shd_01)
- [Part2: 功能操作](https://hackmd.io/@farmer87/shd_02)
- [Part3: 報告排程](https://hackmd.io/@farmer87/shd_03)
- [Part4: API 使用](https://hackmd.io/@farmer87/shd_04)