Last active
December 23, 2015 15:28
-
-
Save omaciel/6655310 to your computer and use it in GitHub Desktop.
This file contains 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 argparse | |
import boto.ec2 | |
import os | |
import paramiko | |
import sys | |
import tempfile | |
import time | |
from urllib import urlopen | |
REQUEST_DELAY = 10 | |
MAX_ATTEMPTS = 30 | |
def wait_for_instance(instance): | |
"Waits for an instance to be running." | |
print "Reserving instance." | |
for i in range(MAX_ATTEMPTS): | |
if instance.state == 'running': | |
break | |
else: | |
print "." | |
time.sleep(REQUEST_DELAY) | |
instance.update() | |
else: | |
print 'Failed to launch EC2 instance. Exiting.' | |
sys.exit(-1) | |
return instance | |
def upload_file(ssh_client, filename, remote_filename): | |
"Uploads file to a remote server" | |
try: | |
ftp = ssh_client.open_sftp() | |
print "Uploading file." | |
ftp.put(filename, remote_filename) | |
ftp.close() | |
print "File uploaded to remote server." | |
except Exception, e: | |
print 'Failed to upload file. Exiting' | |
print str(e) | |
sys.exit(-1) | |
def download_iso(url): | |
"Downloads an ISO installer image." | |
iso_img = urlopen(url) | |
(fd, filename) = tempfile.mkstemp() | |
f = os.fdopen(fd, 'w') | |
print "Downloading ISO" | |
for line in iso_img.readlines(): | |
print "." | |
f.write(line) | |
f.close() | |
return filename | |
def reserve_client(conn, img_id, security_groups, key_name, instance_type='t1.micro', disk_size=7, tag=None): | |
dev_sda1 = boto.ec2.blockdevicemapping.BlockDeviceType() | |
dev_sda1.size = disk_size | |
bdm = boto.ec2.blockdevicemapping.BlockDeviceMapping() | |
bdm['/dev/sda1'] = dev_sda1 | |
reservation = conn.run_instances( | |
image_id=img_id, | |
security_groups=[security_groups], | |
key_name=key_name, | |
instance_type=instance_type, | |
block_device_map=bdm, | |
) | |
instance = wait_for_instance(reservation.instances[0]) | |
# Name the instance | |
if tag: | |
instance.add_tag("Name", tag) | |
instance.update() | |
return instance | |
def run_command(ssh_client, cmd, bufsize=-1, get_pty=True, timeout=10): | |
status = None | |
stdin, stdout, stderr = ssh_client.exec_command(cmd, bufsize, get_pty=get_pty) | |
for i in range(timeout): | |
if stdout.channel.exit_status_ready(): | |
status = stdout.channel.recv_exit_status() | |
break | |
time.sleep(1) | |
cmd_stdout = stdout.readlines() | |
cmd_stderr = stderr.readlines() | |
stdin.close() | |
stdout.close() | |
stderr.close() | |
return (status, cmd_stdout, cmd_stderr) | |
def terminate_instance(instance): | |
instance.terminate() | |
def get_ec2_connection(region='us-east-1', aws_access_key_id=None, aws_secret_access_key=None): | |
if aws_access_key_id is None or aws_secret_access_key is None: | |
conn = boto.ec2.connect_to_region(region) | |
else: | |
conn = boto.ec2.connect_to_region(region, aws_access_key_id=aws_access_key_id, aws_secret_access_key=aws_secret_access_key) | |
return conn | |
def get_ssh_client(hostname, username='root', key_filename=None, timeout=10): | |
if key_filename is None: | |
key_filename = os.path.abspath(os.path.expanduser('~/.ssh/id_rsa')) | |
ssh_client = paramiko.SSHClient() | |
ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) | |
for i in range(MAX_ATTEMPTS): | |
try: | |
ssh_client.connect(hostname=hostname, | |
username=username, | |
key_filename=key_filename, | |
timeout=timeout) | |
break | |
except Exception, e: | |
print "Cannot reach instance yet; re-trying..." | |
time.sleep(REQUEST_DELAY) | |
continue | |
else: | |
print "Failed to connect to EC2 client. Exiting." | |
sys.exit(-1) | |
return ssh_client | |
def register_instance(ssh_client, username, password, autosubscribe=True, product_name=None): | |
print 'Registering instance' | |
cmd = 'sudo subscription-manager register --force --username=%s --password=%s' % (username, password) | |
if autosubscribe: | |
cmd += " --autosubscribe" | |
(status, out, err) = run_command(ssh_client, cmd) | |
if product_name: | |
(status, out, err) = run_command(ssh_client, 'sudo subscription-manager repos --list') | |
(status, out, err) = run_command(ssh_client, 'sudo yum-config-manager --enable %s' % product_name) | |
print "".join(out) | |
# Remove un-wanted repos | |
if product_name == 'rhel-6-server-rpms': | |
for prod in ['\*for-rhel\*', '\*cf-tools\*', '\*rhev\*', '\*rhui\*']: | |
(status, out, err) = run_command(ssh_client, 'sudo yum-config-manager --disable %s' % prod) | |
print "".join(out) | |
def fix_iptables(ssh_client): | |
print "Fixing iptables" | |
cmd = 'sudo lokkit --update --port 80:tcp --port 443:tcp --port 8088:tcp --port 5671:tcp --port 22:tcp' | |
(status, out, err) = run_command(ssh_client, cmd) | |
def mount_iso(ssh_client, dir_name='ISO'): | |
print "Mounting ISO image" | |
(status, out, err) = run_command(ssh_client, 'mkdir %s' % dir_name) | |
(status, out, err) = run_command(ssh_client, 'sudo mount -t iso9660 -o loop *.iso %s' % dir_name) | |
def install_packages(ssh_client, dir_name='ISO', nogpgsigs=False): | |
print "Installing packages" | |
cmd = 'cd %s && sudo ./install_packages' % dir_name | |
if nogpgsigs: | |
cmd += " --nogpgsigs" | |
print cmd | |
(status, out, err) = run_command(ssh_client, cmd) | |
print "".join(out) | |
def fix_hostname(ssh_client, instance): | |
print "Fixing the hostname" | |
instance_ip = instance.dns_name.split('.')[0][4:].replace('-','.') | |
cmd1 = 'sudo sed -i -e "s/^::1.*/%s %s/" /etc/hosts' % (instance_ip, instance.dns_name) | |
cmd2 = 'sudo hostname %s' % instance.dns_name | |
(status, out, err) = run_command(ssh_client, cmd1) | |
(status, out, err) = run_command(ssh_client, cmd2) | |
def katello_configure(ssh_client, instance, deployment='katello', password='admin'): | |
print "Running the configuration script" | |
cmd = 'sudo katello-configure --deployment=%s --user-pass=%s' % (deployment, password) | |
(status, out, err) = run_command(ssh_client, cmd) | |
print "".join(out) | |
print "Server can be reached at https://%s/%s" % (instance.dns_name, deployment) | |
def install_product(ssh_client, instance, iso_url, rhn_user, rhn_password, deployment, subscription): | |
print "Downloading ISO image locally..." | |
iso_img = download_iso(iso_url) | |
print "Uploading ISO image..." | |
upload_file(ssh_client, iso_img, '%s.iso' % deployment) | |
register_instance(ssh_client, rhn_user, rhn_password, True, subscription) | |
fix_iptables(ssh_client) | |
mount_iso(ssh_client) | |
install_packages(ssh_client, nogpgsigs=True) | |
fix_hostname(ssh_client, instance) | |
katello_configure(ssh_client, instance, deployment) | |
if __name__ == '__main__': | |
DEPLOYMENT = [ | |
'katello', | |
'sam', | |
] | |
IMAGE_TYPES = [ | |
't1.micro', | |
'm1.small', | |
'm1.medium', | |
'm1.large', | |
'm1.xlarge', | |
'm3.xlarge', | |
'm3.2xlarge', | |
'c1.medium', | |
'c1.xlarge', | |
'cc2.8xlarge', | |
'm2.xlarge', | |
'm2.2xlarge', | |
'm2.4xlarge', | |
'cr1.8xlarge', | |
'hi1.4xlarge', | |
'hs1.8xlarge', | |
'cg1.4xlarge', | |
] | |
parser = argparse.ArgumentParser() | |
parser.add_argument('--region', type=str, default='us-east-1', dest='region') | |
parser.add_argument('-u', '--aws_access_key_id', type=str, dest='aws_id') | |
parser.add_argument('-p', '--aws_secret_access_key', type=str, dest='aws_key') | |
parser.add_argument('--ami-id', type=str, dest='ami_id') | |
parser.add_argument('--name', type=str, dest='name') | |
parser.add_argument('--image-type', type=str, choices=IMAGE_TYPES, dest='image_type') | |
parser.add_argument('--disk-size', type=int, default=7, dest='disk_size') | |
parser.add_argument('--security-group', type=str, dest='security_group') | |
parser.add_argument('--key-name', type=str, dest='key_name') | |
parser.add_argument('--instance-user', type=str, default='ec2-user', dest='instance_user') | |
parser.add_argument('--rhn-user-name', type=str, dest='rhn_user_name') | |
parser.add_argument('--rhn-user-password', type=str, dest='rhn_user_password') | |
parser.add_argument('--subscription-name', type=str, dest='subscription_name') | |
parser.add_argument('--iso-url', type=str, dest='iso_url') | |
parser.add_argument('--deployment', type=str, choices=DEPLOYMENT) | |
[options, ignored_options] = parser.parse_known_args() | |
#TODO: Add options validation | |
conn = get_ec2_connection(options.region, options.aws_id, options.aws_key) | |
instance = reserve_client(conn, options.ami_id, options.security_group, options.key_name, options.image_type, options.disk_size, options.name) | |
ssh_client = get_ssh_client(instance.dns_name, options.instance_user) | |
install_product(ssh_client, instance, options.iso_url, options.rhn_user_name, options.rhn_user_password, options.deployment, options.subscription_name) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment