Hide
Compute Engine

Storing and Retrieving Metadata

Every instance stores its metadata on the metadata server. You can query this metadata server programmatically for information about the instance, such as the instance's host name, instance ID, startup and shutdown scripts, custom metadata, and service account information. Your instance automatically has access to the metadata server API without any additional authorization.

Metadata is stored in the format key:value. There is a default set of metadata entries that every instance has access to. You can also create custom metadata.

The metadata server is accessible by querying any of the following URLs:

  • Full URL: http://metadata.google.internal/computeMetadata/v1/
  • Shorthand URL: http://metadata/computeMetadata/v1/
  • IP address: http://169.254.169.254/computeMetadata/v1/

For more information, see querying metadata.

Current version: v1

Compute Engine might offer more than one metadata version at a single time, but it is recommended that you always use the newest metadata server version available. At any time, Google Compute Engine can add new entries to the metadata server and add new fields to responses. Check back periodically for changes!

Contents

Project and instance metadata

Metadata can be assigned at both the project and instance level. Project level metadata propagates to all virtual machine instances within the project, while instance level metadata only impacts that instance. You can set both project and instance level metadata but if you set the same key for both your project and instance metadata, Compute Engine will use the instance metadata.

This behavior can affect the way your ssh keys are propagated, if you set both project and instance level ssh keys. For more information, see Setting up your ssh keys.

Default metadata

Google Compute Engine defines a set of default metadata entries that provide information about your instance or project. Default metadata is always defined and set by the server. You cannot manually edit any of these metadata pairs.

The following is a list of default metadata available to a project. Some metadata entries are directories that contain other metadata keys. This difference is marked by a trailing slash in the metadata name. For example, attributes/ is a directory that contains other keys, while numeric-project-id is a metadata key or endpoint that maps to a value.

Relative to http://metadata.google.internal/computeMetadata/v1/project/
Metadata Entry Description
attributes/ A directory of custom metadata values that are passed to the project.
attributes/sshKeys A list of ssh keys that can be used to connect to instances in the project.
numeric-project-id The numeric project ID of the instance, which is not the same as the project name visible in the Google Developers Console. Do not use this as the project with gcloud compute; instead, use the project-id metadata entry value.
project-id The project ID.

The following is a list of default metadata available to an instance:

Relative to http://metadata.google.internal/computeMetadata/v1/instance/
Metadata Entry Description
attributes/ A directory of custom metadata values passed to the instance during startup or shutdown. See Specifying Custom Metadata below.
description The free-text description of an instance, assigned using the --description flag, or set in the API.
disks/ A directory of disks attached to this instance.
hostname The host name of the instance.
id The ID of the instance. This is a unique, numerical ID that is generated by Google Compute Engine. This is useful for identifying instances if you do not want to use instance names.
machine-type The fully-qualified machine type name of the instance's host machine.
network-interfaces/ A directory of network interfaces for the instance.
network-interfaces/<index>/forwarded-ips/ A directory of any external IPs that are currently pointing to this virtual machine instance, for the network interface at <index>. Specifically, provides a list of external IPs served by forwarding rules that direct packets to this instance.
scheduling/ A directory with the scheduling options for the instance.
scheduling/on-host-maintenance The instance's transparent maintenance event behavior setting. This value is set with the ‑‑on_host_maintenance flag or via the API.
scheduling/automatic-restart The instance's automatic restart setting. This value is set with the ‑‑automatic_restart flag or via the API.
maintenance-event The path that indicates that a transparent maintenance event is affecting this instance. See Transparent maintenance notice for details.
service-accounts/ A directory of service accounts associated with the instance.
tags Any tags associated with the instance.
zone The instance's zone.

Query metadata

You can query the contents of the metadata server using the following root URLs from within a virtual machine. Any of the following metadata URLs can be used to make requests to the metadata server:

  • Full URL: http://metadata.google.internal/computeMetadata/v1/
  • Shorthand URL: http://metadata/computeMetadata/v1/
  • IP address: http://169.254.169.254/computeMetadata/v1/

