blob: 8d0fa5388f7b7505016236659b16f8c7cc93ea61 [file] [log] [blame]
#!/usr/bin/env python
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You 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.
# This example performs several tasks on Google Compute Engine and the GCE
# Load Balancer. It can be run directly or can be imported into an
# interactive python session. This can also serve as an integration test for
# the GCE Load Balancer Driver.
#
# To run interactively:
# - Make sure you have valid values in secrets.py
# (For more information about setting up your credentials, see the
# libcloud/common/google.py docstring)
# - Run 'python' in this directory, then:
# import gce_lb_demo
# gcelb = gce_lb_demo.get_gcelb_driver()
# gcelb.list_balancers()
# etc.
# - Or, to run the full demo from the interactive python shell:
# import gce_lb_demo
# gce_lb_demo.CLEANUP = False # optional
# gce_lb_demo.MAX_NODES = 4 # optional
# gce_lb_demo.DATACENTER = 'us-central1-a' # optional
# gce_lb_demo.main()
import os.path
import sys
import time
try:
import secrets
except ImportError:
print('"demos/secrets.py" not found.\n\n'
'Please copy secrets.py-dist to secrets.py and update the GCE* '
'values with appropriate authentication information.\n'
'Additional information about setting these values can be found '
'in the docstring for:\n'
'libcloud/common/google.py\n')
sys.exit(1)
# Add parent dir of this file's dir to sys.path (OS-agnostically)
sys.path.append(os.path.normpath(os.path.join(os.path.dirname(__file__),
os.path.pardir)))
from libcloud.utils.py3 import PY3
if PY3:
import urllib.request as url_req
else:
import urllib2 as url_req
# This demo uses both the Compute driver and the LoadBalancer driver
from libcloud.compute.types import Provider
from libcloud.compute.providers import get_driver
from libcloud.loadbalancer.types import Provider as Provider_lb
from libcloud.loadbalancer.providers import get_driver as get_driver_lb
# String that all resource names created by the demo will start with
# WARNING: Any resource that has a matching name will be destroyed.
DEMO_BASE_NAME = 'libcloud-lb-demo'
# Datacenter to create resources in
DATACENTER = 'us-central1-a'
# Clean up resources at the end (can be set to false in order to
# inspect resources at the end of the run). Resources will be cleaned
# at the beginning regardless.
CLEANUP = True
args = getattr(secrets, 'GCE_PARAMS', ())
kwargs = getattr(secrets, 'GCE_KEYWORD_PARAMS', {})
# Add datacenter to kwargs for Python 2.5 compatibility
kwargs = kwargs.copy()
kwargs['datacenter'] = DATACENTER
# ==== HELPER FUNCTIONS ====
def get_gce_driver():
driver = get_driver(Provider.GCE)(*args, **kwargs)
return driver
def get_gcelb_driver(gce_driver=None):
# The GCE Load Balancer driver uses the GCE Compute driver for all of its
# API calls. You can either provide the driver directly, or provide the
# same authentication information so the LB driver can get its own
# Compute driver.
if gce_driver:
driver = get_driver_lb(Provider_lb.GCE)(gce_driver=gce_driver)
else:
driver = get_driver_lb(Provider_lb.GCE)(*args, **kwargs)
return driver
def display(title, resource_list):
"""
Display a list of resources.
:param title: String to be printed at the heading of the list.
:type title: ``str``
:param resource_list: List of resources to display
:type resource_list: Any ``object`` with a C{name} attribute
"""
print('%s:' % title)
for item in resource_list[:10]:
print(' %s' % item.name)
def clean_up(gce, base_name, node_list=None, resource_list=None):
"""
Destroy all resources that have a name beginning with 'base_name'.
:param base_name: String with the first part of the name of resources
to destroy
:type base_name: ``str``
:keyword node_list: List of nodes to consider for deletion
:type node_list: ``list`` of :class:`Node`
:keyword resource_list: List of resources to consider for deletion
:type resource_list: ``list`` of I{Resource Objects}
"""
if node_list is None:
node_list = []
if resource_list is None:
resource_list = []
# Use ex_destroy_multiple_nodes to destroy nodes
del_nodes = []
for node in node_list:
if node.name.startswith(base_name):
del_nodes.append(node)
result = gce.ex_destroy_multiple_nodes(del_nodes)
for i, success in enumerate(result):
if success:
print(' Deleted %s' % del_nodes[i].name)
else:
print(' Failed to delete %s' % del_nodes[i].name)
# Destroy everything else with just the destroy method
for resource in resource_list:
if resource.name.startswith(base_name):
if resource.destroy():
print(' Deleted %s' % resource.name)
else:
print(' Failed to Delete %s' % resource.name)
# ==== DEMO CODE STARTS HERE ====
def main():
gce = get_gce_driver()
gcelb = get_gcelb_driver(gce)
# Existing Balancers
balancers = gcelb.list_balancers()
display('Load Balancers', balancers)
# Protocols
protocols = gcelb.list_protocols()
print('Protocols:')
for p in protocols:
print(' %s' % p)
# Healthchecks
healthchecks = gcelb.ex_list_healthchecks()
display('Health Checks', healthchecks)
# This demo is based on the GCE Load Balancing Quickstart described here:
# https://developers.google.com/compute/docs/load-balancing/lb-quickstart
# == Clean-up and existing demo resources ==
all_nodes = gce.list_nodes(ex_zone='all')
firewalls = gce.ex_list_firewalls()
print('Cleaning up any "%s" resources:' % DEMO_BASE_NAME)
clean_up(gce, DEMO_BASE_NAME, all_nodes,
balancers + healthchecks + firewalls)
# == Create 3 nodes to balance between ==
startup_script = ('apt-get -y update && '
'apt-get -y install apache2 && '
'hostname > /var/www/index.html')
tag = '%s-www' % DEMO_BASE_NAME
base_name = '%s-www' % DEMO_BASE_NAME
image = gce.ex_get_image('debian-7')
size = gce.ex_get_size('n1-standard-1')
number = 3
metadata = {'items': [{'key': 'startup-script',
'value': startup_script}]}
lb_nodes = gce.ex_create_multiple_nodes(base_name, size, image,
number, ex_tags=[tag],
ex_metadata=metadata,
ignore_errors=False)
display('Created Nodes', lb_nodes)
# == Create a Firewall for instances ==
print('Creating a Firewall:')
name = '%s-firewall' % DEMO_BASE_NAME
allowed = [{'IPProtocol': 'tcp',
'ports': ['80']}]
firewall = gce.ex_create_firewall(name, allowed, source_tags=[tag])
print(' Firewall %s created' % firewall.name)
# == Create a Health Check ==
print('Creating a HealthCheck:')
name = '%s-healthcheck' % DEMO_BASE_NAME
# These are all the default values, but listed here as an example. To
# create a healthcheck with the defaults, only name is required.
hc = gcelb.ex_create_healthcheck(name, host=None, path='/', port='80',
interval=5, timeout=5,
unhealthy_threshold=2,
healthy_threshold=2)
print(' Healthcheck %s created' % hc.name)
# == Create Load Balancer ==
print('Creating Load Balancer')
name = '%s-lb' % DEMO_BASE_NAME
port = 80
protocol = 'tcp'
algorithm = None
members = lb_nodes[:2] # Only attach the first two initially
healthchecks = [hc]
balancer = gcelb.create_balancer(name, port, protocol, algorithm, members,
ex_healthchecks=healthchecks)
print(' Load Balancer %s created' % balancer.name)
# == Attach third Node ==
print('Attaching additional node to Load Balancer:')
member = balancer.attach_compute_node(lb_nodes[2])
print(' Attached %s to %s' % (member.id, balancer.name))
# == Show Balancer Members ==
members = balancer.list_members()
print('Load Balancer Members:')
for member in members:
print(' ID: %s IP: %s' % (member.id, member.ip))
# == Remove a Member ==
print('Removing a Member:')
detached = members[0]
detach = balancer.detach_member(detached)
if detach:
print(' Member %s detached from %s' % (detached.id, balancer.name))
# == Show Updated Balancer Members ==
members = balancer.list_members()
print('Updated Load Balancer Members:')
for member in members:
print(' ID: %s IP: %s' % (member.id, member.ip))
# == Reattach Member ==
print('Reattaching Member:')
member = balancer.attach_member(detached)
print(' Member %s attached to %s' % (member.id, balancer.name))
# == Test Load Balancer by connecting to it multiple times ==
print('Sleeping for 10 seconds to stabilize the balancer...')
time.sleep(10)
rounds = 200
url = 'http://%s/' % balancer.ip
line_length = 75
print('Connecting to %s %s times:' % (url, rounds))
for x in range(rounds):
response = url_req.urlopen(url)
if PY3:
output = str(response.read(), encoding='utf-8').strip()
else:
output = response.read().strip()
if 'www-001' in output:
padded_output = output.center(line_length)
elif 'www-002' in output:
padded_output = output.rjust(line_length)
else:
padded_output = output.ljust(line_length)
sys.stdout.write('\r%s' % padded_output)
sys.stdout.flush()
print('')
if CLEANUP:
balancers = gcelb.list_balancers()
healthchecks = gcelb.ex_list_healthchecks()
nodes = gce.list_nodes(ex_zone='all')
firewalls = gce.ex_list_firewalls()
print('Cleaning up %s resources created.' % DEMO_BASE_NAME)
clean_up(gce, DEMO_BASE_NAME, nodes,
balancers + healthchecks + firewalls)
if __name__ == '__main__':
main()