Restore from a snapshot

A disk is either a boot disk that is used to start and run a VM's (virtual machine) operating system, or a non-boot disk that a VM uses only for data storage.

You can use snapshots to backup and restore disk data in the following ways:

Creating a new disk from a snapshot

If you backed up a boot or non-boot disk with a snapshot, you can create a new disk based on the snapshot.

Restrictions

  • The new disk must be at least the same size as the original source disk for the snapshot. If you create a disk that is larger than the original source disk for the snapshot, you must resize the file system on that persistent disk to include the additional disk space. Depending on your operating system and file system type, you might need to use a different file system resizing tool. For more information, see your operating system documentation.

  • You can create a new zonal disk from a given snapshot at most once every ten minutes. If you want to issue a burst of requests to snapshot your disks, you can issue at most 6 requests in 60 minutes. This limit does not apply when creating regional disks from a snapshot. For more information, see Snapshot frequency limits.

Console

  1. In the Google Cloud console, go to the Snapshots page.

    Go to Snapshots

  2. Find the name of the snapshot that you want to restore.

  3. Go to the Disks page.

    Go to the Disks page

  4. Click Create new disk.

  5. Specify the following configuration parameters:

    • A name for the disk.
    • A type for the disk.
    • Optionally, you can override the default region and zone selection. You can select any region and zone, regardless of the storage location of the source snapshot.
  6. Under Source type, click Snapshot.

  7. Select the name of the snapshot to restore.

  8. Select the size of the new disk, in gigabytes. This number must be equal to or larger than the original source disk for the snapshot.

  9. Click Create to create the disk.

gcloud

  1. Use the gcloud compute snapshots list command command to find the name of the snapshot you want to restore:

    gcloud compute snapshots list
    
  2. Use the gcloud compute snapshots describe command command to find the size of the snapshot you want to restore:

    gcloud compute snapshots describe SNAPSHOT_NAME
    

    Replace SNAPSHOT_NAME with the name of the snapshot being restored.

  3. Use the gcloud compute disks create command command to create a new regional or zonal disk from your snapshot. If you need an SSD persistent disk for additional throughput or IOPS, include the --type flag and specify pd-ssd.

    gcloud compute disks create DISK_NAME \
        --size=DISK_SIZE \
        --source-snapshot=SNAPSHOT_NAME \
        --type=DISK_TYPE
    

    Replace the following:

    • DISK_NAME: the name of the new disk.
    • DISK_SIZE: The size of the new disk, in gigabytes. This number must be equal to or larger than the original source disk for the snapshot.
    • SNAPSHOT_NAME: the name of the snapshot being restored.
    • DISK_TYPE: full or partial URL for the type of the disk. For example, https://www.googleapis.com/compute/v1/projects/PROJECT_ID /zones/ZONE/diskTypes/pd-ssd.

API

  1. Construct a GET request to snapshots.list to display the list of snapshots in your project.

    GET https://compute.googleapis.com/compute/v1/projects/PROJECT_ID/global/snapshots
    

    Replace PROJECT_ID with your project ID.

  2. Construct a POST request to create a zonal disk using the disks.insert method. Include the name, sizeGb, and type properties. To restore a disk using a snapshot, you must include the sourceSnapshot property.

    POST https://compute.googleapis.com/compute/v1/projects/PROJECT_ID/zones/ZONE/disks
    
    {
     "name": "DISK_NAME",
     "sizeGb": "DISK_SIZE",
     "type": "zones/ZONE/diskTypes/DISK_TYPE"
     "sourceSnapshot": "SNAPSHOT_NAME"
    }
    

    Replace the following:

    • PROJECT_ID: your project ID.
    • ZONE the zone where your instance and new disk are located.
    • DISK_NAME: the name of the new disk.
    • DISK_SIZE: the size of the new disk, in gigabytes. This number must be equal to or larger than the original source disk for the snapshot.
    • DISK_TYPE: full or partial URL for the type of the disk. For example https://www.googleapis.com/compute/v1/projects/PROJECT_ID/zones/ ZONE/diskTypes/pd-ssd.
    • SNAPSHOT_NAME: the source snapshot for the disk you are restoring.

Optionally, you can then attach the new disk to an existing instance.