Specific metadata values are defined as sub-paths below these root URLs.

You can query for default metadata values only from within the associated instance. You cannot query an instance's default metadata from another instance or directly from your local computer. For example, you would send a curl or wget command from the instance to its metadata server.

Custom metadata can be queried and set from outside the virtual machine, as well as from within the instance. See Specifying custom metadata for more information.

When you query for metadata, you must provide the following header in all of your requests:

Metadata-Flavor: Google

This header indicates that the request was sent with the intention of retrieving metadata values, rather than unintentionally from an insecure source, and allows the metadata server to return the data you requested. If you do not provide this header, the metadata server denies your request.

Depending on the type of query you make, the metadata server can return data in a number of ways.

Query directory listings

The metadata server uses directories to organize certain metadata keys. Any metadata entry ending in a trailing slash is a directory. For example, the disks/ entry is a directory of disks attached to that instance:

user@myinst:~$ curl "http://metadata.google.internal/computeMetadata/v1/instance/disks/" -H "Metadata-Flavor: Google"
0/
1/
2/

Similarly, if you wanted more information about the 1/ directory, you can query the specific URL for that directory:

user@myinst:~$ curl "http://metadata.google.internal/computeMetadata/v1/instance/disks/1/" -H "Metadata-Flavor: Google"
device-name
index
mode
type

Query metadata endpoints

Other metadata entries are keys or endpoints that return one or more values. To query for data from a metadata endpoint, send a query to that particular endpoint. For example, to query the mode of a specific disk, query the following endpoint:

user@myinst:~$ curl "http://metadata.google.internal/computeMetadata/v1/instance/disks/1/mode" -H "Metadata-Flavor: Google"
READ_WRITE

By default, each endpoint defines the format for returned data. Some endpoints might return data in JSON format by default, while other endpoints might return data as a string. You can override the default data format specification by using the alt=json or alt=text query parameters, which returns data in JSON string format or as a plaintext representation, respectfully.

For example, the tags key automatically returns data in JSON format. You can choose to return data in text format instead, by specifying the alt=text query parameter:

user@myinst:~$ curl "http://metadata.google.internal/computeMetadata/v1/instance/tags" -H "Metadata-Flavor: Google"
["bread","butter","cheese","cream","lettuce"]

user@myinst:~$ curl "http://metadata.google.internal/computeMetadata/v1/instance/tags?alt=text" -H "Metadata-Flavor: Google"
bread
butter
cheese
cream
lettuce

Query recursive contents

If you want to return all contents underneath a directory, use the recursive=true query parameter with your request:

user@myinst:~$ curl "http://metadata.google.internal/computeMetadata/v1/instance/disks/?recursive=true" -H "Metadata-Flavor: Google"
[{"deviceName":"boot","index":0,"mode":"READ_WRITE","type":"PERSISTENT"},
{"deviceName":"persistent-disk-1","index":1,"mode":"READ_WRITE","type":"PERSISTENT"},
{"deviceName":"persistent-disk-2","index":2,"mode":"READ_ONLY","type":"PERSISTENT"}]

By default, recursive contents are returned in JSON format. If you want to return these contents in text format, append the alt=text query parameter:

user@myinst:~$ curl "http://metadata.google.internal/computeMetadata/v1/instance/disks/?recursive=true&alt=text" -H "Metadata-Flavor: Google"
0/device-name boot
0/index 0
0/mode READ_WRITE
0/type PERSISTENT
1/device-name persistent-disk-1
1/index 1
1/mode READ_WRITE
1/type PERSISTENT
2/device-name persistent-disk-1
2/index 2
2/mode READ_ONLY
2/type PERSISTENT

Detect if you are running in Compute Engine

You can easily detect if your applications or scripts are running within a Compute Engine instance by using the metadata server. When you make a request to the server, any response from the metadata server will contain the Metadata-Flavor: Google header. You can look for this header to reliably detect if you are running in Compute Engine.

