Skip to content

Instantly share code, notes, and snippets.

@ericcholis
Forked from themartorana/build.py
Created December 28, 2012 14:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ericcholis/4398373 to your computer and use it in GitHub Desktop.
Save ericcholis/4398373 to your computer and use it in GitHub Desktop.
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