Skip to content

Instantly share code, notes, and snippets.

@omaciel
Last active December 23, 2015 15:28
Show Gist options
  • Save omaciel/6655310 to your computer and use it in GitHub Desktop.
Save omaciel/6655310 to your computer and use it in GitHub Desktop.
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