Stay organized with collections
Save and categorize content based on your preferences.
A disk is either a boot disk that is used to start and run the operating system
on a virtual machine (VM) instance 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:
Create a disk from a snapshot and optionally attach it to a VM
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.
Permissions required for this task
To perform this task, you must have the following
permissions:
compute.disks.create on the project to create a new disk
compute.instances.attachDisk on the VM instance
compute.disks.use permission on the disk to attach
Console
In the Google Cloud console, go to the Snapshots page.
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.
Under Source type, click Snapshot.
Select the name of the snapshot to restore.
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.
Click Create to create the disk.
Optionally, you can then attach the new disk to an existing instance.
Replace SNAPSHOT_NAME with the name of the snapshot being
restored.
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.
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.
DISK_NAME is the name of the disk made from your snapshot.
API
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.
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.
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 by
constructing a POST request to the instances.attachDisk
method,
and including 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"
}
Replace the following:
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.
import com.google.cloud.compute.v1.Disk;
import com.google.cloud.compute.v1.DisksClient;
import com.google.cloud.compute.v1.InsertDiskRequest;
import com.google.cloud.compute.v1.Operation;
import java.io.IOException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
public class CreateDiskFromSnapshot {
public static void main(String[] args)
throws IOException, ExecutionException, InterruptedException, TimeoutException {
// TODO(developer): Replace these variables before running the sample.
// Project ID or project number of the Cloud project you want to use.
String projectId = "YOUR_PROJECT_ID";
// Name of the zone in which you want to create the disk.
String zone = "europe-central2-b";
// Name of the disk you want to create.
String diskName = "YOUR_DISK_NAME";
// 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"
String diskType = String.format("zones/%s/diskTypes/pd-ssd", zone);
// Size of the new disk in gigabytes.
long diskSizeGb = 10;
// The full path and name of the snapshot that you want to use as the source for the new disk.
// This value uses the following format:
// "projects/{projectName}/global/snapshots/{snapshotName}"
String snapshotLink = String.format("projects/%s/global/snapshots/%s", projectId,
"SNAPSHOT_NAME");
createDiskFromSnapshot(projectId, zone, diskName, diskType, diskSizeGb, snapshotLink);
}
// Creates a new disk in a project in given zone, using a snapshot.
public static void createDiskFromSnapshot(String projectId, String zone, String diskName,
String diskType, long diskSizeGb, String snapshotLink)
throws IOException, ExecutionException, InterruptedException, TimeoutException {
// Initialize client that will be used to send requests. This client only needs to be created
// once, and can be reused for multiple requests. After completing all of your requests, call
// the `disksClient.close()` method on the client to safely
// clean up any remaining background resources.
try (DisksClient disksClient = DisksClient.create()) {
// Set the disk properties and the source snapshot.
Disk disk = Disk.newBuilder()
.setName(diskName)
.setZone(zone)
.setSizeGb(diskSizeGb)
.setType(diskType)
.setSourceSnapshot(snapshotLink)
.build();
// Create the insert disk request.
InsertDiskRequest insertDiskRequest = InsertDiskRequest.newBuilder()
.setProject(projectId)
.setZone(zone)
.setDiskResource(disk)
.build();
// Wait for the create disk operation to complete.
Operation response = disksClient.insertAsync(insertDiskRequest)
.get(3, TimeUnit.MINUTES);
if (response.hasError()) {
System.out.println("Disk creation failed!" + response);
return;
}
System.out.println("Disk created. Operation Status: " + response.getStatus());
}
}
}
import sys
from typing import Any
from google.api_core.extended_operation import ExtendedOperation
from google.cloud import compute_v1
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_disk_from_snapshot(
project_id: str,
zone: str,
disk_name: str,
disk_type: str,
disk_size_gb: int,
snapshot_link: str,
) -> compute_v1.Disk:
"""
Creates a new disk in a project in given zone.
Args:
project_id: project ID or project number of the Cloud project you want to use.
zone: name of the zone in which you want to create the disk.
disk_name: name of the disk you want to create.
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
snapshot_link: a link to the snapshot you want to use as a source for the new disk.
This value uses the following format: "projects/{project_name}/global/snapshots/{snapshot_name}"
Returns:
An unattached Disk instance.
"""
disk_client = compute_v1.DisksClient()
disk = compute_v1.Disk()
disk.zone = zone
disk.size_gb = disk_size_gb
disk.source_snapshot = snapshot_link
disk.type_ = disk_type
disk.name = disk_name
operation = disk_client.insert(project=project_id, zone=zone, disk_resource=disk)
wait_for_extended_operation(operation, "disk creation")
return disk_client.get(project=project_id, zone=zone, disk=disk_name)
Create a VM from existing disks
You can create boot disk and data disks from snapshots and then attach these
disks to a new VM.
import com.google.cloud.compute.v1.AttachedDisk;
import com.google.cloud.compute.v1.Disk;
import com.google.cloud.compute.v1.DisksClient;
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.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
public class CreateInstanceWithExistingDisks {
public static void main(String[] args)
throws IOException, ExecutionException, InterruptedException, TimeoutException {
// TODO(developer): Replace these variables before running the sample.
// Project ID or project number of the Cloud project you want to use.
String projectId = "YOUR_PROJECT_ID";
// Name of the zone to create the instance in. For example: "us-west3-b"
String zone = "europe-central2-b";
// Name of the new virtual machine (VM) instance.
String instanceName = "YOUR_INSTANCE_NAME";
// Array of disk names to be attached to the new virtual machine.
// First disk in this list will be used as the boot disk.
List<String> diskNames = List.of("your-boot-disk", "another-disk1", "another-disk2");
createInstanceWithExistingDisks(projectId, zone, instanceName, diskNames);
}
// Create a new VM instance using the selected disks.
// The first disk in diskNames will be used as the boot disk.
public static void createInstanceWithExistingDisks(String projectId, String zone,
String instanceName, List<String> diskNames)
throws IOException, ExecutionException, InterruptedException, TimeoutException {
// Initialize client that will be used to send requests. This client only needs to be created
// once, and can be reused for multiple requests. After completing all of your requests, call
// the `instancesClient.close()` method on the client to safely
// clean up any remaining background resources.
try (InstancesClient instancesClient = InstancesClient.create();
DisksClient disksClient = DisksClient.create()) {
if (diskNames.size() == 0) {
throw new Error("At least one disk should be provided");
}
// Create the list of attached disks to be used in instance creation.
List<AttachedDisk> attachedDisks = new ArrayList<>();
for (int i = 0; i < diskNames.size(); i++) {
String diskName = diskNames.get(i);
Disk disk = disksClient.get(projectId, zone, diskName);
AttachedDisk attDisk = null;
if (i == 0) {
// Make the first disk in the list as the boot disk.
attDisk = AttachedDisk.newBuilder()
.setSource(disk.getSelfLink())
.setBoot(true)
.build();
} else {
attDisk = AttachedDisk.newBuilder()
.setSource(disk.getSelfLink())
.build();
}
attachedDisks.add(attDisk);
}
// Create the instance.
Instance instance = Instance.newBuilder()
.setName(instanceName)
// Add the attached disks to the instance.
.addAllDisks(attachedDisks)
.setMachineType(String.format("zones/%s/machineTypes/n1-standard-1", zone))
.addNetworkInterfaces(
NetworkInterface.newBuilder().setName("global/networks/default").build())
.build();
// Create the insert instance request.
InsertInstanceRequest insertInstanceRequest = InsertInstanceRequest.newBuilder()
.setProject(projectId)
.setZone(zone)
.setInstanceResource(instance)
.build();
// Wait for the create operation to complete.
Operation response = instancesClient.insertAsync(insertInstanceRequest)
.get(3, TimeUnit.MINUTES);
if (response.hasError()) {
System.out.println("Instance creation failed!" + response);
return;
}
System.out.println("Operation Status: " + response.getStatus());
}
}
}
import re
import sys
from typing import Any, Iterable, List, NoReturn
import warnings
from google.api_core.extended_operation import ExtendedOperation
from google.cloud import compute_v1
def get_disk(project_id: str, zone: str, disk_name: str) -> compute_v1.Disk:
"""
Gets a disk from a project.
Args:
project_id: project ID or project number of the Cloud project you want to use.
zone: name of the zone where the disk exists.
disk_name: name of the disk you want to retrieve.
"""
disk_client = compute_v1.DisksClient()
return disk_client.get(project=project_id, zone=zone, disk=disk_name)
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,
spot: bool = False,
instance_termination_action: str = "STOP",
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. Preemptible VMs have been deprecated and you should now use Spot VMs.
spot: boolean value indicating if the new instance should be a Spot VM or not.
instance_termination_action: What action should be taken once a Spot VM is terminated.
Possible values: "STOP", "DELETE"
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.network_interfaces = [network_interface]
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
if preemptible:
# Set the preemptible setting
warnings.warn(
"Preemptible VMs are being replaced by Spot VMs.", DeprecationWarning
)
instance.scheduling = compute_v1.Scheduling()
instance.scheduling.preemptible = True
if spot:
# Set the Spot VM setting
instance.scheduling = compute_v1.Scheduling()
instance.scheduling.provisioning_model = (
compute_v1.Scheduling.ProvisioningModel.SPOT.name
)
instance.scheduling.instance_termination_action = instance_termination_action
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_with_existing_disks(
project_id: str, zone: str, instance_name: str, disk_names: List[str]
) -> compute_v1.Instance:
"""
Create a new VM instance using selected disks. The first disk in disk_names will
be used as boot disk.
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.
disk_names: list of disk names to be attached to the new virtual machine.
First disk in this list will be used as the boot device.
Returns:
Instance object.
"""
assert len(disk_names) >= 1
disks = [get_disk(project_id, zone, disk_name) for disk_name in disk_names]
attached_disks = []
for disk in disks:
adisk = compute_v1.AttachedDisk()
adisk.source = disk.self_link
attached_disks.append(adisk)
attached_disks[0].boot = True
instance = create_instance(project_id, zone, instance_name, attached_disks)
return instance
Create a 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.
Permissions required for this task
To perform this task, you must have the following
permissions:
compute.instances.create on the project
compute.instances.updateShieldedVmConfig if you plan to create a
Shielded VM instance and you want
to be able to change any of the Shielded VM settings
compute.networks.use on the project if using a legacy
network
compute.subnetworks.use either on the whole project or on the chosen subnet
(VPC networks)
compute.networks.useExternalIp on the project if you need to assign an external
IP address (either ephemeral or static) to the instance using a legacy network
compute.subnetworks.useExternalIp either on the whole project or on the chosen
subnet if you need to assign an external IP address (either ephemeral or static) to the instance
using a VPC network
compute.addresses.use on the project if specifying a static address in the
project
compute.instances.setMetadata if setting metadata
compute.instances.setTags on the instance if setting tags
compute.instances.setLabels on the instance if setting
labels
compute.instances.setServiceAccount on the instance if setting
service account
compute.images.useReadOnly on the image if creating a new root
persistent disk
compute.disks.create on the project if creating a new root
persistent disk with this instance
compute.disks.useReadOnly on the disk if attaching an existing
persistent disk in read-only mode
compute.disks.use on the disk if attaching an existing disk in
read/write mode
compute.disks.setLabels on the disk if setting
labels
compute.snapshots.create on the project to create a new
snapshot if creating an instance from a snapshot
compute.snapshots.useReadOnly on the snapshot if creating an instance
from a snapshot
compute.instanceTemplates.useReadOnly on the instance template if creating
instance from instance template
Console
In the Google Cloud console, go to the VM instances page.
Optional: Change the Zone for this VM. Compute Engine
randomizes the list of zones within each region to encourage use across
multiple zones.
Select a Machine configuration for your VM.
In the Boot disk section, click Change, and then do the
following:
Click the Snapshots tab.
In the Snapshot list, click a snapshot.
Specify the boot disk type and size.
Optional: For advanced configuration options, click Show advanced
configurations.
To confirm your boot disk options, click Select.
In the Firewall section, to permit HTTP or HTTPS traffic to
the VM, select Allow HTTP traffic or Allow HTTPS traffic.
The Google 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.
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:
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);
}
import re
import sys
from typing import Any, List
import warnings
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,
spot: bool = False,
instance_termination_action: str = "STOP",
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. Preemptible VMs have been deprecated and you should now use Spot VMs.
spot: boolean value indicating if the new instance should be a Spot VM or not.
instance_termination_action: What action should be taken once a Spot VM is terminated.
Possible values: "STOP", "DELETE"
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.network_interfaces = [network_interface]
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
if preemptible:
# Set the preemptible setting
warnings.warn(
"Preemptible VMs are being replaced by Spot VMs.", DeprecationWarning
)
instance.scheduling = compute_v1.Scheduling()
instance.scheduling.preemptible = True
if spot:
# Set the Spot VM setting
instance.scheduling = compute_v1.Scheduling()
instance.scheduling.provisioning_model = (
compute_v1.Scheduling.ProvisioningModel.SPOT.name
)
instance.scheduling.instance_termination_action = instance_termination_action
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
Create a 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.
Permissions required for this task
To perform this task, you must have the following
permissions:
compute.instances.create on the project
compute.instances.updateShieldedVmConfig if you plan to create a
Shielded VM instance and you want
to be able to change any of the Shielded VM settings
compute.networks.use on the project if using a legacy
network
compute.subnetworks.use either on the whole project or on the chosen subnet
(VPC networks)
compute.networks.useExternalIp on the project if you need to assign an external
IP address (either ephemeral or static) to the instance using a legacy network
compute.subnetworks.useExternalIp either on the whole project or on the chosen
subnet if you need to assign an external IP address (either ephemeral or static) to the instance
using a VPC network
compute.addresses.use on the project if specifying a static address in the
project
compute.instances.setMetadata if setting metadata
compute.instances.setTags on the instance if setting tags
compute.instances.setLabels on the instance if setting
labels
compute.instances.setServiceAccount on the instance if setting
service account
compute.images.useReadOnly on the image if creating a new root
persistent disk
compute.disks.create on the project if creating a new root
persistent disk with this instance
compute.disks.useReadOnly on the disk if attaching an existing
persistent disk in read-only mode
compute.disks.use on the disk if attaching an existing disk in
read/write mode
compute.disks.setLabels on the disk if setting
labels
compute.snapshots.create on the project to create a new
snapshot if creating an instance from a snapshot
compute.snapshots.useReadOnly on the snapshot if creating an instance
from a snapshot
compute.instanceTemplates.useReadOnly on the instance template if creating
instance from instance template
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.
Restore each non-boot snapshot to a new disk.
In the Google Cloud console, go to the Disks page.
Select the Region and Zone for this VM. The disk and VM
must be in the same zone.
Select a Machine type for your VM.
If you want to allow incoming external traffic, change the Firewall
rules for the VM.
To attach disks to the VM, expand the Networking, disks, security, management, sole tenancy
section, and then do the following:
Expand the Disks section.
Click Attach existing disk.
In the Disk list, select a disk to attach to this
VM.
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.
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.
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:
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: