レック・テクノロジー・コンサルティング株式会社TECH BLOG

EnterpriseManager でバックアップ情報を連携(Part2)

前回までで、「Veeam Backup Enterprise Manager(以下、VBEMとします)」の実装もできましたので、PythonからAPIで接続してみたいと思います。

Pythonからのジョブ情報取得

Veeam Enterprise Manager」に、APIエンドポイントにアクセスするためには、ポート9398を利用します。Veeam Enterprise Managerでも、Veeam Backup & Replicationと同じく、SwaggerUIが用意されています。
https://(VBEMIPアドレス):9398/swagger
正常にアクセスできる場合、以下のような画面が表示されます。
image1.png

では実際に、APIを利用してログインし、登録されているジョブの情報を取得してみます。以下のようなスクリプトを実行します。


import requests
import urllib3

urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

base_url = "https://(EnterpriseManagerのIPアドレス)/api"
username = "(EnterpriseManagerの管理者アカウントIPアドレス)"  
password = "(EnterpriseManagerの管理者アカウントパスワード)"

session = requests.Session()
headers = {"Content-Type": "application/xml"}

# ログイン(セッション開始)
login_response = session.post(
    f"{base_url}/sessionMngr/?v=latest",
    auth=(username, password),
    headers=headers,
    verify=False
)

if login_response.status_code == 201:
    token = login_response.headers.get("X-RestSvcSessionId")

    # AcceptヘッダーでJSONを要求
    session.headers.update({
        "X-RestSvcSessionId": token,
        "Accept": "application/json"
    })

    # ジョブ一覧取得
    jobs_response = session.get(f"{base_url}/jobs", verify=False)

    if jobs_response.status_code == 200:
        try:
            jobs = jobs_response.json()
            for job in jobs['Refs']:
                print(f"ジョブ名: {job['Name']}, URL: {job['Href']}")
        except Exception as e:
            print("JSONとしてパースできませんでした:", e)
    else:
        print("ジョブ取得失敗")

    session.delete(f"{base_url}/sessionMngr/", verify=False)

else:
    print(f"ログイン失敗: ステータスコード {login_response.status_code}")


APIへのログインですが、基本的にBasicHTTP認証か、TLS証明書を利用した認証がサポートされています。このスクリプトではBasicHTTP認証を使ってVBEMにログインしています。X-RestSvcSessionId というセッションIDを取得し、こちらを「認証トークン」としています。

# ログイン(セッション開始)
login_response = session.post(
    f"{base_url}/sessionMngr/?v=latest",
    auth=(username, password),
    headers=headers,
    verify=False
)
if login_response.status_code == 201:
    token = login_response.headers.get("X-RestSvcSessionId")

また、ログインに利用できるアカウントは、EntepriseManagerにて以下のロール権限を持っている必要があります。
・Portal Administrators(ポータル管理者)
・Portal Users(ポータル利用者)
・Restore Operators(リストアオペレータ)
該当ユーザは、VBEMの以下GUI(「設定」→「権限」)で確認できます。
image2.png


また、ユーザ名として、「ドメイン\user」というWindowsアカウントを利用する場合、「\」はエスケープシーケンスの対応として、記載を重ねる必要があります。例えば「DC1-VEEAM3Administorator」であれば、「DC1-VEEAM3\Administorator」と記載します。

ログインが完了すると、ヘッダに認証トークンをセットして、/jobエンドポイントからJSONでレスポンスを取得します。

    # ジョブ一覧取得
    jobs_response = session.get(f"{base_url}/jobs", verify=False)
    if jobs_response.status_code == 200:
        try:
            jobs = jobs_response.json()


取得したレスポンスから、ジョブの名称及び格納URLを取得します。

            for job in jobs['Refs']:
                print(f"ジョブ名: {job['Name']}, URL: {job['Href']}")


上記スクリプトを実行すると、以下のような結果が表示されます。
image3.pngこの結果は、VBEMに登録されているジョブと、そのジョブの詳細情報(設定、ステータスなど)が格納されているURLが表示されています。こちらから、Veeamの各ジョブの情報を取得できます。