Console

  1. Go to the VM instances page.

    Go to the VM instances page

  2. Click the name of the instance where you want to restore your non-boot disk.
  3. At the top of the instance details page, click Edit.
  4. Under Additional disks, click Attach existing disk.
  5. Select the name of the new disk made from your snapshot.
  6. Click Done to attach the disk.
  7. At the bottom of the instance details page, click Save to apply your changes to the instance.

gcloud

  1. Use the gcloud compute instances attach-disk command to attach your disk to an instance:

    gcloud compute instances attach-disk INSTANCE_NAME \
        --disk DISK_NAME
    

    where:

    • INSTANCE_NAME is the name of the instance.
    • DISK_NAME is the name of the disk made from your snapshot.

API

  1. Construct a POST request to the instances.attachDisk method, and include the URL to the zonal disk that you just created from your snapshot.

    POST https://compute.googleapis.com/compute/v1/projects/PROJECT_ID/zones/ZONE/instances/INSTANCE_NAME/attachDisk
    
    {
     "source": "/compute/v1/projects/PROJECT_ID/zones/ZONE/disks/DISK_NAME"
    }
    

    where:

    • PROJECT_ID is your project ID.
    • ZONE is the zone where your instance and new disk are located.
    • INSTANCE_NAME is the name of the instance where you are adding the new disk.
    • DISK_NAME is the name of the new disk.

After you create and attach a new disk to an instance, you must mount the disk so that the operating system can use the available storage space.

Create a new VM from a boot disk snapshot

If you backed up a VM's boot disk with a snapshot, you can use that snapshot to create a new VM.

Console

  1. In the Google Cloud console, go to the VM instances page.

    Go to VM instances

  2. Select your project and click Continue.

  3. Click Create instance.

  4. Specify a Name for your VM. For more information, see Resource naming convention.

  5. Optional: Change the Zone for this VM. Compute Engine randomizes the list of zones within each region to encourage use across multiple zones.

  6. Select a Machine configuration for your VM.

  7. In the Boot disk section, click Change, and then do the following:

    1. Click the Snapshots tab.
    2. In the Snapshot list, click a snapshot.
    3. Specify the boot disk type and size.
    4. Optional: For advanced configuration options, click Show advanced configurations.
    5. To confirm your boot disk options, click Select.
  8. In the Firewall section, to permit HTTP or HTTPS traffic to the VM, select Allow HTTP traffic or Allow HTTPS traffic.

    The Cloud console adds a network tag to your VM and creates the corresponding ingress firewall rule that allows all incoming traffic on tcp:80 (HTTP) or tcp:443 (HTTPS). The network tag associates the firewall rule with the VM. For more information, see Firewall rules overview in the Virtual Private Cloud documentation.

  9. To create and start the VM, click Create.

gcloud

Use the gcloud compute instances create command and include the --source-snapshot flag:

gcloud compute instances create VM_NAME \
    --source-snapshot=BOOT_SNAPSHOT_NAME \
    --boot-disk-size=BOOT_DISK_SIZE \
    --boot-disk-type=BOOT_DISK_TYPE \
    --boot-disk-device-name=BOOT_DISK_NAME

Replace the following:

  • VM_NAME: name for the new VM
  • BOOT_SNAPSHOT_NAME: name of the boot disk snapshot that you want to restore to the boot disk of the new VM.
  • BOOT_DISK_SIZE: Optional: size, in gigabytes, of the new boot disk

    The size must be equal to or larger than the size of the source disk from which the snapshot was made.

  • BOOT_DISK_TYPE: Optional: type of the boot persistent disk

    For example, pd-ssd.

  • BOOT_DISK_NAME: name of the new boot disk for this VM

API

When you use the API to create a VM from a snapshot, the following restrictions apply:

  • Only one persistent disk can be used as the boot persistent disk.
  • You must attach the boot persistent disk as the first disk for that VM.
  • If you specify the source property, you cannot also specify the initializeParams property. Providing a source indicates that the boot persistent disk exists already, but the initializeParams property indicates that Compute Engine should create a new boot persistent disk.

    To create a VM from a boot disk snapshot, specify the sourceSnapshot field under the disks property. Optional: specify the diskSizeGb and diskType properties for the new boot disk:

POST https://compute.googleapis.com/compute/v1/projects/PROJECT_ID/zones/ZONE/instances
{
  "name": "VM_NAME",
  "machineType": "machineTypes/MACHINE_TYPE"
  "networkInterfaces": [{
    "accessConfigs": [{
      "type": "ONE_TO_ONE_NAT",
      "name": "External NAT"
    }],
    "network": "global/networks/default"
  }],
  "disks": [{
     "boot": true,
     "initializeParams": {
       "sourceSnapshot": "global/snapshots/BOOT_SNAPSHOT_NAME",
       "diskSizeGb": "BOOT_DISK_SIZE",
       "diskType": "BOOT_DISK_TYPE"
    }
   }],
 }

Replace the following:

  • PROJECT_ID: your project ID
  • ZONE: zone where you want to create the new VM
  • VM_NAME: name of the VM that you want to restore a snapshot to
  • MACHINE_TYPE: machine type of the VM
  • BOOT_SNAPSHOT_NAME: name of the snapshot that you want to use to create the boot disk of a new VM
  • BOOT_DISK_SIZE: Optional: size, in gigabytes, for the new boot disk

    The size must be equal to or larger than the size of the source disk from which the snapshot was made.

  • BOOT_DISK_TYPE: Optional: type of the boot disk

    For example, pd-ssd.

Go

import (
	"context"
	"fmt"
	"io"

	compute "cloud.google.com/go/compute/apiv1"
	computepb "google.golang.org/genproto/googleapis/cloud/compute/v1"
	"google.golang.org/protobuf/proto"
)

// createInstanceFromSnapshot creates a new VM instance with boot disk created from a snapshot.
func createInstanceFromSnapshot(w io.Writer, projectID, zone, instanceName, snapshotLink string) error {
	// projectID := "your_project_id"
	// zone := "europe-central2-b"
	// instanceName := "your_instance_name"
	// snapshotLink := "projects/project_name/global/snapshots/snapshot_name"

	ctx := context.Background()
	instancesClient, err := compute.NewInstancesRESTClient(ctx)
	if err != nil {
		return fmt.Errorf("NewInstancesRESTClient: %v", err)
	}
	defer instancesClient.Close()

	req := &computepb.InsertInstanceRequest{
		Project: projectID,
		Zone:    zone,
		InstanceResource: &computepb.Instance{
			Name: proto.String(instanceName),
			Disks: []*computepb.AttachedDisk{
				{
					InitializeParams: &computepb.AttachedDiskInitializeParams{
						DiskSizeGb:     proto.Int64(11),
						SourceSnapshot: proto.String(snapshotLink),
						DiskType:       proto.String(fmt.Sprintf("zones/%s/diskTypes/pd-standard", zone)),
					},
					AutoDelete: proto.Bool(true),
					Boot:       proto.Bool(true),
					Type:       proto.String(computepb.AttachedDisk_PERSISTENT.String()),
				},
			},
			MachineType: proto.String(fmt.Sprintf("zones/%s/machineTypes/n1-standard-1", zone)),
			NetworkInterfaces: []*computepb.NetworkInterface{
				{
					Name: proto.String("global/networks/default"),
				},
			},
		},
	}

	op, err := instancesClient.Insert(ctx, req)
	if err != nil {
		return fmt.Errorf("unable to create instance: %v", err)
	}

	if err = op.Wait(ctx); err != nil {
		return fmt.Errorf("unable to wait for the operation: %v", err)
	}

	fmt.Fprintf(w, "Instance created\n")

	return nil
}

Java


