스냅샷으로 부팅 또는 비부팅 디스크를 백업한 경우 스냅샷을 기반으로 새 디스크를 만들 수 있습니다.
제한사항
새 디스크의 크기는 최소한 스냅샷의 원래 소스 디스크와 같아야 합니다. 스냅샷의 원본 소스 디스크보다 큰 디스크를 만드는 경우 추가 디스크 공간이 포함되도록 영구 디스크의 파일 시스템 크기를 조절해야 합니다. 운영체제 및 파일 시스템 유형에 따라서는 다른 파일 시스템 크기 조절 도구를 사용해야 할 수도 있습니다.
자세한 내용은 운영체제 문서를 참조하세요.
지정된 스냅샷에서 최대 10분마다 영역 또는 리전 디스크를 만들 수 있습니다. 디스크 스냅샷 요청 버스트를 실행하려면 60분 동안 최대 6개의 요청을 실행할 수 있습니다. 스냅샷에서 리전 디스크를 만들 때는 이 한도가 적용되지 않습니다. 자세한 내용은 스냅샷 빈도 제한을 참조하세요.
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());
}
}
}
from __future__ import annotations
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:
"""
Waits 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)
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());
}
}
}
from __future__ import annotations
import re
import sys
from typing import Any
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:
"""
Waits 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.network = 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}"
instance.scheduling = compute_v1.Scheduling()
if accelerators:
instance.guest_accelerators = accelerators
instance.scheduling.on_host_maintenance = (
compute_v1.Scheduling.OnHostMaintenance.TERMINATE.name
)
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.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
부팅 디스크 스냅샷에서 VM 만들기
스냅샷으로 VM의 부팅 디스크를 백업한 경우 해당 스냅샷을 사용하여 새 VM을 만들 수 있습니다.
스냅샷에서 리전 영구 디스크 부팅 디스크로 VM을 만들려면 Google Cloud CLI 또는 Compute Engine API를 사용합니다.
선택사항: 이 VM의 영역을 변경합니다. Compute Engine은 각 리전 내의 영역 목록의 순서를 무작위로 지정하여 여러 영역에서 사용하도록 권장합니다.
VM의 머신 구성을 선택합니다.
부팅 디스크 섹션에서 변경을 클릭한 후 다음을 수행합니다.
스냅샷 탭을 클릭합니다.
스냅샷 목록에서 스냅샷을 클릭합니다.
부팅 디스크 유형과 크기를 지정합니다.
(선택사항) 고급 구성 옵션의 경우 고급 구성 표시를 클릭합니다.
부팅 디스크 옵션을 확인하려면 선택을 클릭합니다.
방화벽 섹션에서 VM에 대한 HTTP 또는 HTTPS 트래픽을 허용하려면 HTTP 트래픽 허용 또는 HTTPS 트래픽 허용을 선택합니다.
Google Cloud 콘솔은 VM에 네트워크 태그를 추가하고 tcp:80(HTTP) 또는 tcp:443(HTTPS)에서 들어오는 모든 트래픽을 허용하는 인그레스 방화벽 규칙을 만듭니다. 네트워크 태그는 방화벽 규칙을 VM과 연결합니다. 자세한 내용은 Virtual Private Cloud 문서의 방화벽 규칙 개요를 참조하세요.
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);
}
from __future__ import annotations
import re
import sys
from typing import Any
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:
"""
Waits 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.network = 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}"
instance.scheduling = compute_v1.Scheduling()
if accelerators:
instance.guest_accelerators = accelerators
instance.scheduling.on_host_maintenance = (
compute_v1.Scheduling.OnHostMaintenance.TERMINATE.name
)
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.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
REST
API를 사용하여 스냅샷에서 VM을 만드는 경우 다음 제한사항이 적용됩니다.
하나의 영구 디스크만 부팅 디스크로 사용될 수 있습니다.
해당 VM의 첫 번째 디스크로 부팅 디스크를 연결해야 합니다.
source 속성을 지정하면 initializeParams 속성을 지정할 수 없습니다. source 제공은 부팅 영구 디스크가 이미 있음을 나타내지만 initializeParams 속성은 Compute Engine이 부팅 영구 디스크를 새로 만들어야 함을 나타냅니다.
Persistent Disk 부팅 디스크
부팅 디스크 스냅샷을 사용하여 VM을 만들려면 instances.insert 메서드를 사용하고 disks 속성 아래에 sourceSnapshot 필드를 지정합니다. (선택사항) 새 부팅 디스크의 diskSizeGb 및 diskType 속성을 지정합니다.
이 VM의 리전과 영역을 선택합니다. 디스크 및 VM이 영역 디스크와 동일한 영역에 있거나 리전 디스크의 리전에 있어야 합니다.
VM의 머신 유형을 선택합니다.
외부 수신 트래픽을 허용하려면 VM의 방화벽 규칙을 변경합니다.
VM에 디스크를 연결하려면 고급 옵션 섹션을 펼친 후 다음을 수행합니다.
디스크 섹션을 펼칩니다.
기존 디스크 연결을 클릭합니다.
디스크 목록에서 이 VM에 연결할 디스크를 선택합니다.
연결 설정 섹션에서 디스크의 연결 모드와 삭제 규칙을 선택합니다. 새 디스크 추가에 대한 자세한 내용은 VM에 영구 디스크 추가를 참조하세요.
저장을 클릭합니다.
연결하려는 디스크마다 이 단계를 반복합니다. VM을 만들 때 비부팅 디스크를 15개까지 추가할 수 있습니다.
만들기를 클릭하여 VM을 만들고 시작합니다.
gcloud
gcloud compute instances create 명령어를 사용하여 VM을 만듭니다.
복원할 각 비부팅 스냅샷에 대해 --create-disk 플래그를 포함하고 source-snapshot을 지정합니다. VM을 만들 때 비부팅 디스크를 15개까지 추가할 수 있습니다.
예를 들면 https://www.googleapis.com/compute/v1/projects/PROJECT_ID/zones/ZONE/diskTypes/pd-ssd입니다.
REST
API를 사용하여 비부팅 스냅샷을 새 VM으로 복원하는 경우 다음 제한 사항이 적용됩니다.
하나의 영구 디스크만 부팅 영구 디스크가 될 수 있습니다.
해당 VM의 첫 번째 디스크로 부팅 영구 디스크를 연결해야 합니다.
source 속성을 지정하면 initializeParams 속성을 지정할 수 없습니다. source 제공은 부팅 영구 디스크가 이미 있음을 나타내지만 initializeParams 속성은 Compute Engine이 부팅 영구 디스크를 새로 만들어야 함을 나타냅니다.
베타 API를 사용하여 initializeParams 속성에서 sourceSnapshot 필드를 지정합니다. 만들려는 모든 비부팅 디스크의 initializeParams 속성을 반복하여 비부팅 디스크를 15개까지 추가할 수 있습니다. 필요한 경우 만드는 모든 디스크에 diskSizeGb 및 diskType 속성을 지정할 수 있습니다.