For example, the following curl request returns a Metadata-Flavor: Google header, indicating that the request is being made from within a Compute Engine instance.

me@my-inst:~$ curl metadata.google.internal -i
HTTP/1.1 200 OK
Metadata-Flavor: Google
Content-Type: application/text
Date: Thu, 10 Apr 2014 19:24:27 GMT
Server: Metadata Server for VM
Content-Length: 22
X-XSS-Protection: 1; mode=block
X-Frame-Options: SAMEORIGIN

0.1/
computeMetadata/

Specify custom metadata

You can set custom metadata for an instance or project from the Google Developers Console, gcloud, or the Compute Engine API. This is useful for passing in arbitrary values to your project or instance, and also useful for setting startup and shutdown scripts.

Set custom instance metadata

Set custom metadata for an instance in the Developers Console, the gcloud tool, or the API. Instance metadata applies only to a specific instance.

Set metadata during instance creation

Developers Console


In Developers Console:

  1. Log into the VM instances page in the Developers Console.
  2. Click New instance.
  3. Fill in the desired properties for your instance and expand the Management, disk, networking, access & security options section.
  4. In the Metadata section, fill in as many key/value pairs for your custom metadata as you need.
  5. When you are done, click Create to create your virtual machine.

gcloud


In gcloud, use the --metadata flag to set custom metadata.

$ gcloud compute instances create example-instance --metadata foo:bar

API


In the API, provide custom metadata as part of the metadata property in your request:

POST https://www.googleapis.com/compute/v1/projects/myproject/zones/us-central1-a/instances

{
  "...
        }
      ]
    }
  ],
  "metadata": {
    "items": [
      {
       "key": "foo",
       "value": "bar"
      }
    ]
  },
  ..
}

Update metadata on a running instance

Developers Console


  1. Log into the VM instances page in the Developers Console.
  2. Click on the instance for which you want to update metadata.
  3. Under Custom metadata, click Edit or Add metadata.
  4. Update your custom key/value pair.
  5. Save your changes.

gcloud


Updating instance metadata with the gcloud tool is an additive action. Specify only the metadata keys that you want to add or change. If a key that you provided already exists, the value for that key is updated with the new value.

In gcloud, use the instances add-metadata command:

$ gcloud compute instances add-metadata INSTANCE \
  --metadata bread=mayo cheese=cheddar lettuce=romaine

If you want to change the lettuce=romaine entry to lettuce=green, use:

$ gcloud compute instances add-metadata INSTANCE --metadata lettuce=green

If you want to remove the lettuce=romaine entry, specify the existing key and exclude the value.

$ gcloud compute instances remove-metadata INSTANCE --keys lettuce

API


In the API, make a request to the instances().setMetadata method. Provide the new metadata values and the current fingerprint value.

A fingerprint is a random string of characters generated by Compute Engine and is used to perform optimistic locking. Provide the matching fingerprint value in order to perform your request. The fingerprint changes after each request and if you provide a mismatched fingerprint, your request is rejected. In this way, only one update can be made at a time, preventing collisions.

To get the current fingerprint of an instance and see any existing key/value pairs for the instance. Send a instances().get request:

GET https://www.googleapis.com/compute/v1/projects/myproject/zones/us-central1-a/instances/example-instance

{
 ...
 "name": "example-instance",
 "metadata": {
  "kind": "compute#metadata",
  "fingerprint": "zhma6O1w2l8="
  "items": [
   {
    "key": "foo",
    "value": "bar"
   }
  ]
 },
 ...
}

Next, make a request to the instances().setMetadata method and set your custom metadata key/value pairs. If the instance has existing key/value pairs that you want to keep, you must include them in this request with the new key/value pairs:

POST https://www.googleapis.com/compute/v1/projects/myproject/zones/us-central1-a/instances/example-instance/setMetadata

