Esegui il peering di cluster e SVM

Questa pagina descrive come configurare il peering per il pool di archiviazione ONTAP in Google Cloud NetApp Volumes.

Il peering del cluster e il peering della macchina virtuale di archiviazione (SVM) collegano il pool di archiviazione ONTAP Flex Unified a un altro cluster. In questo modo è possibile eseguire servizi come SnapMirror e FlexCache.

Utilizza lo script peer_cluster.py per accettare un'offerta e inserire una passphrase per un pool in modalità ONTAP. Per saperne di più, consulta Script di peering del cluster.

Scegli una procedura

Scegli una delle seguenti procedure di peering in base alla tua configurazione:

  • Peering ibrido: esegui la migrazione o la replica da un pool in modalità ONTAP a un volume NetApp Volumes in modalità predefinita (Standard, Premium, Extreme, o Flex Unified in modalità predefinita). NetApp Volumes avvia il peering dalla destinazione. Completa il peering nel pool di origine in modalità ONTAP.

  • Peering manuale: stabilisci il peering autonomamente e non utilizzi un flusso di lavoro di migrazione ibrida o di replica esterna. Seleziona uno scenario:

    • Un pool in modalità ONTAP e un cluster ONTAP esterno on-premise o al di fuori di NetApp Volumes.

    • Due pool in modalità ONTAP.

Per saperne di più sulle opzioni di peering aggiuntive nel cluster ONTAP esterno, consulta la documentazione di NetApp ONTAP.

Come funziona il peering del cluster in un pool in modalità ONTAP

La procedura di peering del cluster segue un flusso di lavoro di offerta e accettazione:

  • Offerta: un cluster avvia il peering verso gli indirizzi IC-LIF peer e riceve una passphrase.

  • Accettazione: il cluster peer completa il peering utilizzando gli indirizzi IC-LIF del cluster di offerta e la passphrase.

Il proxy dell'interfaccia a riga di comando ONTAP non è interattivo. Il comando cluster peer create -generate-passphrase non richiede l'input, quindi puoi eseguire l'offerta su un pool in modalità ONTAP utilizzando ontap_execute. Elenca tutti gli indirizzi IC-LIF remoti come valore -peer-addrs separato da virgole. Il comando cluster peer accept richiede la passphrase, quindi questo passaggio non riesce tramite il proxy. Utilizza peer_cluster.py quando un pool in modalità ONTAP deve accettare un'offerta.

Per eseguire il peering dei cluster, utilizza uno dei seguenti scenari:

  • Scenario A (ONTAP in modalità ONTAP e ONTAP esterno): esegui cluster peer create-generate-passphrase nel pool in modalità ONTAP utilizzando ontap_execute con tutti gli indirizzi IC-LIF peer. L'amministratore ONTAP esterno esegue cluster peer accept al prompt del cluster con tutti gli indirizzi IC-LIF in modalità ONTAP e inserisce la passphrase.

  • Scenario B (due pool in modalità ONTAP): esegui cluster peer create-generate-passphrase nel pool A utilizzando ontap_execute, quindi esegui peer_cluster.py con PEER_MODE=accept nel pool B.

Esegui il peering SVM eseguendo vserver peer accept utilizzando ontap_execute nel pool in modalità ONTAP. Nello scenario A, il cluster ONTAP esterno esegue vserver peer create.

Metodi di replica che richiedono il peering

I seguenti metodi di replica richiedono il peering:

  • Qualsiasi origine ONTAP in modalità ONTAP Flex Unified (SnapMirror): esegui il peering nel pool in modalità ONTAP.

  • Modalità ONTAP Flex Unified in qualsiasi destinazione ONTAP (SnapMirror): esegui il peering nel pool in modalità ONTAP.

  • Origine in modalità ONTAP in NetApp Volumes in modalità predefinita (migrazione dei volumi o replica esterna): utilizza il peering ibrido nel pool di origine in modalità ONTAP.

La replica dei volumi in modalità predefinita all'interno di NetApp Volumes non utilizza il peering del cluster ONTAP.

Peering ibrido

Utilizza questa sezione quando l'origine è un pool in modalità ONTAP e la destinazione è un volume in modalità predefinita in NetApp Volumes.

Come funziona NetApp Volumes

