#!/usr/bin/env ruby $:.unshift File.expand_path(File.dirname(__FILE__)) $:.unshift File.expand_path(File.join(File.dirname(__FILE__), 'installer', 'utils')) require 'rubygems' require 'fog' require 'net/http' require 'constants' require 'readline' # METHODS # cmd # easily issue system commands in a clear way def cmd(cmd) puts cmd system(cmd) end #cmd # ssh_cmd # More easily issue commands over the ssh connection. def ssh_cmd(cmd) puts cmd puts @ssh.run(cmd)[0].stdout end #ssh_cmd # compile_stack_info # Fills in all necessary information which is stack specific def compile_stack_info # User is stack specific but not to # be included in the fog creation hash @user = @stack[:user] @stack.delete :user # This part of the package name will always be the same local_file = "#{`pwd`.strip}/pkg/" # Append the rest of the file name according to distribution if @user == 'ubuntu' @dist = { :flavor => "ubuntu", :package => "rhoconnect_#{Constants::RC_VERSION}_all.deb", :local_file => "#{local_file}rhoconnect_#{Constants::RC_VERSION}_all.deb", :pkg_mgr => 'dpkg', :pkg_type => 'DEB', :pkg_repo => 'apt-get', :deps => Constants::DEB_DEPS, :repo_src_file => '/etc/apt/sources.list', :repo_str => '\n' + '# This is the repository for rhoconnect packages\n' + 'deb http://rhoconnect.s3.amazonaws.com/packages/deb rhoconnect main' } elsif @user == 'root' @dist = { :flavor => "centos", :package => "rhoconnect-#{Constants::RC_VERSION}.noarch.rpm", :local_file => "#{local_file}rhoconnect-#{Constants::RC_VERSION}.noarch.rpm", :pkg_mgr => 'rpm', :pkg_type => 'RPM', :pkg_repo => 'yum', :deps => Constants::RPM_DEPS, :repo_src_file => '/etc/yum.repos.d/rhoconnect.repo', :repo_str => '[rhoconnect]\n' + 'name=Rhoconnect\n' + 'baseurl=http://rhoconnect.s3.amazonaws.com/packages/rpm\n' + 'enabled=1\n' + 'gpgcheck=0\n' } else puts "Incorrect user name" exit 3 end #i end #compile_stack_info # create_ec2_instance # Generates the Fog object and creates a new ec2 instance. def create_ec2_instance make_fog start_new_instance end #create_ec2_instance # get_access_keys # Retrieves the access key and secret access key from the above specified file. def get_access_keys lines = IO.readlines Constants::ACCESS_KEY_FILE @access_key = lines.first.strip.split("=")[1] @secret_access_key = lines.last.strip.split("=")[1] end #get_access_keys # make_fog # Generates the Fog object used to create the new ec2 instance. def make_fog get_access_keys @fog = Fog::Compute.new( :provider => 'AWS', :region => Constants::REGION, :aws_access_key_id => @access_key, :aws_secret_access_key => @secret_access_key ) end #make_fog # start_new_instance # Creates a new ec2 instance as per the given stack. def start_new_instance puts "Creating new instance..." @server = @fog.servers.create(@stack) @server.wait_for { print "."; STDOUT.flush; ready? } puts if @server.ready? # wait for all services to start on remote VM puts "Waiting #{Constants::SLEEP} seconds for services to start on remote VM..." Constants::SLEEP.times do sleep 1 print "." STDOUT.flush end #do puts # save important instance information @host = @server.dns_name @server_id = @server.id else puts "Server timed out." exit 7 end #if end #start_new_instance # establish_ssh_connection # Establishes the ssh connection needed to issue commands to the remote machine. def establish_ssh_connection @ssh = Fog::SSH.new( @host, @user, :keys => Constants::SSH_KEY ) end #establish_ssh_connection # destroy_ec2_instance # Terminates the current ec2 instance def destroy_ec2_instance @server.destroy puts "Terminating Instance." end #destroy_ec2_instance # prepare_sources # Prepares the remote machine's repo source list to be able to download rhoconnect def prepare_sources puts "preparing sources..." ssh_cmd "sudo touch #{@dist[:repo_src_file]}" if @dist[:flavor] == 'centos' filename = @dist[:repo_src_file] src_str = @dist[:repo_str] # Create file for yum rhoconnect sources # Get current permissions of file perms = @ssh.run("stat --format=%a #{filename}")[0].stdout.strip # Change permissions so that it can be edited by "others" ssh_cmd "sudo chmod 0666 #{filename}" ssh_cmd "echo -e \"#{src_str}\" >> #{filename}" ssh_cmd "sudo chmod 0#{perms} #{filename}" cat_src = @ssh.run("cat #{@dist[:repo_src_file]}")[0].stdout.strip ssh_cmd "sudo #{@dist[:pkg_repo]} update" unless @dist[:flavor] == "centos" end #prepare_sources # install_package # Issues commands to the remote machine to start the installation def install_package prepare_sources puts "Installing rhoconnect package.\n" + "This may take a while...\n\n" ssh_cmd "yes | sudo #{@dist[:pkg_repo]} install rhoconnect" end #install_package # start_servers # Attempts to start redis and nginx servers def start_servers puts "Waiting #{Constants::SLEEP} seconds for services to initialize." Constants::SLEEP.times do |sec| print '.' STDOUT.flush sleep 1 end #do puts attempts = 0 while @ssh.run("pgrep redis")[0].stdout.strip == "" ssh_cmd "sudo /etc/init.d/redis start" attempts += 1 sleep 1 end #while puts "Redis start took #{attempts} attempts" puts attempts = 0 while @ssh.run("pgrep nginx")[0].stdout.strip == "" ssh_cmd "sudo /etc/init.d/nginx start" attempts += 1 sleep 1 end #while puts "Nginx start took #{attempts} attempts." puts end # start_servers # chack_rc_service # Makes an HTTP request to check that the rhoconnect service is working def check_rc_service request = Net::HTTP.get_response(@host, '/console') puts "Host: #{@host}" puts "Code: #{request.code} Message: #{request.message}" if request.code == '200' puts "Rhoconnect service up!" else puts "Failed to connect to rhoconnect service." exit 13 end #if end #check_rc_service # compute_time # General time computation method def compute_time(start_time, end_time) time_delta = (end_time - start_time) if time_delta >= 60 time_delta /= 60 time_units = 'minute' if time_delta > 1 time_units << 's' end #if else time_units = 'seconds' end #if "\nTest completed in #{time_delta} #{time_units}\n" end #compute_time # SCRIPT # Test Package installations Constants::STACKS.each do |stack| start_time = Time.now begin @stack = stack compile_stack_info puts "\n" + "================================================\n" + "Now starting test of #{@dist[:pkg_type]} package\n" + "================================================\n" + "\n\n" create_ec2_instance # Establish connections establish_ssh_connection @dist[:remote_home] = @ssh.run("echo ~")[0].stdout.strip install_package # Start the redis and nginx servers on the remote machine start_servers # Check the status of the rhoconnect service check_rc_service end_time = Time.now puts compute_time(start_time, end_time) rescue => e puts "OH NOEZ, Exception!!" puts e.inspect puts e.backtrace exit 15 ensure if @server != nil destroy_ec2_instance end #if end #begin end #do