> ## Documentation Index
> Fetch the complete documentation index at: https://docs.preprod.world/llms.txt
> Use this file to discover all available pages before exploring further.

# Manage a Virtual GPU cluster

export const MethodSection = ({children}) => children ?? null;

export const MethodSwitch = ({children}) => {
  const tabs = React.Children.toArray(children).map(c => {
    if (!c || !c.props) return null;
    if (c.props.id) return c;
    const inner = c.props.children;
    if (inner && inner.props && inner.props.id) return inner;
    return null;
  }).filter(Boolean);
  const firstId = tabs.length > 0 ? tabs[0].props.id : "";
  const [active, setActive] = React.useState(firstId);
  React.useEffect(() => {
    try {
      const saved = localStorage.getItem("gcore_docs_method");
      if (saved && tabs.find(t => t.props.id === saved)) {
        setActive(saved);
      }
    } catch (_) {}
  }, []);
  React.useEffect(() => {
    try {
      document.querySelectorAll("h2[id], h3[id]").forEach(heading => {
        const visible = heading.offsetParent !== null;
        document.querySelectorAll(`a[href="#${heading.id}"]`).forEach(link => {
          if (link.closest("h1,h2,h3,h4,h5,h6")) return;
          const li = link.closest("li");
          if (li) li.style.display = visible ? "" : "none";
        });
      });
    } catch (_) {}
    window.dispatchEvent(new Event("scroll"));
  }, [active]);
  const handleClick = id => {
    setActive(id);
    try {
      localStorage.setItem("gcore_docs_method", id);
    } catch (_) {}
  };
  return <div>
      <div className="not-prose flex gap-0 border-b border-zinc-200 dark:border-zinc-800 mb-8 mt-2" role="tablist">
        {tabs.map(tab => {
    const isActive = active === tab.props.id;
    return <button key={tab.props.id} role="tab" aria-selected={isActive} onClick={() => handleClick(tab.props.id)} className={["px-4 py-2 text-sm font-medium border-b-2 -mb-px transition-colors cursor-pointer", isActive ? "border-primary text-primary" : "border-transparent text-zinc-500 hover:text-zinc-800 dark:hover:text-zinc-200"].join(" ")}>
              {tab.props.label}
            </button>;
  })}
      </div>

      {tabs.map(tab => <div key={tab.props.id} style={{
    display: active === tab.props.id ? "" : "none"
  }}>
          {tab.props.children}
        </div>)}
    </div>;
};