{
 "fingerprint": "zhma6O1w2l8=",
 "items": [
  {
   "key": "foo",
   "value": "bar"
  },
  {
   "key": "baz",
   "value": "bat"
  }
 ]
}

To remove all metadata key/value pairs from an instance, specify an instances().setMetadata request and exclude the items property. Note that you must still include the current metadata fingerprint property for this request to succeed:

POST https://www.googleapis.com/compute/v1/projects/myproject/zones/us-central1-a/instances/example-instance/setMetadata

{
 "fingerprint": "5rC_DXxBUZw="
}

Set project-wide custom metadata

Set project-wide metadata to apply the metadata to all instances in the project. For example, if you define a project-wide metadata pair of baz=bat, that metadata pair is automatically applied to all instances in the project.

Similar to instance metadata, project metadata updates are additive. This means that you only specify the metadata keys that you want to add or change. If you specify an existing key, then the key's value will be updated with the new value.

Developers Console


  1. Log into the Metadata page.
  2. Click on Edit.
  3. Add or edit a metadata entry.
  4. Save your changes.

gcloud


In gcloud, use the project-info add-metadata command. For example:

$ gcloud compute project-info add-metadata --metadata foo=bar baz=bat
$ gcloud compute project-info describe
...
commonInstanceMetadata:
  fingerprint: RfOFY_-eS64=
  items:
  - key: baz
    value: bat
  - key: foo
    value: bar
  - key: sshKeys
...

One metadata key-value pair is specified with an equals sign, for example, key=value. Multiple key-value pairs are separated with spaces.

You can optionally specify one or more files from which to read metadata using the --metadata-from-file flag.

API


In the API, make a request to the projects().setCommonInstanceMetadata method, providing the new metadata and a fingerprint value.

A fingerprint is a random string of characters generated by Compute Engine and is used to perform optimistic locking. Provide the matching fingerprint value in order to perform your request. The fingerprint changes after each request and if you provide a mismatched fingerprint, your request is rejected. In this way, only one update can be made at a time, preventing collisions.

To get the current fingerprint of an instance, perform a project().get request and copy the fingerprint value:

GET https://www.googleapis.com/compute/v1/projects/myproject