Il flusso di lavoro di peering ibrido include i seguenti passaggi:

  1. Crea una migrazione dei volumi o una replica esterna nel volume di destinazione volume nella Google Cloud console o utilizzando Google Cloud CLI. Specifica il nome del cluster di origine in modalità ONTAP, la SVM, il volume e gli indirizzi IC-LIF di origine.

  2. Se il peering del cluster non è già stabilito, NetApp Volumes controlla la connettività nella destinazione, genera una passphrase e visualizza le istruzioni di peering.

  3. Devi eseguire i passaggi di peering rimanenti nel pool di origine in modalità ONTAP, perché NetApp Volumes non esegue comandi automatici nel pool di origine.

Non puoi invertire questo ordine. Devi creare prima la destinazione in modalità predefinita.

Completa il peering del cluster nell'origine in modalità ONTAP

Recupera la passphrase e gli indirizzi IC-LIF di destinazione nella Google Cloud console nella scheda Replica o Migrazione oppure utilizzando Google Cloud CLI:

 gcloud netapp volumes replications list --volume=DESTINATION_VOLUME --location=LOCATION \
  --format="table(hybridPeeringDetails.command,hybridPeeringDetails.passphrase,hybridPeeringDetails.subnetIp)"

Nel pool di origine in modalità ONTAP, accetta il peering offerto da NetApp Volumes nella destinazione. Configura ontap_execute come descritto in Procedure comuni in modalità ONTAP. Imposta POOL_NAME e LOCATION per il pool di origine. Elenca tutti gli indirizzi IC-LIF di destinazione in PEER_IC_LIF_IPS, quindi esegui peer_cluster.py con PEER_MODE=accept:

 export PROJECT_ID="myproject"
 export LOCATION="us-central1-a"
 export POOL_NAME="ontap-mode-source-pool"
 export PEER_MODE="accept"
 export PEER_IC_LIF_IPS="DESTINATION_IC_LIF_IP_1,DESTINATION_IC_LIF_IP_2"
 export PASSPHRASE="passphrase-from-gcnv-console"

 python3 peer_cluster.py

Verifica la configurazione nel pool di origine:

 ontap_execute "cluster peer show"

Completa il peering SVM nell'origine in modalità ONTAP

Se NetApp Volumes non completa automaticamente il peering SVM, visualizza un comando di peering vserver. Esegui il comando utilizzando ontap_execute o accetta il peer in attesa:

 ontap_execute "vserver peer accept -vserver SOURCE_SVM_NAME -peer-vserver PEER_SVM_NAME"

Verifica la configurazione:

 ontap_execute "vserver peer show"

Torna al flusso di lavoro ibrido nella Google Cloud console o esegui gcloud netapp volumes replications list per verificare che la replica o la migrazione sia in corso.

Peering manuale

Utilizza questa sezione quando stabilisci il peering autonomamente senza un flusso di lavoro ibrido, ad esempio prima di SnapMirror tra un pool in modalità ONTAP e un cluster ONTAP esterno o tra due pool in modalità ONTAP.

Prima di iniziare

Completa i seguenti prerequisiti:

  1. Verifica che gli IC-LIF nel pool in modalità ONTAP raggiungano gli IC-LIF del cluster peer. Gli IC-LIF nei pool in modalità ONTAP si trovano in IPspace Gcnv; nei cluster ONTAP esterni si trovano in IPspace Default. Testa ICMP e le porte intercluster richieste.

  2. Configura ontap_execute prima di iniziare.

  3. Raccogli il nome del cluster, il nome della SVM e tutti gli indirizzi IP IC-LIF del cluster peer nel pool in modalità ONTAP. Fornisci un indirizzo per nodo, separato da virgole. Il numero di IC-LIF corrisponde al numero di nodi del cluster peer.

  4. Condividi il nome del cluster del pool, il nome della SVM e tutti gli indirizzi IC-LIF con l'amministratore del cluster peer.

Panoramica

Per eseguire il peering manuale dei cluster e delle SVM, segui questi passaggi:

  1. Configura ontap_execute

  2. Cerca nomi e IC-LIF

  3. Verifica la connettività

  4. Cluster peer

  5. SVM peer

  6. Verifica il peering

Cerca nomi e IC-LIF

In ogni pool in modalità ONTAP, esegui i comandi di ricerca descritti in Procedure comuni in modalità ONTAP.

Elenca gli indirizzi IC-LIF, che dipendono dalle dimensioni del pool, e forniscili all'amministratore del cluster peer.

Verifica la connettività

Esegui un comando ping per eseguire il peering degli IC-LIF dal tuo pool utilizzando il flag -vserver Gcnv:

 ontap_execute "network ping -vserver Gcnv -destination PEER_IC_LIF_IP -lif intercluster-1"

