Skip to content

Instantly share code, notes, and snippets.

@clayrichardson
Created March 21, 2012 20:55
Show Gist options
  • Save clayrichardson/2152768 to your computer and use it in GitHub Desktop.
Save clayrichardson/2152768 to your computer and use it in GitHub Desktop.
Create and tag Cassandra cluster on RightScale
import sys, urllib, httplib2, base64, json, re, time, paramiko
from operator import itemgetter
import pprint
headers = {}
cookie = ''
url_tail = '?api_version=1.0&format=js'
def create_url(method=None):
base_url = 'https://my.rightscale.com/api/acct/%s/' % account_id
return base_url + method + url_tail
def login(username=None, password=None, account_id=None):
base64string = base64.encodestring('%s:%s' % (username, password))[:-1]
headers['Authorization'] = "Basic %s" % base64string
response, content = api_request(create_url(method='login'), headers=headers)
headers['Cookie'] = response['set-cookie']
def rightscale_request(method=None):
http_request = httplib2.Http()
return api_request(create_url(method=method), headers=headers)
def api_request(url=None, method='GET', body=None, headers=headers):
http_request = httplib2.Http()
print "Getting URL: ", url
return http_request.request(uri=url, method=method, headers=headers, body=body)
def get_array_servers(array_id):
request_url = 'https://my.rightscale.com/api/acct/%s/server_arrays/%s/instances' % (account_id, array_id)
response, content = api_request(request_url + url_tail)
print 'Response: ', response
return json.loads(content)
def get_array_nickname(array_id):
request_url = 'https://my.rightscale.com/api/acct/%s/server_arrays/%s' % (account_id, array_id)
response, content = api_request(request_url + url_tail)
return json.loads(content)['nickname']
def add_servers_to_array(number_of_servers, array_id):
array_launch_url = 'https://my.rightscale.com/api/acct/%s/server_arrays/%s/launch' % (account_id, array_id)
for i in range(number_of_servers):
response, content = api_request(url=array_launch_url + url_tail, method='POST')
print 'Response: ', response
print 'Content: ', content
if __name__ == '__main__':
import rs_config
### you need to make an rs_config file
### that contains the following information
user = rs_config.user
password = rs_config.password
account_id = rs_config.account_id
array_id = rs_config.array_id
key_filename = rs_config.key_filename
cassandra_arrays = []
cassandra_hrefs = []
login(user, password, account_id)
cassandra_re = re.compile('cassandra', re.I)
response, content = rightscale_request('server_arrays')
server_arrays = json.loads(content)
for server_array in server_arrays:
if re.search(cassandra_re, server_array['nickname']):
cassandra_arrays.append(server_array)
pprint.pprint(cassandra_arrays)
for cassandra_array in cassandra_arrays:
cassandra_hrefs.append(cassandra_array['href'])
# uncomment to launch new instances
# add_servers_to_array(5, array_id)
cassandra_instances = get_array_servers(array_id)
cluster_operational_flag = False
cluster_stranded_flag = False
sorted_instances = sorted(cassandra_instances, key=itemgetter('nickname'))
while not cluster_operational_flag:
without_internal = []
without_external = []
pending = []
booting = []
operational = []
cluster_operational_flag = True
cluster_details = {}
for instance in sorted_instances:
cluster_details[instance['nickname']] = [
instance['ip_address'],
instance['private_ip_address'],
instance['state'],
]
if instance['ip_address'] == None:
cluster_operational_flag = False
without_external.append(instance)
if instance['private_ip_address'] == None:
cluster_operational_flag = False
without_internal.append(instance)
if instance['state'] == 'pending':
pending.append(instance)
if instance['state'] == 'booting':
booting.append(instance)
if instance['state'] == 'operational':
operational.append(instance)
if instance['state'] != 'operational':
cluster_operational_flag = False
if instance['state'] == 'stranded':
cluster_operational_flag = False
cluster_stranded_flag = True
print "CLUSTER STRANDED!"
exit()
pprint.pprint(cluster_details)
print "%s instances in cluster: %s pending, %s booting, %s without internal ip, %s without external ip, %s operational" % (len(sorted_instances), len(pending), len(booting), len(without_internal), len(without_external), len(operational))
if not cluster_operational_flag:
print "cluster not ready yet, sleeping 5 seconds before checking again",
for i in range(5):
sys.stdout.write('.')
time.sleep(1)
sys.stdout.write('\n')
sys.stdout.flush()
cassandra_instances = get_array_servers(array_id)
sorted_instances = sorted(cassandra_instances, key=itemgetter('nickname'))
print "cluster ready to tag shit!"
cassandra_instances = get_array_servers(array_id)
array_nickname = get_array_nickname(array_id)
sorted_instances = sorted(cassandra_instances, key=itemgetter('nickname'), reverse=True)
# because rightscale doesn't support running
# rightscripts on individual servers in an array,
# we need to ssh into each one to tag them with
# their node numbers
instance_number = 0
for instance in sorted_instances:
pprint.pprint(instance)
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(instance['ip_address'], username='root', key_filename=key_filename)
commands = [
'rs_tag -a "ip:internal=%s"' % instance['private_ip_address'],
'rs_tag -a "ip:external=%s"' % instance['ip_address'],
'rs_tag -a "cassandra:node=%s"' % instance_number,
'rs_tag -a "cassandra:cluster=%s"' % array_nickname,
]
for command in commands:
stdin, stdout, stderr = ssh.exec_command(command)
print stdout.readlines()
ssh.close()
instance_number = instance_number + 1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment