Class: Sumo
- Inherits:
-
Object
- Object
- Sumo
- Defined in:
- lib/sumo.rb
Instance Method Summary collapse
- #bootstrap_chef(hostname) ⇒ Object
- #config ⇒ Object
- #create_keypair ⇒ Object
- #create_security_group ⇒ Object
- #ec2 ⇒ Object
- #fetch_list ⇒ Object
- #fetch_resources(hostname) ⇒ Object
- #find(id_or_hostname) ⇒ Object
- #instance_info(instance_id) ⇒ Object
- #keypair_file ⇒ Object
- #launch ⇒ Object
- #list ⇒ Object
- #list_by_status(status) ⇒ Object
- #open_firewall(port) ⇒ Object
- #parse_resources(raw, hostname) ⇒ Object
- #pending ⇒ Object
- #read_config ⇒ Object
- #resources(hostname) ⇒ Object
- #running ⇒ Object
- #setup_role(hostname, role) ⇒ Object
- #ssh(hostname, cmds) ⇒ Object
- #sumo_dir ⇒ Object
- #terminate(instance_id) ⇒ Object
- #wait_for_hostname(instance_id) ⇒ Object
- #wait_for_ssh(hostname) ⇒ Object
Instance Method Details
#bootstrap_chef(hostname) ⇒ Object
98 99 100 101 102 103 104 105 106 107 108 |
# File 'lib/sumo.rb', line 98 def bootstrap_chef(hostname) commands = [ 'apt-get update', 'apt-get autoremove -y', 'apt-get install -y ruby ruby-dev rubygems git-core', 'gem sources -a http://gems.opscode.com', 'gem install chef ohai --no-rdoc --no-ri', "git clone #{config['cookbooks_url']}", ] ssh(hostname, commands) end |
#config ⇒ Object
149 150 151 |
# File 'lib/sumo.rb', line 149 def config @config ||= read_config end |
#create_keypair ⇒ Object
167 168 169 170 171 |
# File 'lib/sumo.rb', line 167 def create_keypair keypair = ec2.create_keypair(:key_name => "sumo").keyMaterial File.open(keypair_file, 'w') { |f| f.write keypair } File.chmod 0600, keypair_file end |
#create_security_group ⇒ Object
173 174 175 176 |
# File 'lib/sumo.rb', line 173 def create_security_group ec2.create_security_group(:group_name => 'sumo', :group_description => 'Sumo') rescue EC2::InvalidGroupDuplicate end |
#ec2 ⇒ Object
189 190 191 |
# File 'lib/sumo.rb', line 189 def ec2 @ec2 ||= EC2::Base.new(:access_key_id => config['access_id'], :secret_access_key => config['access_secret']) end |
#fetch_list ⇒ Object
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
# File 'lib/sumo.rb', line 28 def fetch_list result = ec2.describe_instances return [] unless result.reservationSet instances = [] result.reservationSet.item.each do |r| r.instancesSet.item.each do |item| instances << { :instance_id => item.instanceId, :status => item.instanceState.name, :hostname => item.dnsName } end end instances end |
#fetch_resources(hostname) ⇒ Object
132 133 134 135 136 137 |
# File 'lib/sumo.rb', line 132 def fetch_resources(hostname) cmd = "ssh -i #{keypair_file} root@#{hostname} 'cat /root/resources' 2>&1" out = IO.popen(cmd, 'r') { |pipe| pipe.read } abort "failed to read resources, output:\n#{out}" unless $?.success? parse_resources(out, hostname) end |
#find(id_or_hostname) ⇒ Object
45 46 47 48 49 50 51 52 53 |
# File 'lib/sumo.rb', line 45 def find(id_or_hostname) return unless id_or_hostname id_or_hostname = id_or_hostname.strip.downcase list.detect do |inst| inst[:hostname] == id_or_hostname or inst[:instance_id] == id_or_hostname or inst[:instance_id].gsub(/^i-/, '') == id_or_hostname end end |
#instance_info(instance_id) ⇒ Object
67 68 69 70 71 |
# File 'lib/sumo.rb', line 67 def instance_info(instance_id) fetch_list.detect do |inst| inst[:instance_id] == instance_id end end |
#keypair_file ⇒ Object
163 164 165 |
# File 'lib/sumo.rb', line 163 def keypair_file "#{sumo_dir}/keypair.pem" end |
#launch ⇒ Object
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
# File 'lib/sumo.rb', line 6 def launch ami = config['ami'] raise "No AMI selected" unless ami create_keypair unless File.exists? keypair_file create_security_group open_firewall(22) result = ec2.run_instances( :image_id => ami, :instance_type => config['instance_size'] || 'm1.small', :key_name => 'sumo', :group_id => [ 'sumo' ] ) result.instancesSet.item[0].instanceId end |
#list ⇒ Object
24 25 26 |
# File 'lib/sumo.rb', line 24 def list @list ||= fetch_list end |
#list_by_status(status) ⇒ Object
63 64 65 |
# File 'lib/sumo.rb', line 63 def list_by_status(status) list.select { |i| i[:status] == status } end |
#open_firewall(port) ⇒ Object
178 179 180 181 182 183 184 185 186 187 |
# File 'lib/sumo.rb', line 178 def open_firewall(port) ec2.( :group_name => 'sumo', :ip_protocol => 'tcp', :from_port => port, :to_port => port, :cidr_ip => '0.0.0.0/0' ) rescue EC2::InvalidPermissionDuplicate end |
#parse_resources(raw, hostname) ⇒ Object
139 140 141 142 143 |
# File 'lib/sumo.rb', line 139 def parse_resources(raw, hostname) raw.split("\n").map do |line| line.gsub(/localhost/, hostname) end end |
#pending ⇒ Object
59 60 61 |
# File 'lib/sumo.rb', line 59 def pending list_by_status('pending') end |
#read_config ⇒ Object
157 158 159 160 161 |
# File 'lib/sumo.rb', line 157 def read_config YAML.load File.read("#{sumo_dir}/config.yml") rescue Errno::ENOENT raise "Sumo is not configured, please fill in ~/.sumo/config.yml" end |
#resources(hostname) ⇒ Object
127 128 129 130 |
# File 'lib/sumo.rb', line 127 def resources(hostname) @resources ||= {} @resources[hostname] ||= fetch_resources(hostname) end |
#running ⇒ Object
55 56 57 |
# File 'lib/sumo.rb', line 55 def running list_by_status('running') end |
#setup_role(hostname, role) ⇒ Object
110 111 112 113 114 115 116 |
# File 'lib/sumo.rb', line 110 def setup_role(hostname, role) commands = [ "cd chef-cookbooks", "/var/lib/gems/1.8/bin/chef-solo -c config.json -j roles/#{role}.json" ] ssh(hostname, commands) end |
#ssh(hostname, cmds) ⇒ Object
118 119 120 121 122 123 124 125 |
# File 'lib/sumo.rb', line 118 def ssh(hostname, cmds) IO.popen("ssh -i #{keypair_file} root@#{hostname} > ~/.sumo/ssh.log 2>&1", "w") do |pipe| pipe.puts cmds.join(' && ') end unless $?.success? abort "failed\nCheck ~/.sumo/ssh.log for the output" end end |
#sumo_dir ⇒ Object
153 154 155 |
# File 'lib/sumo.rb', line 153 def sumo_dir "#{ENV['HOME']}/.sumo" end |
#terminate(instance_id) ⇒ Object
145 146 147 |
# File 'lib/sumo.rb', line 145 def terminate(instance_id) ec2.terminate_instances(:instance_id => [ instance_id ]) end |
#wait_for_hostname(instance_id) ⇒ Object
73 74 75 76 77 78 79 80 81 82 83 |
# File 'lib/sumo.rb', line 73 def wait_for_hostname(instance_id) raise ArgumentError unless instance_id and instance_id.match(/^i-/) loop do if inst = instance_info(instance_id) if hostname = inst[:hostname] return hostname end end sleep 1 end end |
#wait_for_ssh(hostname) ⇒ Object
85 86 87 88 89 90 91 92 93 94 95 96 |
# File 'lib/sumo.rb', line 85 def wait_for_ssh(hostname) raise ArgumentError unless hostname loop do begin Timeout::timeout(4) do TCPSocket.new(hostname, 22) return end rescue SocketError, Timeout::Error, Errno::ECONNREFUSED, Errno::EHOSTUNREACH end end end |