Risolvi i problemi di routing o firewall prima di continuare. Se il ping non riesce tra i pool, consulta Perché NetApp Volumes non riesce a raggiungere Active Directory (e altre reti dietro il VPC) per indicazioni su VPC e rete partner.

Cluster peer

Per eseguire il peering dei cluster, utilizza uno dei seguenti scenari:

Scenario A: pool in modalità ONTAP e ONTAP esterno

Per eseguire il peering di un pool in modalità ONTAP con un cluster ONTAP esterno:

  1. Offerta nel pool in modalità ONTAP: esegui il cluster peer create -generate-passphrase comando utilizzando ontap_execute con tutti gli indirizzi IC-LIF peer. Copia la passphrase dall'output comando.

  2. Accettazione in ONTAP esterno: l'amministratore del cluster peer esegue il comando cluster peer accept al prompt ONTAP con tutti gli indirizzi IC-LIF in modalità ONTAP e inserisce la passphrase.

Per offrire il peering nel pool in modalità ONTAP:

 ontap_execute "cluster peer create -ipspace Gcnv -peer-addrs PEER_IC_LIF_1,PEER_IC_LIF_2 -generate-passphrase"

Elenca tutti gli indirizzi IC-LIF per il cluster peer nel flag -peer-addrs, separati da virgole. Aggiungi indirizzi aggiuntivi se il cluster peer ha più di due nodi.

ONTAP visualizza la passphrase nell'output del comando in Passphrase:. Copia immediatamente la passphrase; ONTAP avvisa che non è possibile visualizzarla di nuovo.

Se il comando non riesce o l'output non include una passphrase, utilizza peer_cluster.py con PEER_MODE=offer invece. Per saperne di più, consulta Script di peering del cluster.

Copia la passphrase e inviala all'amministratore ONTAP esterno. Accetta l'offerta entro il periodo di validità della passphrase, che per impostazione predefinita è di un'ora.

Accetta l'offerta nel cluster ONTAP esterno al prompt del cluster peer elencando tutti gli indirizzi IC-LIF in modalità ONTAP:

 cluster peer accept -ipspace Default -peer-addrs ONTAP_MODE_IC_LIF_1,ONTAP_MODE_IC_LIF_2

Quando ONTAP ti chiede, inserisci la passphrase. Includi ogni indirizzo IC-LIF dal pool in modalità ONTAP.

Verifica la configurazione nel pool in modalità ONTAP:

 ontap_execute "cluster peer show"

Scenario B: due pool in modalità ONTAP

Per eseguire il peering di due pool in modalità ONTAP:

  1. Offerta nel pool A: esegui il comando cluster peer create -generate-passphrase utilizzando ontap_execute nel pool A. Elenca tutti gli indirizzi IC-LIF dal pool B in -peer-addrs. Copia la passphrase.

  2. Accettazione nel pool B: esegui peer_cluster.py con PEER_MODE=accept nel pool B ed elenca tutti gli indirizzi IC-LIF dal pool A in PEER_IC_LIF_IPS.

Offerta nel pool A:

 ontap_execute "cluster peer create -ipspace Gcnv -peer-addrs POOL_B_IC_LIF_1,POOL_B_IC_LIF_2 -generate-passphrase"

Elenca tutti gli IC-LIF dal pool B, separati da virgole. Aggiungi indirizzi aggiuntivi quando il pool B ha più di due nodi. Copia il valore Passphrase: dall'output comando.

Se il comando non riesce, utilizza peer_cluster.py con PEER_MODE=offer nel pool A.

Accettazione nel pool B:

 export PROJECT_ID="myproject"
 export LOCATION="us-west1-b"
 export POOL_NAME="pool-b"
 export PEER_MODE="accept"
 export PEER_IC_LIF_IPS="POOL_A_IC_LIF_1,POOL_A_IC_LIF_2"
 export PASSPHRASE="passphrase-from-pool-a"

 python3 peer_cluster.py

Elenca tutti gli IC-LIF dal pool A in PEER_IC_LIF_IPS.

Verifica la configurazione in ogni pool:

 ontap_execute "cluster peer show"

Verifica che la disponibilità sia Disponibile e che l'autenticazione sia OK.

SVM peer

Dopo che il peering del cluster è riuscito, crea un peer SVM per SnapMirror. Se hai bisogno di FlexCache, aggiungilo al flag -applications.

