From 17fc42e50af0b24757c442c38c14b946565d7721 Mon Sep 17 00:00:00 2001 From: Jon Wayne Parrott Date: Thu, 21 Apr 2016 10:55:55 -0700 Subject: [PATCH] Adding metadata sample Change-Id: I9876e6badd5dfda2c142b153a9ec1c54ca5d4a79 --- compute/metadata/README.md | 6 +++ compute/metadata/main.py | 79 +++++++++++++++++++++++++++++++ compute/metadata/main_test.py | 43 +++++++++++++++++ compute/metadata/requirements.txt | 1 + 4 files changed, 129 insertions(+) create mode 100644 compute/metadata/README.md create mode 100644 compute/metadata/main.py create mode 100644 compute/metadata/main_test.py create mode 100644 compute/metadata/requirements.txt diff --git a/compute/metadata/README.md b/compute/metadata/README.md new file mode 100644 index 000000000000..4ecf64f83b26 --- /dev/null +++ b/compute/metadata/README.md @@ -0,0 +1,6 @@ +# Compute Engine Metadata Samples + +These samples demonstrate interacting with the Compute Engine metadata service. These samples must be run on Compute Engine. + + + diff --git a/compute/metadata/main.py b/compute/metadata/main.py new file mode 100644 index 000000000000..9791139a0924 --- /dev/null +++ b/compute/metadata/main.py @@ -0,0 +1,79 @@ +#!/usr/bin/env python + +# Copyright 2016 Google Inc. All Rights Reserved. +# +# 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 watch for maintenance notices. + +For more information, see the README.md under /compute. +""" + +# [START all] + +import time + +import requests + + +METADATA_URL = "http://metadata.google.internal/computeMetadata/v1/" +METADATA_HEADERS = {'Metadata-Flavor': 'Google'} + + +def wait_for_maintenance(callback): + url = METADATA_URL + 'instance/maintenance-event' + last_in_maintenance = False + # [START hanging_get] + last_etag = 0 + + while True: + r = requests.get( + url, + params={'last_etag': last_etag}, + headers=METADATA_HEADERS) + + print(r) + + # During maintenance the service can return a 503, so these should + # be retried. + if r.status_code == 503: + time.sleep(1) + continue + # [END hanging_get] + + last_etag = r.headers['etag'] + + if r.text == 'MIGRATE_ON_HOST_MAINTENANCE': + in_maintenance = True + else: + in_maintenance = False + + if in_maintenance != last_in_maintenance: + last_in_maintenance = in_maintenance + callback(in_maintenance) + + +def maintenance_callback(status): + if status: + print('Undergoing host maintenance') + else: + print('Finished host maintenance') + + +def main(): + wait_for_maintenance(maintenance_callback) + + +if __name__ == '__main__': + main() +# [END all] diff --git a/compute/metadata/main_test.py b/compute/metadata/main_test.py new file mode 100644 index 000000000000..3e030d91dd75 --- /dev/null +++ b/compute/metadata/main_test.py @@ -0,0 +1,43 @@ +# Copyright 2016, 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. + +import main +import mock + + +@mock.patch('main.requests') +def test_wait_for_maintenance(requests_mock): + # Response 1 is a host maintenance event. + response1_mock = mock.Mock() + response1_mock.status_code = 200 + response1_mock.text = 'MIGRATE_ON_HOST_MAINTENANCE' + response1_mock.headers = {'etag': 1} + # Response 2 is the end of the event. + response2_mock = mock.Mock() + response2_mock.status_code = 200 + response2_mock.text = 'NONE' + response2_mock.headers = {'etag': 2} + # Response 3 is a 503 + response3_mock = mock.Mock() + response3_mock.status_code = 503 + + requests_mock.get.side_effect = [ + response1_mock, response2_mock, response3_mock, response2_mock, + StopIteration()] + + callback_mock = mock.Mock() + + try: + main.wait_for_maintenance(callback_mock) + except StopIteration: + pass diff --git a/compute/metadata/requirements.txt b/compute/metadata/requirements.txt new file mode 100644 index 000000000000..ca0dee4830d5 --- /dev/null +++ b/compute/metadata/requirements.txt @@ -0,0 +1 @@ +requests==2.9.1