import com.google.api.gax.longrunning.OperationFuture;
import com.google.cloud.compute.v1.AttachedDisk;
import com.google.cloud.compute.v1.AttachedDisk.Type;
import com.google.cloud.compute.v1.AttachedDiskInitializeParams;
import com.google.cloud.compute.v1.Image;
import com.google.cloud.compute.v1.ImagesClient;
import com.google.cloud.compute.v1.InsertInstanceRequest;
import com.google.cloud.compute.v1.Instance;
import com.google.cloud.compute.v1.InstancesClient;
import com.google.cloud.compute.v1.NetworkInterface;
import com.google.cloud.compute.v1.Operation;
import java.io.IOException;
import java.util.Vector;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public class CreateInstancesAdvanced {

  /**
   * @param diskType the type of disk you want to create. This value uses the following format:
   * "zones/{zone}/diskTypes/(pd-standard|pd-ssd|pd-balanced|pd-extreme)". For example:
   * "zones/us-west3-b/diskTypes/pd-ssd"
   * @param diskSizeGb size of the new disk in gigabytes
   * @param boot boolean flag indicating whether this disk should be used as a boot disk of an
   * instance
   * @param diskSnapshot disk snapshot to use when creating this disk. You must have read access to
   * this disk. This value uses the following format:
   * "projects/{project_name}/global/snapshots/{snapshot_name}"
   * @return AttachedDisk object configured to be created using the specified snapshot.
   */
  private static AttachedDisk diskFromSnapshot(String diskType, int diskSizeGb, boolean boot,
      String diskSnapshot) {
    AttachedDisk disk =
        AttachedDisk.newBuilder()
            .setBoot(boot)
            // Remember to set auto_delete to True if you want the disk to be deleted when
            // you delete your VM instance.
            .setAutoDelete(true)
            .setType(Type.PERSISTENT.toString())
            .setInitializeParams(
                AttachedDiskInitializeParams.newBuilder()
                    .setSourceSnapshot(diskSnapshot)
                    .setDiskSizeGb(diskSizeGb)
                    .setDiskType(diskType)
                    .build())
            .build();
    return disk;
  }


  /**
   * Send an instance creation request to the Compute Engine API and wait for it to complete.
   *
   * @param project project ID or project number of the Cloud project you want to use.
   * @param zone name of the zone to create the instance in. For example: "us-west3-b"
   * @param instanceName name of the new virtual machine (VM) instance.
   * @param disks a list of compute_v1.AttachedDisk objects describing the disks you want to attach
   * to your new instance.
   * @param machineType machine type of the VM being created. This value uses the following format:
   * "zones/{zone}/machineTypes/{type_name}".
   * For example: "zones/europe-west3-c/machineTypes/f1-micro"
   * @param network name of the network you want the new instance to use. For example:
   * "global/networks/default" represents the network named "default", which is created
   * automatically for each project.
   * @param subnetwork name of the subnetwork you want the new instance to use. This value uses the
   * following format: "regions/{region}/subnetworks/{subnetwork_name}"
   * @return Instance object.
   */
  private static Instance createWithDisks(String project, String zone, String instanceName,
      Vector<AttachedDisk> disks, String machineType, String network, String subnetwork)
      throws IOException, InterruptedException, ExecutionException, TimeoutException {
    try (InstancesClient instancesClient = InstancesClient.create()) {
      // Use the network interface provided in the networkName argument.
      NetworkInterface networkInterface;
      if (subnetwork != null) {
        networkInterface = NetworkInterface.newBuilder()
            .setName(network).setSubnetwork(subnetwork)
            .build();
      } else {
        networkInterface = NetworkInterface.newBuilder()
            .setName(network).build();
      }

      machineType = String.format("zones/%s/machineTypes/%s", zone, machineType);

      // Bind `instanceName`, `machineType`, `disk`, and `networkInterface` to an instance.
      Instance instanceResource =
          Instance.newBuilder()
              .setName(instanceName)
              .setMachineType(machineType)
              .addAllDisks(disks)
              .addNetworkInterfaces(networkInterface)
              .build();

      System.out.printf("Creating instance: %s at %s ", instanceName, zone);

      // Insert the instance in the specified project and zone.
      InsertInstanceRequest insertInstanceRequest = InsertInstanceRequest.newBuilder()
          .setProject(project)
          .setZone(zone)
          .setInstanceResource(instanceResource).build();

      OperationFuture<Operation, Operation> operation = instancesClient.insertAsync(
          insertInstanceRequest);

      // Wait for the operation to complete.
      Operation response = operation.get(3, TimeUnit.MINUTES);

      if (response.hasError()) {
        System.out.println("Instance creation failed ! ! " + response);
        return null;
      }
      System.out.println("Operation Status: " + response.getStatus());

      return instancesClient.get(project, zone, instanceName);
    }
  }

  /**
   * Create a new VM instance with boot disk created from a snapshot.
   *
   * @param project project ID or project number of the Cloud project you want to use.
   * @param zone name of the zone to create the instance in. For example: "us-west3-b"
   * @param instanceName name of the new virtual machine (VM) instance.
   * @param snapshotName link to the snapshot you want to use as the source of your boot disk in the
   * form of: "projects/{project_name}/global/snapshots/{snapshot_name}"
   * @return Instance object.
   */
  public static Instance createFromSnapshot(String project, String zone, String instanceName,
      String snapshotName)
      throws IOException, InterruptedException, ExecutionException, TimeoutException {
    String diskType = String.format("zones/%s/diskTypes/pd-standard", zone);
    Vector<AttachedDisk> disks = new Vector<>();
    disks.add(diskFromSnapshot(diskType, 11, true, snapshotName));
    return createWithDisks(project, zone, instanceName, disks, "n1-standard-1",
        "global/networks/default", null);
  }

Node.js

/**
 * TODO(developer): Uncomment and replace these variables before running the sample.
 */
// const projectId = 'YOUR_PROJECT_ID';
// const zone = 'europe-central2-b';
// const instanceName = 'YOUR_INSTANCE_NAME';
// const snapshotLink = 'projects/YOUR_PROJECT/global/snapshots/YOUR_SNAPSHOT_NAME';

const compute = require('@google-cloud/compute');

// Creates a new VM instance with boot disk created from a snapshot.
async function createInstanceFromSnapshot() {
  const instancesClient = new compute.InstancesClient();

  const [response] = await instancesClient.insert({
    project: projectId,
    zone,
    instanceResource: {
      name: instanceName,
      disks: [
        {
          initializeParams: {
            diskSizeGb: '11',
            sourceSnapshot: snapshotLink,
            diskType: `zones/${zone}/diskTypes/pd-standard`,
          },
          autoDelete: true,
          boot: true,
          type: 'PERSISTENT',
        },
      ],
      machineType: `zones/${zone}/machineTypes/n1-standard-1`,
      networkInterfaces: [
        {
          name: 'global/networks/default',
        },
      ],
    },
  });
  let operation = response.latestResponse;
  const operationsClient = new compute.ZoneOperationsClient();

  // Wait for the create operation to complete.
  while (operation.status !== 'DONE') {
    [operation] = await operationsClient.wait({
      operation: operation.name,
      project: projectId,
      zone: operation.zone.split('/').pop(),
    });
  }

  console.log('Instance created.');
}

createInstanceFromSnapshot();

Python

import re
import sys
from typing import Any, List

from google.api_core.extended_operation import ExtendedOperation
from google.cloud import compute_v1


def disk_from_snapshot(
    disk_type: str,
    disk_size_gb: int,
    boot: bool,
    source_snapshot: str,
    auto_delete: bool = True,
) -> compute_v1.AttachedDisk():
    """
    Create an AttachedDisk object to be used in VM instance creation. Uses a disk snapshot as the
    source for the new disk.

    Args:
         disk_type: the type of disk you want to create. This value uses the following format:
            "zones/{zone}/diskTypes/(pd-standard|pd-ssd|pd-balanced|pd-extreme)".
            For example: "zones/us-west3-b/diskTypes/pd-ssd"
        disk_size_gb: size of the new disk in gigabytes
        boot: boolean flag indicating whether this disk should be used as a boot disk of an instance
        source_snapshot: disk snapshot to use when creating this disk. You must have read access to this disk.
            This value uses the following format: "projects/{project_name}/global/snapshots/{snapshot_name}"
        auto_delete: boolean flag indicating whether this disk should be deleted with the VM that uses it

    Returns:
        AttachedDisk object configured to be created using the specified snapshot.
    """
    disk = compute_v1.AttachedDisk()
    initialize_params = compute_v1.AttachedDiskInitializeParams()
    initialize_params.source_snapshot = source_snapshot
    initialize_params.disk_type = disk_type
    initialize_params.disk_size_gb = disk_size_gb
    disk.initialize_params = initialize_params
    # Remember to set auto_delete to True if you want the disk to be deleted when you delete
    # your VM instance.
    disk.auto_delete = auto_delete
    disk.boot = boot
    return disk


def wait_for_extended_operation(
    operation: ExtendedOperation, verbose_name: str = "operation", timeout: int = 300
) -> Any:
    """
    This method will wait for the extended (long-running) operation to
    complete. If the operation is successful, it will return its result.
    If the operation ends with an error, an exception will be raised.
    If there were any warnings during the execution of the operation
    they will be printed to sys.stderr.

    Args:
        operation: a long-running operation you want to wait on.
        verbose_name: (optional) a more verbose name of the operation,
            used only during error and warning reporting.
        timeout: how long (in seconds) to wait for operation to finish.
            If None, wait indefinitely.

    Returns:
        Whatever the operation.result() returns.

    Raises:
        This method will raise the exception received from `operation.exception()`
        or RuntimeError if there is no exception set, but there is an `error_code`
        set for the `operation`.

        In case of an operation taking longer than `timeout` seconds to complete,
        a `concurrent.futures.TimeoutError` will be raised.
    """
    result = operation.result(timeout=timeout)

    if operation.error_code:
        print(
            f"Error during {verbose_name}: [Code: {operation.error_code}]: {operation.error_message}",
            file=sys.stderr,
            flush=True,
        )
        print(f"Operation ID: {operation.name}", file=sys.stderr, flush=True)
        raise operation.exception() or RuntimeError(operation.error_message)

    if operation.warnings:
        print(f"Warnings during {verbose_name}:\n", file=sys.stderr, flush=True)
        for warning in operation.warnings:
            print(f" - {warning.code}: {warning.message}", file=sys.stderr, flush=True)

    return result


def create_instance(
    project_id: str,
    zone: str,
    instance_name: str,
    disks: List[compute_v1.AttachedDisk],
    machine_type: str = "n1-standard-1",
    network_link: str = "global/networks/default",
    subnetwork_link: str = None,
    internal_ip: str = None,
    external_access: bool = False,
    external_ipv4: str = None,
    accelerators: List[compute_v1.AcceleratorConfig] = None,
    preemptible: bool = False,
    custom_hostname: str = None,
    delete_protection: bool = False,
) -> compute_v1.Instance:
    """
    Send an instance creation request to the Compute Engine API and wait for it to complete.

    Args:
        project_id: project ID or project number of the Cloud project you want to use.
        zone: name of the zone to create the instance in. For example: "us-west3-b"
        instance_name: name of the new virtual machine (VM) instance.
        disks: a list of compute_v1.AttachedDisk objects describing the disks
            you want to attach to your new instance.
        machine_type: machine type of the VM being created. This value uses the
            following format: "zones/{zone}/machineTypes/{type_name}".
            For example: "zones/europe-west3-c/machineTypes/f1-micro"
        network_link: name of the network you want the new instance to use.
            For example: "global/networks/default" represents the network
            named "default", which is created automatically for each project.
        subnetwork_link: name of the subnetwork you want the new instance to use.
            This value uses the following format:
            "regions/{region}/subnetworks/{subnetwork_name}"
        internal_ip: internal IP address you want to assign to the new instance.
            By default, a free address from the pool of available internal IP addresses of
            used subnet will be used.
        external_access: boolean flag indicating if the instance should have an external IPv4
            address assigned.
        external_ipv4: external IPv4 address to be assigned to this instance. If you specify
            an external IP address, it must live in the same region as the zone of the instance.
            This setting requires `external_access` to be set to True to work.
        accelerators: a list of AcceleratorConfig objects describing the accelerators that will
            be attached to the new instance.
        preemptible: boolean value indicating if the new instance should be preemptible
            or not.
        custom_hostname: Custom hostname of the new VM instance.
            Custom hostnames must conform to RFC 1035 requirements for valid hostnames.
        delete_protection: boolean value indicating if the new virtual machine should be
            protected against deletion or not.
    Returns:
        Instance object.
    """
    instance_client = compute_v1.InstancesClient()

    # Use the network interface provided in the network_link argument.
    network_interface = compute_v1.NetworkInterface()
    network_interface.name = network_link
    if subnetwork_link:
        network_interface.subnetwork = subnetwork_link

    if internal_ip:
        network_interface.network_i_p = internal_ip

    if external_access:
        access = compute_v1.AccessConfig()
        access.type_ = compute_v1.AccessConfig.Type.ONE_TO_ONE_NAT.name
        access.name = "External NAT"
        access.network_tier = access.NetworkTier.PREMIUM.name
        if external_ipv4:
            access.nat_i_p = external_ipv4
        network_interface.access_configs = [access]

    # Collect information into the Instance object.
    instance = compute_v1.Instance()
    instance.name = instance_name
    instance.disks = disks
    if re.match(r"^zones/[a-z\d\-]+/machineTypes/[a-z\d\-]+$", machine_type):
        instance.machine_type = machine_type
    else:
        instance.machine_type = f"zones/{zone}/machineTypes/{machine_type}"

    if accelerators:
        instance.guest_accelerators = accelerators

    instance.network_interfaces = [network_interface]

    if preemptible:
        # Set the preemptible setting
        instance.scheduling = compute_v1.Scheduling()
        instance.scheduling.preemptible = True

    if custom_hostname is not None:
        # Set the custom hostname for the instance
        instance.hostname = custom_hostname

    if delete_protection:
        # Set the delete protection bit
        instance.deletion_protection = True

    # Prepare the request to insert an instance.
    request = compute_v1.InsertInstanceRequest()
    request.zone = zone
    request.project = project_id
    request.instance_resource = instance

    # Wait for the create operation to complete.
    print(f"Creating the {instance_name} instance in {zone}...")

    operation = instance_client.insert(request=request)

    wait_for_extended_operation(operation, "instance creation")

    print(f"Instance {instance_name} created.")
    return instance_client.get(project=project_id, zone=zone, instance=instance_name)


def create_from_snapshot(
    project_id: str, zone: str, instance_name: str, snapshot_link: str
):
    """
    Create a new VM instance with boot disk created from a snapshot. The
    new boot disk will have 20 gigabytes.

    Args:
        project_id: project ID or project number of the Cloud project you want to use.
        zone: name of the zone to create the instance in. For example: "us-west3-b"
        instance_name: name of the new virtual machine (VM) instance.
        snapshot_link: link to the snapshot you want to use as the source of your
            boot disk in the form of: "projects/{project_name}/global/snapshots/{snapshot_name}"

    Returns:
        Instance object.
    """
    disk_type = f"zones/{zone}/diskTypes/pd-standard"
    disks = [disk_from_snapshot(disk_type, 20, True, snapshot_link)]
    instance = create_instance(project_id, zone, instance_name, disks)
    return instance

Creating a new VM from a non-boot disk snapshot

If you backed up a non-boot disk with a snapshot, you can create a VM with a new non-boot disk based on the snapshot.

Console

When restoring non-boot snapshots to a new VM from the console, first create a disk from each snapshot. Then, attach the new disks when you create the VM.

  1. Restore each non-boot snapshot to a new disk.

    1. In the Google Cloud console, go to the Disks page.

      Go to Disks

    2. Click Create disk.

    3. Specify a Name for your disk. For more information, see Resource naming convention.

    4. Select the Region and Zone for this disk. The disk and VM must be in the same zone.

    5. Select a disk Type.

    6. Under Source type, select Snapshot.

    7. Under the new Source snapshot field, select a non-boot snapshot that you want to restore to the new disk.

    8. To create the disk, click Create.

    Repeat these steps to create a disk from each snapshot that you want to restore. When creating a VM, you can add up to 15 non-boot disks.

  2. In the Google Cloud console, go to the VM instances page.

    Go to VM instances

  3. Select your project and click Continue.

  4. Click Create instance.

    1. Specify a Name for your VM. For more information, see Resource naming convention.
    2. Select the Region and Zone for this VM. The disk and VM must be in the same zone.
    3. Select a Machine type for your VM.
    4. If you want to allow incoming external traffic, change the Firewall rules for the VM.
    5. To attach disks to the VM, expand the Networking, disks, security, management, sole tenancy section, and then do the following:

      1. Expand the Disks section.
      2. Click Attach existing disk.
        1. In the Disk list, select a disk to attach to this VM.
        2. In the Attachment Setting section, select disk's attachment Mode and the Deletion rule. For more information about adding new disks, see Add a persistent disk to your VM.
      3. Click Save.

      Repeat these steps for each disk that you want to attach. When creating a VM, you can add up to 15 non-boot disks.

  5. To create and start the VM, click Create.

gcloud

Create a VM by using the gcloud compute instances create command. For each non-boot snapshot that you want to restore, include the --create-disk flag, and specify a source-snapshot. When creating a VM, you can add up to 15 non-boot disks.

For example, to restore two non-boot snapshots to a new VM, use the following command:

gcloud compute instances create VM_NAME \
    --create-disk source-snapshot=SNAPSHOT_1_NAME,name=DISK_1_NAME,size=DISK_1_SIZE,type=DISK_1_TYPE \
    --create-disk source-snapshot=SNAPSHOT_2_NAME,name=DISK_2_NAME,size=DISK_2_SIZE,type=DISK_2_TYPE

Replace the following:

  • VM_NAME: name for the new VM
  • SNAPSHOT_1_NAME and SNAPSHOT_2_NAME: names of non-boot snapshots that you want to restore
  • DISK_1_NAME and DISK_2_NAME: names of the new non-boot disks for this VM
  • DISK_1_SIZE and DISK_2_SIZE: Optional: sizes, in gigabytes, of each new non-boot disk

    The sizes must be equal to or larger than the sizes of the source disks from which the snapshot was made.

  • DISK_1_TYPE and DISK_2_TYPE: Optional: types of the persistent disks

    For example, https://www.googleapis.com/compute/v1/projects/PROJECT_ID/zones/ZONE/diskTypes/pd-ssd.

API

When using the API to restore a non-boot snapshot to a new VM, the following restrictions apply:

  • Only one persistent disk can be the boot persistent disk.
  • You must attach the boot persistent disk as the first disk for that VM.
  • If you specify the source property, you can't also specify the initializeParams property. Providing a source indicates that the boot persistent disk exists already, but the initializeParams property indicates that Compute Engine should create a new boot persistent disk.

Using the beta API, specify the sourceSnapshot field under the initializeParams property. You can add up to 15 non-boot disks by repeating the initializeParams property for every non-boot disk that you want to create. You can optionally specify the diskSizeGb and diskType properties for any of the disks that you create.

For example, to restore two non-boot snapshots to a new VM, make the following request:

POST https://compute.googleapis.com/compute/v1/projects/PROJECT_ID/zones/ZONE/instances
{
  "name": "VM_NAME",
  "machineType": "machineTypes/MACHINE_TYPE"
  "networkInterfaces": [{
    "accessConfigs": [{
      "type": "ONE_TO_ONE_NAT",
      "name": "External NAT"
    }],
    "network": "global/networks/default"
  }],
  "disks": [{
     "autoDelete": "true",
     "boot": "true",
     "type": "PERSISTENT",
     "diskSizeGb": "DISK_SIZE",
     "diskType": "DISK_TYPE"
   },
   {
     "initializeParams": {
        "sourceSnapshot": "global/snapshots/SNAPSHOT_1_NAME",
        "diskSizeGb": "DISK_SIZE",
        "diskType": "DISK_TYPE"
     }
   },
   {
     "initializeParams": {
        "sourceSnapshot": "global/snapshots/SNAPSHOT_2_NAME",
        "diskSizeGb": "DISK_SIZE",
        "diskType": "DISK_TYPE"
     }
  }]
 }

Replace the following:

  • PROJECT_ID: your project ID
  • ZONE: zone where you want to create the VM
  • VM_NAME: name of the VM that you want to restore a snapshot to
  • MACHINE_TYPE: machine type of the VM
  • DISK_SIZE: Optional: size, in gigabytes, of the corresponding disk

    When provided, this property must be equal to or larger than the size of the source disk from which the snapshot was made.

  • DISK_TYPE: Optional: full or partial URL for the type of the corresponding persistent disk

    For example, https://www.googleapis.com/compute/v1/projects/PROJECT_ID/zones/ZONE/diskTypes/pd-ssd.

  • SNAPSHOT_1_NAME and SNAPSHOT_2_NAME: names of non-boot snapshots that you want to restore to new, non-boot disks on the new VM