cluster 0.5.33

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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