<MethodSwitch>
  <MethodSection id="portal" label="Customer Portal">
    <p>After [creating](/edge-ai/ai-infrastructure/create-a-virtual-gpu-cluster) a Virtual GPU cluster, use the cluster details page to monitor nodes, manage power state, configure disks and network interfaces, and delete cluster resources.</p>

    ## Cluster details

    <p>To view and manage an existing cluster, open the cluster details page.</p>

    1. In the [Gcore Customer Portal](https://portal.gcore.com), navigate to **GPU Cloud**.
    2. Select the target region.
    3. In the sidebar, expand **GPU Clusters** and select **Virtual GPU Clusters**.
    4. Click a cluster name to open the details page.

    <Frame>
      <img src="https://mintcdn.com/gcore-docs/1EEmhbY3hLFWRm36/images/docs/edge-ai/ai-infrastructure/create-a-virtual-gpu-cluster/cluster-instances-overview.png?fit=max&auto=format&n=1EEmhbY3hLFWRm36&q=85&s=700bae0dda498eadeba759e27077a4f1" alt="Cluster details page with Overview tab showing cluster instances" width="1494" height="560" data-path="images/docs/edge-ai/ai-infrastructure/create-a-virtual-gpu-cluster/cluster-instances-overview.png" />
    </Frame>

    ## Cluster power state

    <p>Virtual GPU clusters support power management operations at the cluster level. Unlike Bare Metal clusters, powering off a Virtual GPU cluster releases compute resources (shelving), which stops billing but also removes data from local disks.</p>

    <Frame>
      <img src="https://mintcdn.com/gcore-docs/1EEmhbY3hLFWRm36/images/docs/edge-ai/ai-infrastructure/create-a-virtual-gpu-cluster/power-management.png?fit=max&auto=format&n=1EEmhbY3hLFWRm36&q=85&s=e66a39a6900e7cd8888a74137549a74c" alt="Power tab with Power on, Power off, Soft reboot, and Hard reboot options" width="1270" height="802" data-path="images/docs/edge-ai/ai-infrastructure/create-a-virtual-gpu-cluster/power-management.png" />
    </Frame>

    ### Power off (shelve) a cluster

    <p>Powering off a Virtual GPU cluster shelves all nodes. Shelving releases CPU, RAM, GPU, and local disk resources. No charges apply while nodes are shelved.</p>

    1. In the cluster list or cluster details page, locate the cluster.
    2. Click the **Power Off** action.
    3. Confirm the operation.

    <Warning>
      When a node is shelved, the local data disk is deleted and all data on it is lost. Only network disks persist. Save important data to network disks or external storage before powering off.
    </Warning>

    ### Power on a cluster

    <p>Powering on a shelved cluster attempts to allocate resources for all nodes.</p>

    1. In the cluster list or cluster details page, locate the powered-off cluster.
    2. Click the **Power On** action.

    ## Node disks

    <p>After cluster creation, disks can be managed individually for each node. This allows adding storage to specific nodes or removing unused disks.</p>

    ### Add a disk to a node

    <p>Add a network volume to a specific node to expand its storage capacity.</p>

    1. Navigate to the cluster details page.
    2. Open the **Volumes** tab.
    3. Select the node to attach a disk to.
    4. Click **Add Volume** and configure the disk type and size.
    5. Click **Create** to attach the new disk.

    <Frame>
      <img src="https://mintcdn.com/gcore-docs/1EEmhbY3hLFWRm36/images/docs/edge-ai/ai-infrastructure/create-a-virtual-gpu-cluster/volumes-tab.png?fit=max&auto=format&n=1EEmhbY3hLFWRm36&q=85&s=9004e94b355c0f9cfed5dceb52eb9cc8" alt="Volumes tab showing instance volumes with Add Volume button" width="1586" height="342" data-path="images/docs/edge-ai/ai-infrastructure/create-a-virtual-gpu-cluster/volumes-tab.png" />
    </Frame>

    ### Remove a disk from a node

    <p>Detach a network volume from a node when it is no longer needed on that node.</p>

    1. Navigate to the cluster details page.
    2. Open the **Volumes** tab.
    3. Locate the disk to remove and click the detach action.
    4. Confirm the operation.

    <Warning>
      Detaching a disk does not delete it. The disk remains in the account and continues to incur storage charges until explicitly deleted.
    </Warning>

    ## Network interfaces

    <p>After cluster creation, network interfaces can be managed individually for each node through the **Networking** tab on the cluster details page.</p>

    ### Add an interface to a node

    <p>Add an interface to connect a node to an additional network.</p>

    1. Navigate to the cluster details page.
    2. Open the **Networking** tab.
    3. Click a node to expand its details.
    4. Click **Add Interface**.
    5. Configure the **Network type** (**Public**, **Private**, or **Dedicated public**) and IP allocation settings.

    <Frame>
      <img src="https://mintcdn.com/gcore-docs/1EEmhbY3hLFWRm36/images/docs/edge-ai/ai-infrastructure/create-a-virtual-gpu-cluster/add-interface-dialog.png?fit=max&auto=format&n=1EEmhbY3hLFWRm36&q=85&s=09109e79ca58189cc67322dd59624b49" alt="Add Interface dialog with network type and configuration options" width="439" height="627" data-path="images/docs/edge-ai/ai-infrastructure/create-a-virtual-gpu-cluster/add-interface-dialog.png" />
    </Frame>

    ### Remove an interface from a node

    <p>Remove an interface from a node when it is no longer needed.</p>

    1. Navigate to the cluster details page.
    2. Open the **Networking** tab.
    3. Click a node to expand its details.
    4. Locate the interface to remove and click the delete action.
    5. Confirm the operation.

    <Info>
      InfiniBand interfaces cannot be removed or modified — they are managed automatically to maintain inter-node communication.
    </Info>

    ## Delete a cluster

    <p>When deleting a Virtual GPU cluster, disks attached to nodes can optionally be preserved.</p>

    <Warning>
      Deleting the last node in a cluster automatically deletes the entire cluster. This applies to both the Customer Portal and API operations. When using the API or Terraform to delete nodes, no confirmation is shown before the cluster is removed. Keep at least one node to preserve the cluster.
    </Warning>

    <Frame>
      <img src="https://mintcdn.com/gcore-docs/1EEmhbY3hLFWRm36/images/docs/edge-ai/ai-infrastructure/create-a-virtual-gpu-cluster/delete-cluster-dialog.png?fit=max&auto=format&n=1EEmhbY3hLFWRm36&q=85&s=8dc332619f70f1923d5fc1d52c3e7d18" alt="Delete Cluster dialog with volume selection and confirmation" width="1081" height="652" data-path="images/docs/edge-ai/ai-infrastructure/create-a-virtual-gpu-cluster/delete-cluster-dialog.png" />
    </Frame>

    1. In the cluster list or cluster details page, click **Delete**.
    2. In the confirmation dialog:
       * To delete all disks along with the cluster, leave the **Delete disks** checkbox selected.
       * To preserve disks for later use, clear the **Delete disks** checkbox.
    3. Confirm the deletion.

    <Info>
      Preserved disks remain in the account and continue to incur storage charges. They can be attached to other instances or clusters.
    </Info>

    ## Cluster automation

    <p>The Customer Portal is suitable for managing individual clusters. Automated workflows — CI/CD pipelines, infrastructure-as-code, or batch provisioning — are better served by the [REST API](/api-reference/cloud/gpu-virtual) or [Terraform](/developer-tools/terraform/overview).</p>
  </MethodSection>

  <MethodSection id="api" label="REST API">
    <p>Use the REST API to inspect virtual GPU clusters, control their power state, manage attached volumes and network interfaces, and automate cluster administration workflows.</p>

    <Info>
      An [API token](/account-settings/api-tokens) is required, along with a
      [project ID](/api-reference/cloud/projects/list-projects)
      and a [region ID](/api-reference/cloud/regions/list-regions).
    </Info>

    <p>Open a terminal and set these environment variables before running the examples:</p>

    ```bash theme={null}
    export GCORE_API_KEY="{YOUR_API_KEY}"
    export GCORE_CLOUD_PROJECT_ID="{YOUR_PROJECT_ID}"
    export GCORE_CLOUD_REGION_ID="{YOUR_REGION_ID}"
    ```

    ## List virtual GPU clusters

    <p>The list endpoint returns all clusters in a project and region. Query string filters — by name, flavor, node count, tags, and timestamps — are documented in the [API reference](/api-reference/cloud/gpu-virtual).</p>

    <Tabs>
      <Tab title="Python SDK">
        ```python theme={null}
        from gcore import Gcore

        client = Gcore()

        page = client.cloud.gpu_virtual.clusters.list()
        for cluster in page.results:
            print(cluster.id, cluster.name, cluster.servers_count, cluster.status)
        ```

        <Info>
          The Python SDK `clusters.list()` does not expose filter parameters. To filter by name, flavor, node count, or tags, use the curl example with query string filters.
        </Info>
      </Tab>

      <Tab title="Go SDK">
        ```go theme={null}
        package main

        import (
            "context"
            "fmt"

            gcore "github.com/G-Core/gcore-go"
            "github.com/G-Core/gcore-go/cloud"
        )

        func main() {
            client := gcore.NewClient()
            ctx := context.Background()

            page, err := client.Cloud.GPUVirtual.Clusters.List(ctx,
                cloud.GPUVirtualClusterListParams{})
            if err != nil {
                panic(err)
            }
            fmt.Printf("Total: %d\n", len(page.Results))
            for _, c := range page.Results {
                fmt.Printf("  %s  %s  nodes=%d\n", c.ID, c.Name, c.ServersCount)
            }
        }
        ```

        <Info>
          The Go SDK `Clusters.List` does not expose filter parameters. To filter by name, flavor, node count, or tags, use the curl example with query string filters.
        </Info>
      </Tab>

      <Tab title="curl">
        ```bash theme={null}
        curl -G "https://api.gcore.com/cloud/v3/gpu/virtual/${GCORE_CLOUD_PROJECT_ID}/${GCORE_CLOUD_REGION_ID}/clusters" \
          -H "Authorization: APIKey ${GCORE_API_KEY}" \
          --data-urlencode "name[prefix]=prod-" \
          --data-urlencode "flavor[prefix]=g3-" \
          --data-urlencode "servers_count[gte]=2" \
          --data-urlencode "tags[env]=production"
        ```

        Response:

        ```json theme={null}
        {
          "count": 1,
          "results": [
            {
              "id": "0dd60286-6258-4594-91e3-f2938c1e3d3a",
              "name": "prod-cluster-1",
              "status": "active",
              "flavor": "g3-ai-24-232-1250-h100-80-1",
              "tags": [
                { "key": "env", "value": "production", "read_only": false },
                { "key": "team", "value": "ml", "read_only": false }
              ],
              "servers_count": 2,
              "created_at": "2026-06-17T18:32:55Z",
              "updated_at": "2026-06-17T18:33:20Z",
              "servers_ids": ["e34a6d40-f42a-4cb1-980b-022f06082df9"],
              "has_pending_changes": false
            }
          ]
        }
        ```

        Use `limit` and `offset` for pagination. The default page size is 10; the maximum is 1000.
      </Tab>
    </Tabs>

    ## Get cluster details

    <p>Returns the full configuration and current status of a single cluster.</p>

    <Tabs>
      <Tab title="Python SDK">
        ```python theme={null}
        from gcore import Gcore

        client = Gcore()

        cluster = client.cloud.gpu_virtual.clusters.get(cluster_id="{CLUSTER_ID}")
        print(cluster.id, cluster.name, cluster.status, cluster.servers_count)
        ```
      </Tab>

      <Tab title="Go SDK">
        ```go theme={null}
        package main

        import (
            "context"
            "fmt"

            gcore "github.com/G-Core/gcore-go"
            "github.com/G-Core/gcore-go/cloud"
        )

        func main() {
            client := gcore.NewClient()
            ctx := context.Background()

            cluster, err := client.Cloud.GPUVirtual.Clusters.Get(ctx,
                "{CLUSTER_ID}",
                cloud.GPUVirtualClusterGetParams{})
            if err != nil {
                panic(err)
            }
            fmt.Printf("%s  %s  nodes=%d\n", cluster.ID, cluster.Name, cluster.ServersCount)
        }
        ```
      </Tab>

      <Tab title="curl">
        ```bash theme={null}
        curl "https://api.gcore.com/cloud/v3/gpu/virtual/${GCORE_CLOUD_PROJECT_ID}/${GCORE_CLOUD_REGION_ID}/clusters/{CLUSTER_ID}" \
          -H "Authorization: APIKey ${GCORE_API_KEY}"
        ```

        Response:

        ```json theme={null}
        {
          "id": "058e03b4-c44b-4684-9075-810cb0354467",
          "name": "prod-cluster-1",
          "status": "active",
          "flavor": "g3-ai-24-232-1250-h100-80-1",
          "tags": [
            { "key": "env", "value": "production", "read_only": false }
          ],
          "servers_count": 2,
          "created_at": "2026-06-17T18:52:19Z",
          "updated_at": "2026-06-17T18:52:44Z",
          "servers_ids": ["0fce6b19-e523-42cf-a74c-571429009735"],
          "servers_settings": {
            "ssh_key_name": "my-key",
            "interfaces": [{ "type": "external", "ip_family": "ipv4", "name": "pub_net" }],
            "volumes": [{ "size": 50, "type": "ssd_hiiops", "boot_index": 0 }]
          },
          "has_pending_changes": false
        }
        ```
      </Tab>
    </Tabs>

    ## Control cluster power state

    <p>The `action` endpoint applies a power operation to all nodes in the cluster at once.</p>

    | Action        | Description                                                                                    |
    | ------------- | ---------------------------------------------------------------------------------------------- |
    | `start`       | Power on a shelved cluster and attempt to reallocate resources                                 |
    | `stop`        | Power off (shelve) all nodes — releases GPU, CPU, RAM, and local disk resources; billing stops |
    | `soft_reboot` | Send an ACPI shutdown signal and reboot                                                        |
    | `hard_reboot` | Force-reset all nodes immediately                                                              |

    <Warning>
      `stop` permanently erases local disk data on all nodes. Save critical data to network volumes before stopping a cluster.
    </Warning>

    <Tabs>
      <Tab title="Python SDK">
        ```python theme={null}
        from gcore import Gcore

        client = Gcore()

        # Replace "stop" with "start", "soft_reboot", or "hard_reboot" as needed
        task_id_list = client.cloud.gpu_virtual.clusters.action(
            cluster_id="{CLUSTER_ID}",
            action="stop",
        )
        print(task_id_list.tasks)
        ```
      </Tab>

      <Tab title="Go SDK">
        ```go theme={null}
        package main

        import (
            "context"
            "fmt"

            gcore "github.com/G-Core/gcore-go"
            "github.com/G-Core/gcore-go/cloud"
        )

        func main() {
            client := gcore.NewClient()
            ctx := context.Background()

            // Swap OfStop for OfStart, OfSoftReboot, or OfHardReboot as needed
            taskIDList, err := client.Cloud.GPUVirtual.Clusters.Action(ctx,
                "{CLUSTER_ID}",
                cloud.GPUVirtualClusterActionParams{
                    OfStop: &cloud.GPUVirtualClusterActionParamsBodyStop{},
                })
            if err != nil {
                panic(err)
            }
            fmt.Printf("%+v\n", taskIDList.Tasks)
        }
        ```
      </Tab>

      <Tab title="curl">
        ```bash theme={null}
        # Power off (stop) — replace "stop" with "start", "soft_reboot", or "hard_reboot"
        curl -X POST \
          "https://api.gcore.com/cloud/v3/gpu/virtual/${GCORE_CLOUD_PROJECT_ID}/${GCORE_CLOUD_REGION_ID}/clusters/{CLUSTER_ID}/action" \
          -H "Authorization: APIKey ${GCORE_API_KEY}" \
          -H "Content-Type: application/json" \
          -d '{"action": "stop"}'
        ```

        Response:

        ```json theme={null}
        { "tasks": ["7a0210ac-fd82-4c06-8e43-4ebdc2d3d1bc"] }
        ```

        Poll `GET /cloud/v1/tasks/{task_id}` every five seconds until `state` is `FINISHED`.
      </Tab>
    </Tabs>

    ## List cluster volumes

    <p>Returns all volumes currently attached to nodes in the cluster.</p>

    <Tabs>
      <Tab title="Python SDK">
        ```python theme={null}
        from gcore import Gcore

        client = Gcore()

        volume_list = client.cloud.gpu_virtual.clusters.volumes.list(cluster_id="{CLUSTER_ID}")
        for vol in volume_list.results:
            print(vol.id, vol.name, vol.size, vol.status)
        ```
      </Tab>

      <Tab title="Go SDK">
        ```go theme={null}
        package main

        import (
            "context"
            "fmt"

            gcore "github.com/G-Core/gcore-go"
            "github.com/G-Core/gcore-go/cloud"
        )

        func main() {
            client := gcore.NewClient()
            ctx := context.Background()

            vols, err := client.Cloud.GPUVirtual.Clusters.Volumes.List(ctx,
                "{CLUSTER_ID}",
                cloud.GPUVirtualClusterVolumeListParams{})
            if err != nil {
                panic(err)
            }
            fmt.Printf("Volumes: %d\n", len(vols.Results))
        }
        ```
      </Tab>

      <Tab title="curl">
        ```bash theme={null}
        curl "https://api.gcore.com/cloud/v3/gpu/virtual/${GCORE_CLOUD_PROJECT_ID}/${GCORE_CLOUD_REGION_ID}/clusters/{CLUSTER_ID}/volumes" \
          -H "Authorization: APIKey ${GCORE_API_KEY}"
        ```

        Response:

        ```json theme={null}
        {
          "count": 1,
          "results": [
            {
              "id": "e937b4c4-da8f-4d7d-b444-d331345a2039",
              "server_id": "0fce6b19-e523-42cf-a74c-571429009735",
              "name": "boot-disk",
              "type": "ssd_hiiops",
              "status": "in-use",
              "size": 50,
              "bootable": true,
              "root_fs": true,
              "created_at": "2026-06-17T18:52:22Z"
            }
          ]
        }
        ```
      </Tab>
    </Tabs>

    ## List cluster network interfaces

    <p>Returns all network interfaces for every node in the cluster, including InfiniBand interfaces used for inter-node communication.</p>

    <Tabs>
      <Tab title="Python SDK">
        ```python theme={null}
        from gcore import Gcore

        client = Gcore()

        iface_list = client.cloud.gpu_virtual.clusters.interfaces.list(cluster_id="{CLUSTER_ID}")
        for iface in iface_list.results:
            print(iface.port_id, iface.network.name, iface.ip_assignments)
        ```
      </Tab>

      <Tab title="Go SDK">
        ```go theme={null}
        package main

        import (
            "context"
            "fmt"

            gcore "github.com/G-Core/gcore-go"
            "github.com/G-Core/gcore-go/cloud"
        )

        func main() {
            client := gcore.NewClient()
            ctx := context.Background()

            ifaces, err := client.Cloud.GPUVirtual.Clusters.Interfaces.List(ctx,
                "{CLUSTER_ID}",
                cloud.GPUVirtualClusterInterfaceListParams{})
            if err != nil {
                panic(err)
            }
            fmt.Printf("Interfaces: %d\n", len(ifaces.Results))
        }
        ```
      </Tab>

      <Tab title="curl">
        ```bash theme={null}
        curl "https://api.gcore.com/cloud/v3/gpu/virtual/${GCORE_CLOUD_PROJECT_ID}/${GCORE_CLOUD_REGION_ID}/clusters/{CLUSTER_ID}/interfaces" \
          -H "Authorization: APIKey ${GCORE_API_KEY}"
        ```

        Response:

        ```json theme={null}
        {
          "count": 2,
          "results": [
            {
              "port_id": "e79e8057-5929-4b79-90d4-d6d894d1fd13",
              "mac_address": "fa:16:3e:01:59:f9",
              "ip_assignments": [{ "subnet_id": "b0ba19bd-...", "ip_address": "85.234.66.234" }],
              "network_id": "831179f2-9828-45a7-af0b-4ca2d0957920",
              "network": { "name": "pub_net", "external": true }
            },
            {
              "port_id": "b1d4862b-486e-456c-bd7f-c4672830d827",
              "ip_assignments": [{ "subnet_id": "8fd1891e-...", "ip_address": "192.168.241.99" }],
              "network": { "name": "gpu-cluster-ib-network-058e03b4-...", "external": false }
            }
          ]
        }
        ```
      </Tab>
    </Tabs>

    <Info>
      The `gpu-cluster-ib-network-*` interface is the InfiniBand network created automatically for inter-node communication. It cannot be removed or modified.
    </Info>

    ## Delete a cluster

    <p>Deletes the cluster and all associated servers. Pass `all_floating_ips=true` to release any floating IPs, `all_reserved_fixed_ips=true` to release reserved fixed IPs, and `all_volumes=true` to delete all attached volumes along with the cluster.</p>

    <Warning>
      Deleting the last node in a cluster automatically deletes the entire cluster — no confirmation is shown when using the API.
    </Warning>

    <Tabs>
      <Tab title="Python SDK">
        ```python theme={null}
        from gcore import Gcore

        client = Gcore()

        task_id_list = client.cloud.gpu_virtual.clusters.delete(
            cluster_id="{CLUSTER_ID}",
            all_floating_ips=True,
            all_reserved_fixed_ips=True,
            all_volumes=True,
        )
        print(task_id_list.tasks)
        ```
      </Tab>

      <Tab title="Go SDK">
        ```go theme={null}
        package main

        import (
            "context"
            "fmt"

            gcore "github.com/G-Core/gcore-go"
            "github.com/G-Core/gcore-go/cloud"
        )

        func main() {
            client := gcore.NewClient()
            ctx := context.Background()

            taskIDList, err := client.Cloud.GPUVirtual.Clusters.Delete(ctx,
                "{CLUSTER_ID}",
                cloud.GPUVirtualClusterDeleteParams{
                    AllFloatingIPs:      gcore.Bool(true),
                    AllReservedFixedIPs: gcore.Bool(true),
                    AllVolumes:          gcore.Bool(true),
                })
            if err != nil {
                panic(err)
            }
            fmt.Printf("%+v\n", taskIDList.Tasks)
        }
        ```
      </Tab>

      <Tab title="curl">
        ```bash theme={null}
        curl -X DELETE \
          "https://api.gcore.com/cloud/v3/gpu/virtual/${GCORE_CLOUD_PROJECT_ID}/${GCORE_CLOUD_REGION_ID}/clusters/{CLUSTER_ID}?all_floating_ips=true&all_reserved_fixed_ips=true&all_volumes=true" \
          -H "Authorization: APIKey ${GCORE_API_KEY}"
        ```

        Response:

        ```json theme={null}
        { "tasks": ["task-uuid"] }
        ```

        Poll `GET /cloud/v1/tasks/{task_id}` every five seconds until `state` is `FINISHED`.
      </Tab>
    </Tabs>
  </MethodSection>

  <MethodSection id="terraform" label="Terraform">
    <p>Manage the lifecycle of a Virtual GPU cluster using the [`gcore_cloud_gpu_virtual_cluster`](https://registry.terraform.io/providers/G-Core/gcore/latest/docs/resources/cloud_gpu_virtual_cluster) resource from the [Terraform provider](/developer-tools/terraform/overview) v2. Power-state control and per-node disk or interface changes require the Customer Portal or REST API — Terraform manages the cluster as a whole, not individual nodes.</p>

    ## Rename a cluster

    <p>Edit the `name` field in the resource block and run `terraform apply`. The change applies in-place without replacing the cluster or its nodes.</p>

    <Warning>
      If the cluster was created without an explicit `security_groups` value, add the default security group ID to the interface block before running `terraform apply`. Retrieve the ID from the portal under **Network** > **Security Groups**, or via the API. Omitting it causes a provider consistency error on update.
    </Warning>

    ```hcl theme={null}
    resource "gcore_cloud_gpu_virtual_cluster" "example" {
      name          = "my-gpu-cluster-renamed"  # updated name
      flavor        = "g3-ai-24-232-1250-h100-80-1"
      servers_count = 1
      project_id    = var.project_id
      region_id     = var.region_id

      servers_settings = {
        interfaces = [{
          type            = "external"
          security_groups = [{ id = "<default-security-group-id>" }]  # required when updating
        }]
        volumes = [{
          boot_index = 0
          name       = "boot-disk"
          size       = 50
          source     = "image"
          type       = "ssd_hiiops"
          image_id   = "2a818d08-a9d3-4477-9966-2663d46f6a27"  # check the images API for current IDs in the target region
        }]
        credentials = {
          ssh_key_name = "my-ssh-key"
        }
      }
    }
    ```

    ## Scale a cluster

    <p>Edit `servers_count` and run `terraform apply`. Terraform calls the cluster action endpoint to adjust node count without recreating the cluster. Scaling up requires sufficient quota for the additional nodes — each node consumes volume storage equal to the boot disk size.</p>

    <Warning>
      If the cluster was created without an explicit `security_groups` value, add the default security group ID to the interface block before running `terraform apply`. Omitting it causes a provider consistency error on update.
    </Warning>

    ```hcl theme={null}
    resource "gcore_cloud_gpu_virtual_cluster" "example" {
      name          = "my-gpu-cluster"
      flavor        = "g3-ai-24-232-1250-h100-80-1"
      servers_count = 3                               # increase or decrease to target node count
      project_id    = var.project_id
      region_id     = var.region_id

      servers_settings = {
        interfaces = [{
          type            = "external"
          security_groups = [{ id = "<default-security-group-id>" }]  # required when updating
        }]
        volumes = [{
          boot_index = 0
          name       = "boot-disk"
          size       = 50
          source     = "image"
          type       = "ssd_hiiops"
          image_id   = "2a818d08-a9d3-4477-9966-2663d46f6a27"
        }]
        credentials = {
          ssh_key_name = "my-ssh-key"
        }
      }
    }
    ```

    ## Import an existing cluster

    <p>Use when a cluster was created outside Terraform and needs to be managed as code. After import, run `terraform plan` to verify that the configuration matches the live resource and resolve any drift.</p>

    ```hcl theme={null}
    # terraform import gcore_cloud_gpu_virtual_cluster.example '<project_id>/<region_id>/<cluster_id>'
    ```

    ## Delete a cluster

    <p>Remove the resource block — Terraform detects the missing declaration and deletes the cluster on the next `terraform apply`.</p>

    ```hcl theme={null}
    # Remove or comment out this block:
    # resource "gcore_cloud_gpu_virtual_cluster" "example" {
    #   name          = "my-gpu-cluster"
    #   flavor        = "g3-ai-24-232-1250-h100-80-1"
    #   servers_count = 1
    #   project_id    = var.project_id
    #   region_id     = var.region_id
    #   ...
    # }
    ```

    ```bash theme={null}
    terraform apply
    ```
  </MethodSection>
</MethodSwitch>