Pythonからバックアップジョブのステータス取得

この結果を踏まえて、次はジョブの状態を取得することにします。以下のようなスクリプトを実行します。


import requests
import urllib3
urllib3.disable_warnings()

# 認証情報
base_url = "https://(EnterpriseManagerのIPアドレス)/api"
username = "(EnterpriseManagerの管理者アカウントIPアドレス)"  
password = "(EnterpriseManagerの管理者アカウントパスワード)"

session = requests.Session()
headers = {"Content-Type": "application/xml"}

# ログイン
login_response = session.post(
    f"{base_url}/sessionMngr/?v=latest",
    auth=(username, password),
    headers=headers,
    verify=False
)

if login_response.status_code == 201:
    token = login_response.headers.get("X-RestSvcSessionId")

    # AcceptヘッダーでJSONを要求
headers = {
    "X-RestSvcSessionId": token,
    "Accept": "application/json"
}

# すべてのジョブ一覧を取得
jobs_response = session.get(f"{base_url}/jobs", headers=headers, verify=False)
jobs = jobs_response.json()["Refs"]

for job in jobs:
    job_name = job["Name"]
    job_id = job["UID"].split(":")[-1]
    session_url = f"{base_url}/jobs/{job_id}/backupSessions"

    # バックアップセッション取得
    sess_response = session.get(session_url, headers=headers, verify=False)
    if sess_response.status_code != 200:
        print(f" {job_name} のセッション取得に失敗")
        continue

    sess_data = sess_response.json().get("Refs", [])
    if not sess_data:
        print(f"{job_name}: セッション履歴なし")
        continue

    # 最新のセッションだけ取得
    latest_sess = sess_data[0]
    sess_detail_url = latest_sess["Href"] + "?format=Entity"
    detail_response = session.get(sess_detail_url, headers=headers, verify=False)
    if detail_response.status_code != 200:
        print(f" {job_name} の詳細取得失敗")
        continue

    detail = detail_response.json()
    status = detail.get("Result", "Unknown")

    print(f"ジョブ: {job_name}")
    print(f"    結果: {status}\n")

# ログアウト
session.delete(f"{base_url}/logonSessions", headers=headers, verify=False)

前半の流れは、先程のスクリプトと同じです。 ジョブの情報を取得したあと、個々のジョブのセッション情報を取得し、「sess.data」という配列に格納します。



for job in jobs:
    job_name = job["Name"]
    job_id = job["UID"].split(":")[-1]
    session_url = f"{base_url}/jobs/{job_id}/backupSessions"

    # バックアップセッション取得
    sess_response = session.get(session_url, headers=headers, verify=False)
    if sess_response.status_code != 200:
        print(f" {job_name} のセッション取得に失敗")
        continue

    sess_data = sess_response.json().get("Refs", [])
    if not sess_data:
        print(f"{job_name}: セッション履歴なし")
        continue

「sess.data」つまりバックアップジョブのステータスが格納されている配列のうち、最新のもののみ取得して表示します。



    # 最新のセッションだけ取得
    latest_sess = sess_data[0]
    sess_detail_url = latest_sess["Href"] + "?format=Entity"
    detail_response = session.get(sess_detail_url, headers=headers, verify=False)
    if detail_response.status_code != 200:
        print(f" {job_name} の詳細取得失敗")
        continue

    detail = detail_response.json()
    status = detail.get("Result", "Unknown")

    print(f"ジョブ: {job_name}")
    print(f"    結果: {status}\n")


これを実行すると、以下のようにバックアップジョブの最新ステータスを確認できます。
get_status.png

いかがでしょうか?このスクリプトを活用して、バックアップジョブの実行結果をDBなどに格納し、それをGrafanaなどを利用して可視化することもできます。
このようにして、Veeam環境の運用管理を各種運用管理環境と連携することが可能となります。



この記事をシェアする

  • Facebook
  • X
  • Pocket
  • Line
  • Hatena
  • Linkedin

資料請求・お問い合わせはこちら

ページトップへ戻る