Scenario A: pool in modalità ONTAP e ONTAP esterno

Per eseguire il peering di un pool in modalità ONTAP con un cluster ONTAP esterno:

  1. Crea in ONTAP esterno: l'amministratore del cluster peer esegue il comando vserver peer create al prompt ONTAP.

  2. Accetta nel pool in modalità ONTAP: esegui il comando vserver peer accept utilizzando ontap_execute.

Crea il peer nel cluster ONTAP esterno al prompt del cluster peer:

 vserver peer create -vserver PEER_SVM_NAME -peer-vserver ONTAP_MODE_SVM_NAME \
  -peer-cluster ONTAP_MODE_CLUSTER_NAME -applications snapmirror

Accetta il peer nel pool in modalità ONTAP:

 ontap_execute "vserver peer accept -vserver ONTAP_MODE_SVM_NAME -peer-vserver PEER_SVM_NAME"

Scenario B: due pool in modalità ONTAP

Per eseguire il peering di due pool in modalità ONTAP:

  1. Crea nel pool A: esegui il comando vserver peer create utilizzando ontap_execute nel pool A (o peer_svm.py se il comando create non è disponibile).

  2. Accetta nel pool B: esegui il comando vserver peer accept utilizzando ontap_execute nel pool B.

Crea il peer nel pool A:

 ontap_execute "vserver peer create -vserver POOL_A_SVM -peer-vserver POOL_B_SVM -peer-cluster POOL_B_CLUSTER_NAME -applications snapmirror"

Accetta il peer nel pool B:

 ontap_execute "vserver peer accept -vserver POOL_B_SVM -peer-vserver POOL_A_SVM"

Non creare lo stesso peer SVM in entrambi i pool.

Verifica il peering

Per verificare il peering nel pool in modalità ONTAP:

 ontap_execute "cluster peer show"
 ontap_execute "vserver peer show"

Verifica che la disponibilità del peer del cluster sia Disponibile e che lo Stato del peer SVM sia peered.

Per lo scenario B, ripeti la procedura nel secondo pool. L'amministratore ONTAP esterno può verificare la configurazione eseguendo cluster peer show e vserver peer show nel cluster peer.

Quando non esistono peer del cluster, il comando cluster peer show restituisce che la voce non esiste.

Elimina il peering

Elimina i peer SVM prima dei peer del cluster.

Per eliminare un peer SVM in un pool, eliminalo per rimuovere la relazione su entrambi i lati quando i pool sono raggiungibili.

 ontap_execute "vserver peer delete -vserver LOCAL_SVM_NAME -peer-vserver PEER_SVM_NAME"

Il proxy dell'interfaccia a riga di comando ONTAP non supporta l'eliminazione dei peer del cluster. Per eliminare un peer del cluster, eliminalo tramite UUID tramite l'API REST.

Innanzitutto, elenca i peer per trovare l'UUID:

 TOKEN=$(gcloud auth print-access-token)
 curl -s -H "Authorization: Bearer $TOKEN" \

 "https://netapp.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/storagePools/POOL_NAME/ontap/api/cluster/peers"

Elimina ogni UUID restituito:

 curl -s -X DELETE -H "Authorization: Bearer $TOKEN" \

 "https://netapp.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/storagePools/POOL_NAME/ontap/api/cluster/peers/PEER_UUID"

Ripeti questa procedura in entrambi i pool in modalità ONTAP in Scenario B. Per lo scenario A, esegui cluster peer delete nel cluster ONTAP esterno, se necessario.

Script di peering del cluster

Salva il seguente script come peer_cluster.py. Utilizzalo in un pool in modalità ONTAP quando quel pool deve accettare un'offerta di peering del cluster (PEER_MODE=accept). Il peering ibrido e lo scenario B utilizzano la modalità accept. Utilizza la modalità offer (PEER_MODE=offer) solo se cluster peer create -generate-passphrase non riesce tramite ontap_execute o non restituisce una passphrase. Questo script richiede Python 3.8 o versioni successive e la libreria standard Python.

 #!/usr/bin/env python3
"""Cluster peer offer or accept on an ONTAP-mode pool through the NetApp Volumes REST proxy."""

import json
import os
import subprocess
import sys
import time
import urllib.error
import urllib.request

REQUIRED = ("PROJECT_ID", "LOCATION", "POOL_NAME", "PEER_MODE")
missing = [name for name in REQUIRED if not os.environ.get(name)]
if missing:
    sys.exit(f"Set required environment variables: {', '.join(missing)}")

