Using the Python Client Library

This document demonstrates how to use the Google Python Client Library for Google Compute Engine. It describes how to authorize requests and how to create, list, and stop instances. This exercise discusses how to use the google-api-python-client library to access Google Compute Engine resources from outside (and within) a virtual machine instance. It does not discuss how to build and run applications within a virtual machine instance.

For a full list of available client libraries, including other Google client libraries and third-party open source libraries, see the Client Libraries page.

Contents

  1. Prerequisites
  2. Getting Started
    1. Authorizing Request
    2. Initializing the API
  3. Listing Instances
  4. Adding an Instance
  5. Deleting an Instance
  6. Waiting for operations
  7. Code Sample and API Reference

Prerequisites

Cloud Project

Create a project on the Google Cloud Platform Console and enable billing.. The project contains all of your resources under a single namespace, and billing is required to create any instances in your project.

Cloud SDK

The Cloud SDK contains tools and libraries that enable you to easily create and manage resources on Google Cloud Platform. Please refer to the Cloud SDK installation instructions to get the SDK for your platform.

After installing the SDK, be sure to authenticate and set your default project:

gcloud init

Google API Client for Python

The google-api-python-client library contains the core Python library for accessing Google APIs and also contains the OAuth 2.0 client library. The typical installation is simply:

$ pip install --upgrade google-api-python-client

For more information on how to install this library, see the installation instructions. You also need to have Python 2.7 or 3.3+ to run the Google Python Client Library.

Getting Started

The purpose of this exercise is to describe how to authorize requests and how to perform basic instance management tasks using the google-api-python-client library. At the end of this exercise, you should be able to:

  • Perform OAuth 2.0 authorization using the oauth2client library
  • Create an instance using the google-python-client library
  • List instances using the google-python-client library
  • Stop an instance using the google-python-client library

To skip the exercise and view the full code example, visit the GoogleCloudPlatform/python-docs-samples GitHub page.

Authorizing Requests

This sample uses OAuth 2.0 authorization. There are many ways to authorize requests using OAuth 2.0, but for the example you will use Application Default Credentials. This allows you to re-use the credentials from the gcloud tool. You should have installed and authorized this tool in the prerequisites section.

To use the application default credentials, import GoogleCredentials:

from oauth2client.client import GoogleCredentials
credentials = GoogleCredentials.get_application_default()

These credentials will be used in the next section to create an API client.

Note: If you receive authorization errors during the next steps, make sure you have logged in with gcloud init.

Initializing the API

Before you can make requests, you first need to initialize an instance of the Google Compute Engine service using the API client library's build method:

from googleapiclient import discovery
compute = discovery.build('compute', 'v1', credentials=credentials)

Notice that you must pass in a valid credentials object, such as the one you generated in the previous step.

Listing Instances

Now that you have credentials and an instance of the client you can use the client to make calls to the Google Compute Engine API and manage resources.

To list the instances in your project, call compute.instances().list. You will need to provide the project ID, the zone for which you want to list instances, and any optional filters:

def list_instances(compute, project, zone):
    result = compute.instances().list(project=project, zone=zone).execute()
    return result['items']

Adding an Instance

To add an instance, use the instances().insert method and specify the properties of the new instance. These properties are specified in the request body; for details about each property see the API reference for instances.insert .

At a minimum, your request must provide values for the following properties when you create a new instance:

  • Instance name
  • Root persistent disk
  • Machine type
  • Zone
  • Network Interfaces

For this example, you are going to start an instance with the following properties:

  • Zone: us-central1-f
  • Machine type: n1-standard-1
  • Root persistent disk: a new persistent disk based on debian-backports
  • The default service account with the following scopes:
    • https://www.googleapis.com/auth/devstorage.read_write - to allow the instance to read and write files in Google Cloud Storage
    • https://www.googleapis.com/auth/logging.write - to allow the instances logs to be uploaded to Google Cloud Logging
  • Metadata to specify commands that the instance should execute upon startup
def create_instance(compute, project, zone, name, bucket):
    # Get the latest Debian Jessie image.
    image_response = compute.images().getFromFamily(
        project='debian-cloud', family='debian-8').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'), 'r').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()

The following sections describe the instance creation parameters.

If you would rather not hand construct the body for your request, many Google Compute Engine tools can automatic generate the JSON for you. For example, the Google Cloud Platform Console, which allows you to configure and create resources for your Google Compute Engine project, also provides a handy REST Request feature that constructs the JSON for the request for you. For more information, see Using the Console to Generate REST Requests.

Root persistent disks

All instances must boot from a root persistent disk. The root persistent disk contains all of the necessary files required for starting an instance. When you create a root persistent disk you must specify the source OS image that should be applied to the disk. In the example above, you created a new root persistent disk based on Debian 8 at the same time as the instance. However, it is also possible to create a disk beforehand and attach it to the instance.

Note: To create an instance using your own private custom OS image, you will need to provide a different URL than the one included in the example. For more information on starting an instance with your own images, see Creating and Starting an Instance.

Adding Instance Metadata

When you create your instance, you may want to include instance metadata such as a startup script, configuration variables, and ssh keys. In the example above, you used the metadata field in your request body to specify a startup script for the instance and some configuration variables as key/values pairs. The startup script, listed below, shows how to read these variables and use them to apply text to an image and upload it to Google Cloud Storage.

apt-get update
apt-get -y install imagemagick

# Use the metadata server to get the configuration specified during
# instance creation. Read more about metadata here:
# https://cloud.google.com/compute/docs/metadata#querying
IMAGE_URL=$(curl http://metadata/computeMetadata/v1/instance/attributes/url -H "Metadata-Flavor: Google")
TEXT=$(curl http://metadata/computeMetadata/v1/instance/attributes/text -H "Metadata-Flavor: Google")
CS_BUCKET=$(curl http://metadata/computeMetadata/v1/instance/attributes/bucket -H "Metadata-Flavor: Google")

mkdir image-output
cd image-output
wget $IMAGE_URL
convert * -pointsize 30 -fill white -stroke black -gravity center -annotate +10+40 "$TEXT" output.png

# Create a Google Cloud Storage bucket.
gsutil mb gs://$CS_BUCKET

# Store the image in the Google Cloud Storage bucket and allow all users
# to read it.
gsutil cp -a public-read output.png gs://$CS_BUCKET/output.png

Deleting an Instance

To delete an instance, you need to call the instances().delete method and provide the name, zone, and project ID of the instance to delete. Because you set the autoDelete parameter for the boot disk it will also be deleted when the instance is deleted. This setting is off by default but is useful when your use case calls for disks and instances to be deleted together.

def delete_instance(compute, project, zone, name):
    return compute.instances().delete(
        project=project,
        zone=zone,
        instance=name).execute()

Waiting for operations to complete

Requests to the Google Compute Engine API that modify resources such as instances will immediately return a response acknowledging your request. The acknowledgement will allow you to check the status of the requested operation. Operations can take a few minutes to complete so it's often easier to wait for the operation to complete before continuing. This helper method will wait until the operation completes before returning:
def wait_for_operation(compute, project, zone, 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)

Notice when you query per-zone operations, you use the zoneOperations.get() method, while querying global operations requires using the globalOperations.get() method. For more information, see zone resources.

Code Samples and API Reference

Now that you've completed this exercise, you can:

  • Download and view the full code sample. The full sample includes a small example of using all of these methods together. Feel free to download it, change it, and run it to suit your needs.
  • Review the API reference to learn how to perform other tasks with the API.
  • Start creating your own applications!

Send feedback about...

Compute Engine Documentation