compute/api/create_instance.py (133 lines of code) (raw):
#!/usr/bin/env python
# Copyright 2015 Google Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Example of using the Compute Engine API to create and delete instances.
Creates a new compute engine instance and uses it to apply a caption to
an image.
https://cloud.google.com/compute/docs/tutorials/python-guide
For more information, see the README.md under /compute.
"""
import argparse
import os
import time
import googleapiclient.discovery
def list_instances(
compute: object,
project: str,
zone: str,
) -> list:
"""Lists all instances in the specified zone.
Args:
compute: an initialized compute service object.
project: the Google Cloud project ID.
zone: the name of the zone in which the instances should be listed.
Returns:
A list of instances.
"""
result = compute.instances().list(project=project, zone=zone).execute()
return result["items"] if "items" in result else None
# [START compute_create_instance]
def create_instance(
compute: object,
project: str,
zone: str,
name: str,
bucket: str,
) -> str:
"""Creates an instance in the specified zone.
Args:
compute: an initialized compute service object.
project: the Google Cloud project ID.
zone: the name of the zone in which the instances should be created.
name: the name of the instance.
bucket: the name of the bucket in which the image should be written.
Returns:
The instance object.
"""
# Get the latest Debian Jessie image.
image_response = (
compute.images()
.getFromFamily(project="debian-cloud", family="debian-11")
.execute()
)
source_disk_image = image_response["selfLink"]
# Configure the machine
machine_type = "zones/%s/machineTypes/n1-standard-1" % zone
startup_script = open(
os.path.join(os.path.dirname(__file__), "startup-script.sh")
).read()
image_url = "http://storage.googleapis.com/gce-demo-input/photo.jpg"
image_caption = "Ready for dessert?"
config = {
"name": name,
"machineType": machine_type,
# Specify the boot disk and the image to use as a source.
"disks": [
{
"boot": True,
"autoDelete": True,
"initializeParams": {
"sourceImage": source_disk_image,
},
}
],
# Specify a network interface with NAT to access the public
# internet.
"networkInterfaces": [
{
"network": "global/networks/default",
"accessConfigs": [{"type": "ONE_TO_ONE_NAT", "name": "External NAT"}],
}
],
# Allow the instance to access cloud storage and logging.
"serviceAccounts": [
{
"email": "default",
"scopes": [
"https://www.googleapis.com/auth/devstorage.read_write",
"https://www.googleapis.com/auth/logging.write",
],
}
],
# Metadata is readable from the instance and allows you to
# pass configuration from deployment scripts to instances.
"metadata": {
"items": [
{
# Startup script is automatically executed by the
# instance upon startup.
"key": "startup-script",
"value": startup_script,
},
{"key": "url", "value": image_url},
{"key": "text", "value": image_caption},
{"key": "bucket", "value": bucket},
]
},
}
return compute.instances().insert(project=project, zone=zone, body=config).execute()
# [END compute_create_instance]
def delete_instance(
compute: object,
project: str,
zone: str,
name: str,
) -> str:
"""Deletes an instance.
Args:
compute: An initialized compute service object.
project: The Google Cloud project ID.
zone: The name of the zone in which the instances should be deleted.
name: The name of the instance.
Returns:
Execute to delete the instance object.
"""
return (
compute.instances().delete(project=project, zone=zone, instance=name).execute()
)
# [START compute_wait_for_operation]
def wait_for_operation(
compute: object,
project: str,
zone: str,
operation: str,
) -> dict:
"""Waits for the given operation to complete.
Args:
compute: an initialized compute service object.
project: the Google Cloud project ID.
zone: the name of the zone in which the operation should be executed.
operation: the operation ID.
Returns:
The result of the operation.
"""
print("Waiting for operation to finish...")
while True:
result = (
compute.zoneOperations()
.get(project=project, zone=zone, operation=operation)
.execute()
)
if result["status"] == "DONE":
print("done.")
if "error" in result:
raise Exception(result["error"])
return result
time.sleep(1)
# [END compute_wait_for_operation]
def main(
project: str,
bucket: str,
zone: str,
instance_name: str,
wait=True,
) -> None:
"""Runs the demo.
Args:
project: the Google Cloud project ID.
bucket: the name of the bucket in which the image should be written.
instance_name: the name of the instance.
wait: whether to wait for the operation to complete.
Returns:
None.
"""
compute = googleapiclient.discovery.build("compute", "v1")
print("Creating instance.")
operation = create_instance(compute, project, zone, instance_name, bucket)
wait_for_operation(compute, project, zone, operation["name"])
instances = list_instances(compute, project, zone)
print(f"Instances in project {project} and zone {zone}:")
for instance in instances:
print(f' - {instance["name"]}')
print(
f"""
Instance created.
It will take a minute or two for the instance to complete work.
Check this URL: http://storage.googleapis.com/{bucket}/output.png
Once the image is uploaded press enter to delete the instance.
"""
)
if wait:
input()
print("Deleting instance.")
operation = delete_instance(compute, project, zone, instance_name)
wait_for_operation(compute, project, zone, operation["name"])
if __name__ == "__main__":
parser = argparse.ArgumentParser(
description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter
)
parser.add_argument("project_id", help="Your Google Cloud project ID.")
parser.add_argument("bucket_name", help="Your Google Cloud Storage bucket name.")
parser.add_argument(
"--zone", default="us-central1-f", help="Compute Engine zone to deploy to."
)
parser.add_argument("--name", default="demo-instance", help="New instance name.")
args = parser.parse_args()
main(args.project_id, args.bucket_name, args.zone, args.name)