PROJECT_ID = os.environ["PROJECT_ID"]
LOCATION = os.environ["LOCATION"]
POOL_NAME = os.environ["POOL_NAME"]
PEER_MODE = os.environ["PEER_MODE"].lower()
POLL_INTERVAL = int(os.environ.get("POLL_INTERVAL", "10"))

API_ROOT = (
    f"https://netapp.googleapis.com/v1/projects/{PROJECT_ID}"
    f"/locations/{LOCATION}/storagePools/{POOL_NAME}/ontap/api"
)

def parse_ip_list(value: str) -> list:
    return [ip.strip() for ip in value.replace("#", ",").split(",") if ip.strip()]

def get_access_token() -> str:
    return subprocess.check_output(
        ["gcloud", "auth", "print-access-token"], text=True
    ).strip()

def api_request(method: str, path: str, body=None) -> dict:
    headers = {
        "Authorization": f"Bearer {get_access_token()}",
        "Content-Type": "application/json",
    }
    data = json.dumps(body).encode() if body is not None else None
    req = urllib.request.Request(f"{API_ROOT}{path}", data=data, headers=headers, method=method)
    try:
        with urllib.request.urlopen(req) as resp:
            return json.loads(resp.read())
    except urllib.error.HTTPError as exc:
        detail = exc.read().decode()
        sys.exit(f"API request failed ({exc.code}): {detail}")

def job_record(response: dict) -> dict:
    return response.get("rawResponse") or response.get("body") or response

def job_state(response: dict) -> str:
    return job_record(response).get("state", "")

def format_job_error(response: dict) -> str:
    record = job_record(response)
    message = record.get("message") or record.get("error", {}).get("message")
    if message:
        return message
    return json.dumps(response, indent=2)

def wait_for_job(job_uuid: str) -> None:
    print(f"ONTAP job UUID: {job_uuid}")
    while True:
        response = api_request("GET", f"/cluster/jobs/{job_uuid}")
        state = job_state(response)
        print(f"  Job state: {state}")
        if state == "success":
            return
        if state in ("failure", "error"):
            sys.exit(f"Job failed: {format_job_error(response)}")
        time.sleep(POLL_INTERVAL)

def extract_passphrase(response: dict) -> str:
    body = response.get("body") or response.get("rawResponse") or {}
    records = body.get("records") or []
    if records:
        auth = records[0].get("authentication") or {}
        if auth.get("passphrase"):
            return auth["passphrase"]
    auth = body.get("authentication") or {}
    return auth.get("passphrase", "")

def build_offer_body() -> dict:
    if not os.environ.get("PEER_IC_LIF_IPS"):
        sys.exit("Set PEER_IC_LIF_IPS for offer mode")

    payload = {
        "remote": {"ip_addresses": parse_ip_list(os.environ["PEER_IC_LIF_IPS"])},
        "authentication": {"generate_passphrase": True},
        "ipspace": {"name": os.environ.get("IPSPACE", "Gcnv")},
    }

    expiry = os.environ.get("EXPIRY_TIME")
    if expiry:
        payload["authentication"]["expiry_time"] = expiry

    local_svm = os.environ.get("LOCAL_SVM_NAME")
    if local_svm:
        payload["initial_allowed_svms"] = [{"name": local_svm}]

    apps = os.environ.get("PEER_APPLICATIONS", "snapmirror")
    payload["peer_applications"] = [a.strip() for a in apps.split(",") if a.strip()]

    encryption = os.environ.get("ENCRYPTION_PROPOSED")
    if encryption:
        payload["encryption"] = {"proposed": encryption}

    return {"body": payload}

def build_accept_body() -> dict:
    for name in ("PEER_IC_LIF_IPS", "PASSPHRASE"):
        if not os.environ.get(name):
            sys.exit(f"Set {name} for accept mode")

    return {
        "body": {
            "remote": {"ip_addresses": parse_ip_list(os.environ["PEER_IC_LIF_IPS"])},
            "authentication": {"passphrase": os.environ["PASSPHRASE"]},
            "ipspace": {"name": os.environ.get("IPSPACE", "Gcnv")},
        }
    }

def main() -> None:
    if PEER_MODE == "offer":
        body = build_offer_body()
        print("Creating cluster peer offer...")
    elif PEER_MODE == "accept":
        body = build_accept_body()
        print("Accepting cluster peer offer...")
    else:
        sys.exit("PEER_MODE must be 'offer' or 'accept'")

    response = api_request("POST", "/cluster/peers?return_records=true", body)

    job = (response.get("body") or {}).get("job") or response.get("job")
    if job and job.get("uuid"):
        wait_for_job(job["uuid"])

    if PEER_MODE == "offer":
        passphrase = extract_passphrase(response)
        if passphrase:
            print(f"\nPassphrase (provide to the peer pool): {passphrase}")
        else:
            print(json.dumps(response, indent=2))

if __name__ == "__main__":
    main()

Variabili di ambiente facoltative: EXPIRY_TIME, PEER_APPLICATIONS (impostazione predefinita snapmirror), ENCRYPTION_PROPOSED e IPSPACE (impostazione predefinita Gcnv).

Script di peering SVM (fallback)

Utilizza peer_svm.py solo quando vserver peer create non è disponibile tramite il proxy dell'interfaccia a riga di comando ONTAP. Utilizza invece vserver peer create e vserver peer accept come descritto in SVM peer.

 #!/usr/bin/env python3
"""Create an SVM peer on an ONTAP-mode pool (fallback when vserver peer create is unavailable)."""

import json
import os
import subprocess
import sys
import time
import urllib.error
import urllib.request

REQUIRED = (
    "PROJECT_ID", "LOCATION", "POOL_NAME",
    "LOCAL_SVM_NAME", "PEER_CLUSTER_NAME", "PEER_SVM_NAME",
)
missing = [name for name in REQUIRED if not os.environ.get(name)]
if missing:
    sys.exit(f"Set required environment variables: {', '.join(missing)}")

PROJECT_ID = os.environ["PROJECT_ID"]
LOCATION = os.environ["LOCATION"]
POOL_NAME = os.environ["POOL_NAME"]
LOCAL_SVM_NAME = os.environ["LOCAL_SVM_NAME"]
PEER_CLUSTER_NAME = os.environ["PEER_CLUSTER_NAME"]
PEER_SVM_NAME = os.environ["PEER_SVM_NAME"]
APPLICATIONS = [
    app.strip()
    for app in os.environ.get("APPLICATIONS", "snapmirror").split(",")
    if app.strip()
]
POLL_INTERVAL = int(os.environ.get("POLL_INTERVAL", "10"))

API_ROOT = (
    f"https://netapp.googleapis.com/v1/projects/{PROJECT_ID}"
    f"/locations/{LOCATION}/storagePools/{POOL_NAME}/ontap/api"
)

def get_access_token() -> str:
    return subprocess.check_output(
        ["gcloud", "auth", "print-access-token"], text=True
    ).strip()

def api_request(method: str, path: str, body=None) -> dict:
    headers = {
        "Authorization": f"Bearer {get_access_token()}",
        "Content-Type": "application/json",
    }
    data = json.dumps(body).encode() if body is not None else None
    req = urllib.request.Request(f"{API_ROOT}{path}", data=data, headers=headers, method=method)
    try:
        with urllib.request.urlopen(req) as resp:
            return json.loads(resp.read())
    except urllib.error.HTTPError as exc:
        sys.exit(f"API request failed ({exc.code}): {exc.read().decode()}")

def format_job_error(response: dict) -> str:
    record = response.get("rawResponse") or response.get("body") or response
    message = record.get("message") or record.get("error", {}).get("message")
    return message or json.dumps(response, indent=2)

def wait_for_job(job_uuid: str) -> None:
    while True:
        response = api_request("GET", f"/cluster/jobs/{job_uuid}")
        record = response.get("rawResponse") or response.get("body") or response
        state = record.get("state", "")
        print(f"  Job state: {state}")
        if state == "success":
            print("SVM peer relationship created.")
            return
        if state in ("failure", "error"):
            sys.exit(f"Job failed: {format_job_error(response)}")
        time.sleep(POLL_INTERVAL)

def main() -> None:
    body = {
        "body": {
            "svm": {"name": LOCAL_SVM_NAME},
            "peer": {
                "cluster": {"name": PEER_CLUSTER_NAME},
                "svm": {"name": PEER_SVM_NAME},
            },
            "applications": APPLICATIONS,
        }
    }
    response = api_request("POST", "/svm/peers?return_records=true", body)
    job = (response.get("body") or {}).get("job") or response.get("job")
    if not job or not job.get("uuid"):
        print(json.dumps(response, indent=2))
        return
    wait_for_job(job["uuid"])

if __name__ == "__main__":
    main()

Passaggi successivi