Created
May 17, 2011 15:54
-
-
Save themartorana/976729 to your computer and use it in GitHub Desktop.
build.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import os, sys | |
import datetime | |
import base64 | |
import cloudservers | |
import cloudlb | |
import urllib2 | |
#import paramiko | |
from time import sleep | |
from conf import settings | |
PGSQL_DATABASE_SERVER_ADDRESS = '10.XXX.XXX.XXX' | |
def get_server_image(cs, image_name): | |
i = cs.images.find(name=image_name) | |
return i | |
def get_flavor(cs, ram_size): | |
return cs.flavors.find(ram=ram_size) | |
def get_file_contents(file_name): | |
contents = open(file_name, 'r').read() | |
return contents | |
def create_server(cs, image_name, ram_size): | |
now = datetime.datetime.now() | |
server_name = 'HAE-%s' % (now.strftime('%Y%m%d-%H%M%S')) | |
print 'Creating server %s' % server_name | |
image = get_server_image(cs, image_name) | |
if not image: | |
raise Exception('Could not get server image "%s"' % image_name) | |
flavor = get_flavor(cs, ram_size) | |
if not flavor: | |
raise Exception('Could not get flavor with %s ram' % ram_size) | |
server = cs.servers.create( | |
server_name, | |
image, | |
flavor, | |
files={ | |
'/etc/rc.local': get_file_contents('build/etc/rc.local'), | |
'/etc/rc.local.stage1': get_file_contents('build/etc/rc.local.stage1'), | |
'/etc/cron.d/initialrunner': get_file_contents('build/etc/cron.d/initialrunner'), | |
} | |
) | |
return server | |
def wait_for_server(cs, s, with_url_ping=False): | |
while s.status != 'ACTIVE': | |
sleep(10) | |
s = cs.servers.get(s.id) | |
print '%s: %s (%s%%)' % (s.id, s.status, s.progress) | |
if with_url_ping: | |
# Wait for a response | |
url = 'http://%s/content/images/logo.png' % s.public_ip | |
tries = 0 | |
while True: | |
try: | |
print 'Attempting to connect to %s' % url | |
urllib2.urlopen(url) | |
print 'ping success, returning' | |
break | |
except urllib2.HTTPError, e: | |
print e | |
if e.code == 401: | |
print '401 not authorized' | |
elif e.code == 404: | |
print '404 not found... waiting...' | |
elif e.code == 503: | |
print '503 service unavailable' | |
else: | |
print 'unknown error: %s' % e | |
sleep(30) | |
except urllib2.URLError, u: | |
print u | |
print 'Connection refused for now...' | |
sleep(30) | |
tries += 1 | |
if tries > 20: # 10 minutes | |
raise Exception('URL ping timed out') | |
def replace_servers(clb, cs, new_servers): | |
virtual_ip = None | |
virtual_ip_new = False | |
existing_load_balancers = clb.loadbalancers.list() | |
# New nodes | |
new_http_nodes = [cloudlb.Node(address=server.private_ip, port=80, condition="ENABLED") for server in new_servers] | |
new_https_nodes = [cloudlb.Node(address=server.private_ip, port=443, condition="ENABLED") for server in new_servers] | |
if len(existing_load_balancers) == 0: | |
print 'No load balancers, adding them' | |
virtual_ip = cloudlb.VirtualIP(type='PUBLIC') | |
virtual_ip_new = True | |
print 'Creating HTTP load balancer' | |
lb = clb.loadbalancers.create( | |
name='hae-web-http', | |
port=80, | |
protocol='HTTP', | |
nodes=new_http_nodes, | |
virtualIps=[virtual_ip] | |
) | |
if virtual_ip_new: | |
virtual_ip = lb.virtual_ips()[0] | |
print 'Virtual IP: %s' % virtual_ip | |
print 'Creating HTTPS load balancer' | |
lb = clb.loadbalancers.create( | |
name='hae-web-https', | |
port=443, | |
protocol='HTTPS', | |
nodes=new_https_nodes, | |
virtualIps=[virtual_ip] | |
) | |
else: | |
print 'Load balancers exist, adding/removing servers' | |
# Replace servers where necessary | |
http_lb = clb.loadbalancers.find(name='hae-web-http') | |
https_lb = clb.loadbalancers.find(name='hae-web-https') | |
existing_http_nodes = http_lb.nodes | |
existing_https_nodes = https_lb.nodes | |
if not http_lb or not https_lb: | |
raise Exception("Cannot find both the http and https load balancers!") | |
print '\nSwitching out HTTP servers' | |
print 'Adding nodes %s' % new_http_nodes | |
http_lb.add_nodes(new_http_nodes) | |
print '\nSwitching out HTTP servers' | |
print 'Adding nodes %s' % new_https_nodes | |
https_lb.add_nodes(new_https_nodes) | |
print 'Sleeping to allow the load balancers time to stat' | |
sleep(20) | |
print 'Deleting old nodes' | |
for node in existing_http_nodes: | |
print 'Deleting http node %s' % node | |
node.delete() | |
for node in existing_https_nodes: | |
print 'Deleting https node %s' % node | |
node.delete() | |
print 'Deleting old servers' | |
for node in existing_http_nodes: | |
server = cs.servers.find(private_ip=node.address) | |
server.delete() | |
if __name__ == '__main__': | |
cs = cloudservers.CloudServers(settings.CLOUDSERVERS_USERNAME, settings.CLOUDSERVERS_API_KEY) | |
s = create_server(cs, 'Ubuntu 10.10 (maverick)', 512) | |
wait_for_server(cs, s, with_url_ping=False) | |
print 'Server IP is %s (private: %s)' % (s.public_ip, s.private_ip) | |
sleep(20) | |
s.update(password='YOUR_PASSWORD_HERE') | |
try: | |
wait_for_server(cs, s, with_url_ping=True) | |
except: | |
# Kill the server | |
s.delete() | |
raise Exception('Server never finished') | |
if s: | |
clb = cloudlb.CloudLoadBalancer( | |
settings.CLOUDSERVERS_USERNAME, | |
settings.CLOUDSERVERS_API_KEY, | |
settings.CLOUDSERVERS_DATA_CENTER | |
) | |
replace_servers(clb, cs, [s]) | |
print 'Exiting with 0' | |
sys.exit(0) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Found this from your blog post. Thanks, I'm defiantly going to rip the Cloud Load Balancer sections.