{
 "name": "myproject",
 "commonInstanceMetadata": {
  "kind": "compute#metadata",
  "fingerprint": "FikclA7UBC0=",
  ...
}

Next, make a request to the projects().setCommonInstanceMetadata method and set your custom metadata key/value pairs:

POST https://www.googleapis.com/compute/v1/projects/myproject

{
 "fingerprint": "FikclA7UBC0=",
 "items": [
  {
   "key": "foo",
   "value": "bar"
  }
 ]
}

Querying custom metadata

Query custom instance or project metadata through the Developers Console, gcloud, or the API.

Developers Console


To see project-wide custom metadata, log into the Metadata page.

To see an instance's custom metadata:

  1. Log into the VM instances page in the Developers Console.
  2. Click on the instance for which you view metadata.
  3. Under Custom metadata, view the instance's custom metadata.

gcloud


To query project-wide metadata:

$ gcloud compute project-info
commonInstanceMetadata:
  fingerprint: FikclA7UBC0=
  items:
  - key: peanut
    value: butter
  kind: compute#metadata
creationTimestamp: '2014-07-08T10:32:36.417-07:00'
...
name: example-instance
quotas:
...
selfLink: https://www.googleapis.com/compute/v1/projects/example-instance

To query for instance metadata:

$ gcloud compute instances describe example-instance
canIpForward: false
cpuPlatform: Intel Sandy Bridge
...
metadata:
  fingerprint: xLQdf0brGqE=
  items:
  - key: peanut
    value: butter
  kind: compute#metadata
name: example-instance
networkInterfaces:
...

API


To query for a project's metadata, perform an empty request to the projects().get method:

GET https://www.googleapis.com/compute/v1/projects/myproject

To query for an instance's metadata, perform an empty request to the instance().get method:

GET https://www.googleapis.com/compute/v1/projects/myproject/zones/us-central1-a/instances/example-instance

Wait for change

Given that metadata values can change while your instance is running, the metadata server offers the ability to be notified of metadata changes using the wait-for-change feature. This feature allows you to perform hanging HTTP GET requests that only return when your specified metadata has changed. You can use this feature on custom metadata or server-defined metadata, so if anything changes about your instance or project, or if someone updates a custom metadata, you can programmatically react to the change. For example, you can perform a request on the tags key so that the request only returns if the contents of the tags metadata has changed. When the request returns, it provides the new value of that metadata key.

To perform a wait-for-change request, query a metadata key and append the ?wait_for_change=true query parameter:

user@myinst:~$ curl "http://metadata.google.internal/computeMetadata/v1/instance/tags?wait_for_change=true" -H "Metadata-Flavor: Google"

After there is a change to the specified metadata key, the query returns with the new value. In this example, if a request is made to the setInstanceTags method, the request returns with the new values:

user@myinst:~$ curl "http://metadata.google.internal/computeMetadata/v1/instance/tags?wait_for_change=true" -H "Metadata-Flavor: Google"
cheese
lettuce

You can also perform a wait-for-change request recursively on the contents of a directory:

user@myinst:~$ curl "http://metadata.google.internal/computeMetadata/v1/instance/attributes/?recursive=true&wait_for_change=true" -H "Metadata-Flavor: Google"

The metadata server returns the new contents if there is any change:

user@myinst:~$ curl "http://metadata.google.internal/computeMetadata/v1/instance/attributes/?recursive=true&wait_for_change=true" -H "Metadata-Flavor: Google"
{"cheese":"lettuce","cookies":"cream"}

The wait-for-change feature also lets you match with your request and set timeouts.

Use ETags

If you submit a simple wait-for-change query, the metadata server returns if anything has changed in the contents of that metadata. However, there is an inherent race condition between a metadata update and a wait-for-change request being issued, so it is useful to have a reliable way to know you are getting the latest metadata value. To help with this, you can use the last_etag query parameter, which compares the ETag value you provide with the ETag value saved on the metadata server. If the ETag values match, then the wait-for-change request will be accepted. If the ETag values do not match, this indicates that the contents of the metadata has changed since the last time you retrieved the ETag value, and the metadata server returns immediately with this latest value.

To grab the current ETag value for a metadata key, make a request to that key and print the headers. In CURL, you can do this with the -v flag:

user@myinst:~$ curl -v "http://metadata.google.internal/computeMetadata/v1/instance/tags" -H "Metadata-Flavor: Google"
* About to connect() to metadata port 80 (#0)
*   Trying 169.254.169.254... connected
* Connected to metadata (169.254.169.254) port 80 (#0)
> GET /computeMetadata/v1/instance/tags?wait_for_change=true HTTP/1.1
> User-Agent: curl/7.19.7 (x86_64-pc-linux-gnu) libcurl/7.19.7 OpenSSL/0.9.8k zlib/1.2.3.3 libidn/1.15
> Host: metadata
> Accept: */*
>
< HTTP/1.1 200 OK
< Content-Type: application/text
< ETag: 411261ca6c9e654e
< Date: Wed, 13 Feb 2013 22:43:45 GMT
< Server: Metadata Server for VM
< Content-Length: 26
< X-XSS-Protection: 1; mode=block
< X-Frame-Options: SAMEORIGIN
<
cheese
lettuce

You can also grab the ETag programmatically. The following example uses Python to extract the ETag value from the metadata response:

import httplib2

def main():
  http = httplib2.Http()
  response, content = http.request('http://metadata.google.internal/computeMetadata/v1/instance/tags',
                                   headers={'Metadata-Flavor': 'Google'})
  etag = response['etag']

  print etag

if __name__ == '__main__':
  main()

Use that ETag value in your wait-for-change request:

user@myinst:~$ curl "http://metadata.google.internal/computeMetadata/v1/instance/tags?wait_for_change=true&last_etag=411261ca6c9e654e" -H "Metadata-Flavor: Google"

The metadata server will match your specified ETag value and if that value changes, the request returns with the new contents of your metadata key.

Using 0 As Your ETag Value

The metadata server will never return 0 as an ETag. You could use that information to simplify some of your code. For example, the following code example sets the initial ETag value as 0, performs a request to the server, which immediately returns with the initial data and the current ETag value, and then uses that information to wait for a change. This method would save you from writing additional lines of code to grab the first initial ETag.

import httplib2

METADATA_URL = 'http://metadata.google.internal/computeMetadata/v1/'

def main():
  http = httplib2.Http()
  tagsUrl = METADATA_URL + 'instance/tags?wait_for_change=true'

  # set the first last_etag as 0
  last_etag = 0
  while True:
    # returns immediately on the initial request because 0 is invalid
    # otherwise wait until something changes
    resp,content = http.request(uri=tagsUrl + '&last_etag=' + str(last_etag), method='GET', body='', headers={'Metadata-Flavor': 'Google'})

    if resp != 500:
      last_etag = resp['etag']
      print content

if __name__ == '__main__':
  main()

Set timeouts

If you would like your wait-for-change request to time out after a certain number of seconds, you can set the timeout_sec=<timeout-in-seconds> query parameter. The timeout_sec parameter limits the wait time of your request to the number of seconds you specified and when the request reaches that limit, it returns the current contents of the metadata key. Here is an example of a wait-for-change request that is set to time out after 360 seconds:

user@myinst:~$ curl "http://metadata.google.internal/computeMetadata/v1/instance/tags?wait_for_change=true&timeout_sec=360" -H "Metadata-Flavor: Google"

When you set the timeout_sec parameter, the request always returns after the specified number of seconds, whether or not the metadata value has actually changed. It is only possible to set an integer value for your timeout.

Status codes

When you perform a wait-for-change request, the metadata server returns standard HTTP status codes to indicate success or failure. In the case of errors, network conditions can cause the metadata server to fail your request and return an error code. In these cases, you should design your application to be fault-tolerant and to be able to recognize and handle these errors.

The possible statuses that the metadata server returns are:

Status Description
HTTP 200 Success! A value was changed, or you reached your specified timeout_sec and the request returned successfully.
Error 400 Your request was invalid. Please fix your query and retry the request.
Error 404 The metadata value you specified no longer exists. The metadata server also returns this error if your metadata is deleted while you are waiting on a change.
Error 500 There was a temporary server error. Please retry your request.

Transparent maintenance notice

The metadata server provides information about an instance's scheduling options and settings, through the scheduling/ directory and the maintenance-event attribute. You can use these attributes to learn about a virtual machine instance's scheduling options, and also use this information to notify you when a maintenance event is about to happen, specifically through the maintenance-event attribute.

The maintenance-event attribute changes its value to indicate the start and end of a maintenance event. The initial value of the attribute is NONE, which indicates that no maintenance event is starting. 60 seconds before a transparent maintenance event, the maintenance-event value changes from NONE to MIGRATE_ON_HOST_MAINTENANCE. Throughout the duration of the maintenance event, the value remains the same. After the maintenance event ends, the value returns to NONE.

To query the maintenance-event attribute:

user@myinst:~$ curl http://metadata.google.internal/computeMetadata/v1/instance/maintenance-event -H "Metadata-Flavor: Google"
NONE

You can use the maintenance-event with the waiting for change feature to notify your scripts and applications when a maintenance event is about to start and end. This lets you automate any actions that you might want to run before or after the event. The following Python sample provides an example of how you might implement these two features together.

import httplib
import sys
import time
import urllib
import urllib2

METADATA_URL = 'http://metadata.google.internal/computeMetadata/v1/'

class Error(Exception):
  pass

class UnexpectedStatusException(Error):
  pass

class UnexpectedMaintenanceEventException(Error):
  pass

def WatchMetadata(metadata_key, handler, initial_value=None):
  """Watches for a change in the value of metadata.

  Args:
    metadata_key: The key identifying which metadata to watch for changes.
    handler: A callable to call when the metadata value changes. Will be passed
      a single parameter, the new value of the metadata.
    initial_value: The expected initial value for the metadata. The handler will
      not be called on the initial metadata request unless the value differs
      from this.

  Raises:
    UnexpectedStatusException: If the http request is unsuccessful for an
      unexpected reason.
  """
  params = {
      'wait_for_change': 'true',
      'last_etag': 0,
      }

  while True:
    value = initial_value
    # start a hanging-GET request for maintenance change events.
    url = '{base_url}{key}?{params}'.format(
        base_url=METADATA_URL,
        key=metadata_key,
        params=urllib.urlencode(params)
        )
    req = urllib2.Request(url, headers={'Metadata-Flavor': 'Google'})

    try:
      response = urllib2.urlopen(req)
      content = response.read()
      status = response.getcode()
    except urllib2.HTTPError as e:
      content = None
      status = e.code

    if status == httplib.SERVICE_UNAVAILABLE:
      time.sleep(1)
      continue
    elif status == httplib.OK:
      # Extract new maintenance-event value and latest etag.
      new_value = content
      headers = response.info()
      params['last_etag'] = headers['ETag']
    else:
      raise UnexpectedStatusException(status)

    # If the maintenance value changed, call the appropriate handler.
    if value != new_value:
      value = new_value
      handler(value)

def HandleMaintenance(on_maintenance_start, on_maintenance_end):
  """Watches for and responds to maintenance-event status changes.

  Args:
    on_maintenance_start: a callable to call before host maintenance starts.
    on_maintenance_end: a callable to call after host maintenance ends.

  Raises:
    UnexpectedStatusException: If the http request is unsuccessful for an
      unexpected reason.
    UnexpectedMaintenanceEventException: If the maintenance-event value is
      not either NONE or MIGRATE_ON_HOST_MAINTENANCE.

  Note: Instances that are set to TERMINATE_ON_HOST_MAINTENANCE will receive
  a power-button push and will not be notified through this script.
  """
  maintenance_key = 'instance/maintenance-event'

  def Handler(event):
    if event == 'MIGRATE_ON_HOST_MAINTENANCE':
      on_maintenance_start()
    elif event == 'NONE':
      on_maintenance_end()
    else:
      raise UnexpectedMaintenanceEventException(event)

  WatchMetadata(maintenance_key, Handler, initial_value='NONE')

def OnMaintenanceStart():
  # Add commands to perform before maintenance starts here.
  pass

def OnMaintenanceEnd():
  # Add commands to perform after maintenance is complete here.
  pass

if __name__ == '__main__':
  # Perform actions when maintenance events occur.
  HandleMaintenance(OnMaintenanceStart, OnMaintenanceEnd)

  # An example of watching for changes in a different metadata field.
  # Replace 'foo' with an existing custom metadata key of your choice.
  #
  # WatchMetadata('instance/attributes/foo',
  #               lambda val: sys.stdout.write('%s\n' % val))

Transition to v1

The v1 metadata server functions slightly differently that the previous v1beta1 server. Here are some of the changes that need to be made for the new metadata server:

  • Update metadata requests to include the Metadata-Flavor: Google header

    The new metadata server requires that all requests provide the Metadata-Flavor: Google header, which indicates that the request was made with the intention of retrieving metadata values, Update your requests to include this new header. For example, a request to the disks/ attribute now looks like the following:

    user@myinst:~$ curl "http://metadata.google.internal/computeMetadata/v1/instance/disks/" -H "Metadata-Flavor: Google"
    
  • Update requests that use the header X-Forwarded-For header

    These requests are automatically rejected by the server, as it generally indicates that the requests are proxied. Update your requests so they do not contain this header.