cluster 0.5.33

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,270 @@
1
+ class AmazonInstance < Instance
2
+ attr_accessor :ssh_key_name,
3
+ :private_dns_name,
4
+ :dns_name,
5
+ :aws_image_id,
6
+ :spot_price,
7
+ :aws_groups,
8
+ :aws_availability_zone,
9
+ :aws_state,
10
+ :aws_launch_time,
11
+ :start_time_sorted,
12
+ :aws_id,
13
+ :aws_instance_id,
14
+ :aws_image_id,
15
+ :aws_instance_type
16
+
17
+ def identified_by?(arg)
18
+ arg = arg.downcase
19
+ super(arg) or @private_dns_name == arg or @dns_name == arg
20
+ end
21
+
22
+ def stop!
23
+ if amazon.ecc.terminate_instances(ec2_id)
24
+ amazon.sdb.delete_attributes amazon.domain, aws_id
25
+ end
26
+ end
27
+
28
+ def dns
29
+ if Infrastructure.in_cluster?
30
+ private_dns_name
31
+ else
32
+ dns_name
33
+ end
34
+ end
35
+
36
+ def ip
37
+ Infrastructure.dns.getaddress(dns).to_s
38
+ end
39
+
40
+ def id
41
+ @aws_instance_id
42
+ end
43
+ alias :ec2_id :id
44
+
45
+ alias :groups :aws_groups
46
+
47
+ def no_sdb?
48
+ !@set_sdb
49
+ end
50
+
51
+ def set_sdb_attributes(args)
52
+ args.each do |k, v|
53
+ case k
54
+ when 'start_time_sorted'
55
+ self.start_time = Time.parse v
56
+ when 'entry', 'ec2_id'
57
+ # NOP
58
+ when 'services'
59
+ @services = v.is_a?(Array) ? v : Array(v)
60
+ when 'disabled_services'
61
+ @disabled_services = v.is_a?(Array) ? v : Array(v)
62
+ else
63
+ self.send("#{k}=", v)
64
+ end
65
+ end
66
+ @set_sdb = true
67
+ end
68
+
69
+ def ec2_id=(id)
70
+ aws_instance_id = id
71
+ end
72
+
73
+ def aws_id
74
+ @aws_id ||= UUIDTools::UUID.timestamp_create.to_s
75
+ end
76
+
77
+ def start_time_sorted
78
+ start_time.xmlschema(3)
79
+ end
80
+
81
+ def fields
82
+ %w(aws_id label start_time_sorted spot_price services disabled_services friendly_name ec2_id state)
83
+ end
84
+
85
+ def attributes
86
+ args = fields.inject({'entry' => 'machine'}) {|m, attr|
87
+ m.merge attr => self.send(attr)
88
+ }
89
+ Amazon.to_sdb_attributes(args)
90
+ end
91
+
92
+ def start!(price = nil)
93
+ args = {
94
+ :key_name => key,
95
+ :user_data => user_data,
96
+ :instance_type => type,
97
+ :availability_zone => zone,
98
+ }
99
+
100
+ resp = if spot_price
101
+ args.merge! :spot_price => spot_price,
102
+ :instance_count => 1,
103
+ :groups => groups,
104
+ :image_id => image
105
+ amazon.ecc.request_spot_instances args
106
+ else
107
+ args.merge! :group_ids => groups,
108
+ :min_count => 1,
109
+ :max_count => 1
110
+ amazon.ecc.launch_instances image, args
111
+ end
112
+
113
+ if resp
114
+ puts "INS RESP -> #{resp.inspect}"
115
+ resp.first.keys.each do |k|
116
+ func = "#{k.to_s}="
117
+ send(func, resp.first[k]) if respond_to? func
118
+ end
119
+
120
+ res = amazon.sdb.put_attributes(amazon.domain, aws_id, attributes, :replace)
121
+ puts "Res #{res.inspect}"
122
+ self
123
+ else
124
+ nil
125
+ end
126
+ end
127
+
128
+ def groups
129
+ return @aws_groups if @aws_groups
130
+
131
+ groups = services.map {|s|
132
+ grps = options.services_to_groups
133
+ if grps and grps.include? s
134
+ grps
135
+ else
136
+ s
137
+ end
138
+ }.flatten
139
+ (groups << 'default').uniq
140
+ end
141
+
142
+ def key
143
+ groups.include?('access') ? 'access' : 'cloud'
144
+ end
145
+
146
+ def user_data
147
+ %Q@#!/bin/bash
148
+
149
+ CLUSTER_USER=ubuntu
150
+ CLUSTER_DIR=/home/${CLUSTER_USER}/.cluster
151
+ LOGGER=${CLUSTER_DIR}/cluster.log
152
+ MONITOR=${CLUSTER_DIR}/monitor.god
153
+ CREDENTIALS=${CLUSTER_DIR}/credentials.yml
154
+ CLUSTER_EXECUTABLE=$(which cluster)
155
+ GEM_PATH=$(gem env gempath)
156
+ GEM_BIN_DIR=$(dirname ${CLUSTER_EXECUTABLE})
157
+ GOD=/usr/bin/god
158
+
159
+ if [[ ! -e $CLUSTER_DIR ]]; then
160
+ mkdir -m 700 $CLUSTER_DIR
161
+ fi
162
+
163
+ if [[ ! -e $CREDENTIALS ]]; then
164
+ wget --no-check-certificate -O $CREDENTIALS '#{amazon.credentials_url}'
165
+ fi
166
+
167
+ if [[ ! -e $CREDENTIALS ]]; then
168
+ echo "Cannot start without credentials! (perhaps a cluster save_credentials is in order)"
169
+ exit 1
170
+ fi
171
+
172
+ chmod 600 $CREDENTIALS
173
+ chown $CLUSTER_USER $CREDENTIALS
174
+ cat >>$CREDENTIALS <<EOF
175
+ cluster:
176
+ id: #{aws_id}
177
+ services: #{services.join(' ')}
178
+ EOF
179
+
180
+ wget --no-check-certificate -O /tmp/cluster.gem '#{Cluster::LOCATION}'
181
+ if [[ -e /tmp/cluster.gem ]]; then
182
+ if [[ $CLUSTER_EXECUTABLE != '' ]]; then
183
+ gem uninstall -x cluster
184
+ fi
185
+ gem install /tmp/cluster.gem
186
+ rm /tmp/cluster.gem
187
+ fi
188
+
189
+
190
+ CLUSTER='X'
191
+ if type -P cluster >/dev/null; then
192
+ CLUSTER=cluster
193
+ elif [[ -x $GEM_BIN_DIR/cluster ]]; then
194
+ CLUSTER="$GEM_BIN_DIR/cluster"
195
+ fi
196
+
197
+ if [[ ! $CLUSTER == 'X' ]]; then
198
+ CLUSTER="$CLUSTER --credentials=${CREDENTIALS} --logger=${LOGGER}"
199
+ $CLUSTER instance_state starting
200
+
201
+ $CLUSTER fetch_monitor ${MONITOR}
202
+ if [[ -e $MONITOR ]]; then
203
+ chmod 600 $MONITOR
204
+ chown $CLUSTER_USER $MONITOR
205
+ mv $MONITOR /etc/god/init.d/cluster.god
206
+ $GOD load /etc/god/init.d/cluster.god
207
+ else
208
+ echo "NO MONITOR FILE!"
209
+ exit 1
210
+ fi
211
+ else
212
+ echo "NO CLUSTER!"
213
+ exit 1
214
+ fi
215
+
216
+ chown -R $CLUSTER_USER:$CLUSTER_USER $CLUSTER_DIR
217
+ @.gsub(/^ /, '')
218
+ end
219
+
220
+ def set_state(state)
221
+ amazon.sdb.put_attributes amazon.domain, aws_id, Amazon.to_sdb_attributes(:state => state), :replace
222
+ @state = state
223
+ end
224
+
225
+ def options
226
+ amazon.options
227
+ end
228
+
229
+ def zone
230
+ amazon.options.zone
231
+ end
232
+
233
+ def amazon
234
+ Infrastructure.current
235
+ end
236
+
237
+ def image
238
+ return @aws_image_id if @aws_image_id
239
+
240
+ case type
241
+ when 'm1.small', 'c1.medium'
242
+ amazon.get_image 32
243
+ else
244
+ amazon.get_image 64
245
+ end
246
+ end
247
+
248
+ def type
249
+ return @aws_instance_type if @aws_instance_type
250
+
251
+ @aws_instance_type = self.class.size_to_type size
252
+ end
253
+
254
+ class << self
255
+ def size_to_type(size)
256
+ case size
257
+ when 'minimum', 'basic'
258
+ 'm1.small'
259
+ when 'average'
260
+ 'm1.large'
261
+ when 'power'
262
+ 'c1.medium'
263
+ when 'super'
264
+ 'c1.xlarge'
265
+ when /^\w+\.\w+$/
266
+ size
267
+ end
268
+ end
269
+ end
270
+ end
@@ -0,0 +1,63 @@
1
+ class AmazonRelease < Release
2
+ attr_accessor :aws_id
3
+
4
+ def created_at
5
+ @created_at ||= Time.now
6
+ end
7
+
8
+ def sdb_created_at
9
+ created_at.xmlschema(3)
10
+ end
11
+
12
+ def sdb_created_at=(time)
13
+ self.created_at = Time.parse(time)
14
+ end
15
+
16
+ def amazon
17
+ Infrastructure.current
18
+ end
19
+
20
+ def save
21
+ fields = %w(aws_id label sdb_created_at environment tag)
22
+ args = fields.inject({'entry' => 'release'}) {|m, attr|
23
+ m.merge attr => self.send(attr)
24
+ }
25
+ attributes = Amazon.to_sdb_attributes(args)
26
+ amazon.sdb.put_attributes(amazon.domain, aws_id, attributes, :replace)
27
+ @new_release = true
28
+ self
29
+ end
30
+
31
+ def new?
32
+ @new_release
33
+ end
34
+
35
+ def aws_id
36
+ @aws_id ||= UUIDTools::UUID.timestamp_create.to_s
37
+ end
38
+
39
+ class << self
40
+ def create(*params)
41
+ self.new(*params).save
42
+ end
43
+
44
+ def current(environment = 'staging')
45
+ query_for_release "entry = 'release' AND environment = '#{environment}' AND sdb_created_at IS NOT NULL ORDER BY sdb_created_at DESC limit 1"
46
+ end
47
+
48
+ def find(env, tag)
49
+ query_for_release "entry = 'release' AND environment = '#{env}' AND tag = '#{tag}'"
50
+ end
51
+
52
+ def query_for_release(clause)
53
+ amazon = Infrastructure.current
54
+ res = amazon.sdb.select("SELECT * FROM #{amazon.domain} WHERE #{clause}")
55
+ args = Amazon.from_sdb_results(res)
56
+ if args.empty?
57
+ nil
58
+ else
59
+ self.new(args.first)
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,97 @@
1
+ require 'time'
2
+ require 'ext/cluster_extensions.rb'
3
+
4
+ class Instance
5
+ attr_accessor :label,
6
+ :id,
7
+ :address,
8
+ :groups,
9
+ :services,
10
+ :disabled_services,
11
+ :size,
12
+ :state,
13
+ :start_time,
14
+ :friendly_name
15
+
16
+ def initialize(*args)
17
+ options = args.extract_options!
18
+ options.each do |key, value|
19
+ func = "#{key}="
20
+ if self.respond_to? func
21
+ self.send func, value
22
+ end
23
+ end
24
+ end
25
+
26
+ def start_time
27
+ case @start_time
28
+ when Time
29
+ @start_time
30
+ when nil
31
+ @start_time = Time.now
32
+ else
33
+ @start_time = Time.parse @start_time
34
+ end
35
+ end
36
+
37
+ def identified_by?(arg)
38
+ arg = arg.downcase
39
+ self.id == arg or self.label == arg or self.dns == arg or self.friendly_name == arg
40
+ end
41
+
42
+ def state
43
+ @state ||= 'spinning'
44
+ end
45
+
46
+ def services
47
+ @services ||= []
48
+ end
49
+
50
+ def disabled_services
51
+ @disabled_services ||= []
52
+ end
53
+
54
+ def enable(service_list)
55
+ for service in service_list
56
+ @disabled_services.delete(service) if disabled_services.include? service
57
+
58
+ unless services.include? service
59
+ @services = services << service
60
+ end
61
+ end
62
+
63
+ @services
64
+ end
65
+
66
+ def disable(service_list)
67
+ for service in service_list
68
+ unless disabled_services.include? service
69
+ @disabled_services = disabled_services << service
70
+ end
71
+ end
72
+
73
+ @disabled_services
74
+ end
75
+
76
+ def to_s(format = nil)
77
+ case format
78
+ when :long
79
+ svs = if services.empty?
80
+ 'N/S'
81
+ else
82
+ services.map {|s|
83
+ disabled_services.include?(s) ? "!#{s}" : s
84
+ }.join(',')
85
+ end
86
+ "#{friendly_name}\t#{svs}\t#{state}\t#{id}\t#{dns}"
87
+ else
88
+ label or id
89
+ end
90
+ end
91
+
92
+ class << self
93
+ def create(*args)
94
+ new(*args).start!
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,30 @@
1
+ class Release
2
+ attr_accessor :label,
3
+ :tag,
4
+ :environment,
5
+ :created_at
6
+
7
+ def initialize(*args)
8
+ options = args.extract_options!
9
+ options.each do |key, value|
10
+ func = "#{key}="
11
+ if self.respond_to? func
12
+ self.send func, value
13
+ end
14
+ end
15
+ end
16
+
17
+ def environment
18
+ @environment ||= 'staging'
19
+ end
20
+
21
+ class << self
22
+ def current(environment = 'staging')
23
+ Infrastructure.current.release_class.current(environment)
24
+ end
25
+
26
+ def find(env, tag)
27
+ Infrastructure.current.release_class.find(environment, tag)
28
+ end
29
+ end
30
+ end