Class: Awsborn::Server
Constant Summary
AwsConstants::AVAILABILITY_ZONES, AwsConstants::INSTANCE_TYPES, AwsConstants::INSTANCE_TYPES_32_BIT, AwsConstants::INSTANCE_TYPES_64_BIT, AwsConstants::REGIONS, AwsConstants::SYMBOL_CONSTANT_MAP
Class Attribute Summary collapse
Class Method Summary
collapse
Instance Method Summary
collapse
#aws_constant, #aws_instance_type_to_symbol, #aws_zone_to_symbol, #endpoint_for_zone_and_service, #symbol_to_aws_instance_type, #symbol_to_aws_zone, #zone_to_aws_region
Constructor Details
#initialize(name, options = {}) ⇒ Server
Returns a new instance of Server.
5
6
7
8
9
|
# File 'lib/awsborn/server.rb', line 5
def initialize (name, options = {})
@name = name
@options = options.dup
self.host_name = elastic_ip
end
|
Class Attribute Details
.logger ⇒ Object
Returns the value of attribute logger.
12
13
14
|
# File 'lib/awsborn/server.rb', line 12
def logger
@logger
end
|
Class Method Details
.bootstrap_script(*args) ⇒ Object
55
56
57
58
|
# File 'lib/awsborn/server.rb', line 55
def bootstrap_script (*args)
@bootstrap_script = args.first unless args.empty?
get_class_attr(:bootstrap_script)
end
|
.cluster(name = ServerCluster.next_name, &block) ⇒ Object
.get_class_attr(class_attr) ⇒ Object
14
15
16
17
18
19
20
21
22
|
# File 'lib/awsborn/server.rb', line 14
def get_class_attr(class_attr)
if (class_var = instance_variable_get("@#{class_attr}"))
class_var
elsif self != ::Awsborn::Server
superclass.send(class_attr)
else
nil
end
end
|
.image_id(*args) ⇒ Object
Set image_id. Examples:
image_id 'ami-123123'
image_id 'ami-123123', :sudo_user => 'ubuntu'
image_id :i386 => 'ami-323232', :x64 => 'ami-646464', :sudo_user => 'ubuntu'
28
29
30
31
32
33
34
|
# File 'lib/awsborn/server.rb', line 28
def image_id (*args)
unless args.empty?
@image_id = args.first
@sudo_user = args.last[:sudo_user] if args.last.is_a?(Hash)
end
get_class_attr(:image_id)
end
|
.individual_security_group(*args) ⇒ Object
43
44
45
46
|
# File 'lib/awsborn/server.rb', line 43
def individual_security_group (*args)
@individual_security_group = args.first unless args.empty?
get_class_attr(:individual_security_group)
end
|
.instance_type(*args) ⇒ Object
35
36
37
38
|
# File 'lib/awsborn/server.rb', line 35
def instance_type (*args)
@instance_type = args.first unless args.empty?
get_class_attr(:instance_type)
end
|
.keys(*args) ⇒ Object
47
48
49
50
|
# File 'lib/awsborn/server.rb', line 47
def keys (*args)
@keys = args unless args.empty?
get_class_attr(:keys)
end
|
.monitor(*args) ⇒ Object
59
60
61
62
|
# File 'lib/awsborn/server.rb', line 59
def monitor (*args)
@monitor = args.first unless args.empty?
get_class_attr(:monitor)
end
|
.security_group(*args) ⇒ Object
39
40
41
42
|
# File 'lib/awsborn/server.rb', line 39
def security_group (*args)
@security_group = args unless args.empty?
get_class_attr(:security_group)
end
|
.sudo_user(*args) ⇒ Object
51
52
53
54
|
# File 'lib/awsborn/server.rb', line 51
def sudo_user (*args)
@sudo_user = args.first unless args.empty?
get_class_attr(:sudo_user)
end
|
Instance Method Details
#associate_address ⇒ Object
185
186
187
188
189
|
# File 'lib/awsborn/server.rb', line 185
def associate_address
logger.debug "Associating address #{elastic_ip} to #{name}"
ec2.associate_address(elastic_ip)
self.host_name = elastic_ip
end
|
#attach_volumes ⇒ Object
199
200
201
202
203
204
205
206
|
# File 'lib/awsborn/server.rb', line 199
def attach_volumes
logger.debug "Attaching volumes #{disk.values.join(', ')} to #{name}" unless disk.empty?
disk.each_pair do |device, str_or_ary|
volume = str_or_ary.is_a?(Array) ? str_or_ary.first : str_or_ary
device = "/dev/#{device}" if device.is_a?(Symbol) || ! device.match('/')
res = ec2.attach_volume(volume, device)
end
end
|
#bootstrap ⇒ Object
191
192
193
194
195
196
197
|
# File 'lib/awsborn/server.rb', line 191
def bootstrap
logger.debug "Bootstrapping #{name}"
script = bootstrap_script
basename = File.basename(script)
system "scp #{script} root@#{host_name}:/tmp"
system "ssh root@#{host_name} 'cd /tmp && chmod 700 #{basename} && ./#{basename}'"
end
|
#cook ⇒ Object
208
209
210
211
212
|
# File 'lib/awsborn/server.rb', line 208
def cook
raise "#{host_name} not running" unless running?
upload_cookbooks
run_chef
end
|
#copy_sudo_users_keys_to_root ⇒ Object
181
182
183
|
# File 'lib/awsborn/server.rb', line 181
def copy_sudo_users_keys_to_root
system("ssh #{sudo_user}@#{host_name} 'sudo cp .ssh/authorized_keys /root/.ssh/authorized_keys'")
end
|
#ec2 ⇒ Object
234
235
236
|
# File 'lib/awsborn/server.rb', line 234
def ec2
@ec2 ||= Ec2.new(zone)
end
|
#find_instance_id_by_name ⇒ Object
72
73
74
75
76
77
78
79
80
81
|
# File 'lib/awsborn/server.rb', line 72
def find_instance_id_by_name
instances = ec2.connection.describe_instances(
:filters => {'tag:Name' => full_name,
'instance-state-name' => ['pending', 'running']}
)
if instances.count > 1
raise ServerError, "Found multiple instances with full_name = #{full_name}."
end
instances.empty? ? nil : instances.first[:aws_instance_id]
end
|
#find_instance_id_by_volume ⇒ Object
83
84
85
86
87
88
89
90
91
|
# File 'lib/awsborn/server.rb', line 83
def find_instance_id_by_volume
map = {}
disk_volume_ids.each { |vol_id| map[vol_id] = ec2.instance_id_for_volume(vol_id) }
ids = map.values.uniq
if ids.size > 1
raise ServerError, "Volumes for #{self.class.name}:#{name} are connected to several instances: #{map.inspect}"
end
ids.first
end
|
#install_ssh_keys(temp_key_pair = nil) ⇒ Object
161
162
163
164
165
166
|
# File 'lib/awsborn/server.rb', line 161
def install_ssh_keys (temp_key_pair = nil)
logger.debug "Installing ssh keys on #{name}"
raise ArgumentError, "No host_name for #{name}" unless host_name
install_ssh_keys_for_sudo_user_or_root(temp_key_pair)
copy_sudo_users_keys_to_root if sudo_user
end
|
#install_ssh_keys_for_sudo_user_or_root(temp_key_pair) ⇒ Object
168
169
170
171
172
173
|
# File 'lib/awsborn/server.rb', line 168
def install_ssh_keys_for_sudo_user_or_root (temp_key_pair)
current_key = "-i #{temp_key_pair.path}" if temp_key_pair
IO.popen("ssh #{current_key} #{sudo_user || 'root'}@#{host_name} 'cat > .ssh/authorized_keys'", "w") do |pipe|
pipe.puts key_data
end
end
|
#key_data ⇒ Object
175
176
177
178
179
|
# File 'lib/awsborn/server.rb', line 175
def key_data
Dir[*keys].inject([]) do |memo, file_name|
memo + File.readlines(file_name).map { |line| line.chomp }
end.join("\n")
end
|
#launch_instance(key_pair) ⇒ Object
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
|
# File 'lib/awsborn/server.rb', line 140
def launch_instance (key_pair)
@launch_response = ec2.launch_instance(image_id,
:instance_type => symbol_to_aws_instance_type(instance_type),
:availability_zone => symbol_to_aws_zone(zone),
:key_name => key_pair.name,
:group_ids => security_group,
:monitoring_enabled => monitor,
:user_data => user_data
)
logger.debug @launch_response
ec2.set_instance_name full_name
Awsborn.wait_for("instance #{instance_id} (#{name}) to start", 10) { instance_running? }
self.host_name = aws_dns_name
end
|
#logger ⇒ Object
341
342
343
|
# File 'lib/awsborn/server.rb', line 341
def logger
@logger ||= self.class.logger
end
|
#refresh ⇒ Object
104
105
106
107
108
109
110
111
112
113
114
115
|
# File 'lib/awsborn/server.rb', line 104
def refresh
start_or_stop_monitoring unless monitor.nil?
associate_address if elastic_ip
begin
update_known_hosts
install_ssh_keys if keys
rescue SecurityError => e
logger.warn "Could not update known_hosts for #{name}:"
logger.warn e
end
end
|
#running? ⇒ Boolean
93
94
95
96
97
98
99
100
101
102
|
# File 'lib/awsborn/server.rb', line 93
def running?
name_id = find_instance_id_by_name
volume_id = find_instance_id_by_volume
if name_id && volume_id && name_id != volume_id
raise ServerError, "Volumes #{disk_volume_ids} are attached to #{volume_id}, not to instance #{name_id} with name #{full_name}"
else
ec2.instance_id = name_id || volume_id
end
end
|
#start(key_pair) ⇒ Object
125
126
127
128
129
130
131
132
133
134
135
136
137
138
|
# File 'lib/awsborn/server.rb', line 125
def start (key_pair)
launch_instance(key_pair)
update_known_hosts
install_ssh_keys(key_pair) if keys
if elastic_ip
associate_address
update_known_hosts
end
bootstrap if bootstrap_script
attach_volumes
end
|
#start_or_stop_monitoring ⇒ Object
117
118
119
120
121
122
123
|
# File 'lib/awsborn/server.rb', line 117
def start_or_stop_monitoring
if monitor && ! ec2.monitoring?
ec2.monitor
elsif ec2.monitoring? && ! monitor
ec2.unmonitor
end
end
|
#update_known_hosts ⇒ Object
#upload_cookbooks ⇒ Object
214
215
216
217
218
219
220
221
222
223
224
225
226
|
# File 'lib/awsborn/server.rb', line 214
def upload_cookbooks
logger.info "Uploading cookbooks to #{host_name}"
cookbooks_dir = '../cookbooks' temp_link = File.directory?(cookbooks_dir) && ! File.directory?('cookbooks')
File.symlink(cookbooks_dir, 'cookbooks') if temp_link
File.open("config/dna.json", "w") { |f| f.write(chef_dna.to_json) }
system "rsync -rL --chmod=o-rw -p --delete --exclude '.*' ./ root@#{host_name}:#{Awsborn.remote_chef_path}"
ensure
FileUtils.rm_f("config/dna.json")
File.delete("cookbooks") if temp_link
end
|