cluster 0.6.5 → 0.7.0

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.
@@ -11,7 +11,7 @@ class Cluster
11
11
  end
12
12
 
13
13
  if arguments.include?('--version')
14
- puts "#{Cluster::NAME} version #{Cluster::Version::STRING}"
14
+ puts "#{Cluster::NAME} version #{Cluster.version}"
15
15
  exit 0
16
16
  end
17
17
 
@@ -52,18 +52,6 @@ class Cluster
52
52
  exit 1
53
53
  end
54
54
 
55
- if command.downcase == 'gemurl'
56
- # We don't need to do any infrastructure for this one...and
57
- # we may not have it yet...
58
- puts Cluster::LOCATION
59
- exit 0
60
- elsif command.downcase == 'imageurl'
61
- # We don't need to do any infrastructure for this one...and
62
- # we may not have it yet...
63
- puts Cluster::IMAGES
64
- exit 0
65
- end
66
-
67
55
  file = File.open(logger_file, File::WRONLY | File::APPEND | File::CREAT)
68
56
 
69
57
  $stderr = file
@@ -139,6 +127,19 @@ class Cluster
139
127
  end
140
128
  end
141
129
 
130
+ def add_self(name, services)
131
+ @sub.update_instances
132
+ ins = @sub.current_instance
133
+ ins.state ||= 'starting'
134
+ ins.friendly_name = name
135
+ servs = services.split ','
136
+ unless servs.empty?
137
+ ins.enable servs
138
+ end
139
+ @sub.alter_instances! ins
140
+ puts ins.aws_id
141
+ end
142
+
142
143
  def enable(*params)
143
144
  service_list = params.shift
144
145
 
@@ -163,11 +164,18 @@ class Cluster
163
164
  alter_instances(params) {|ins| ins.disable servs }
164
165
  end
165
166
 
166
- def label(name, id)
167
+ def label(name, id = nil)
168
+ id ||= @sub.current_instance.id
169
+
167
170
  alter_instances([id]) {|i| i.friendly_name = name.downcase}
168
171
  end
169
172
 
170
- def unlabel(id)
173
+ def update_machines
174
+ @sub.update_machines
175
+ end
176
+
177
+ def unlabel(id = nil)
178
+ id ||= @sub.current_instance.id
171
179
  alter_instances([id]) {|i| i.friendly_name = ''}
172
180
  end
173
181
 
@@ -15,17 +15,24 @@ class Amazon < Infrastructure
15
15
  @options.cluster_bucket = creds['cluster_bucket']
16
16
  @options.bucket_key = creds['bucket_key']
17
17
  @options.cluster_domain = creds['cluster_domain']
18
- @options.zone = creds['zone']
18
+ @options.zones = creds['zones']
19
19
  @options.volumes = creds['volumes']
20
+ @options.elb_name = creds['web']['elb_name']
20
21
  end
21
22
 
22
- @options.key ||= ENV['AMAZON_ACCESS_KEY_ID']
23
- @options.secret ||= ENV['AMAZON_SECRET_ACCESS_KEY']
23
+ @options.key ||= ENV['AWS_ACCESS_KEY']
24
+ @options.secret ||= ENV['AWS_SECRET_KEY']
24
25
  @options.owner ||= ENV['AMAZON_OWNER_ID']
25
26
  @options.cluster_bucket ||= ENV['CLUSTER_BUCKET']
26
27
  @options.bucket_key ||= 'cluster_credentials.yml'
27
- @options.zone ||= ENV['AMAZON_ZONE']
28
+ @options.zones ||= if ENV['AMAZON_ZONE'].empty?
29
+ nil
30
+ else
31
+ Array(ENV['AMAZON_ZONE'])
32
+ end
33
+
28
34
  @options.cluster_domain ||= ENV['CLUSTER_DOMAIN'] || self.class.cluster_name
35
+ @options.elb_name ||= ENV['INGAMER_LOAD_BALANCER']
29
36
  @options.volumes ||= {}
30
37
 
31
38
  @options.role = (ENV['CLUSTER_ROLE'] or ENV['RAILS_ENV'] or 'production')
@@ -69,7 +76,7 @@ class Amazon < Infrastructure
69
76
  end
70
77
 
71
78
  o.on('-z', '--zone VAL', "Availability Zone") do |v|
72
- @options.zone = v
79
+ @options.zones = Array(v)
73
80
  end
74
81
 
75
82
  o.on('--spot', "Use Spot Instances") do |v|
@@ -97,6 +104,10 @@ class Amazon < Infrastructure
97
104
  @@instances ||= load_instances
98
105
  end
99
106
 
107
+ def clear_instances
108
+ @@instances = nil
109
+ end
110
+
100
111
  def cost(sizes)
101
112
  unless @options.spot_instances
102
113
  puts "Cost only works for spot instances currently (ie. supply infrastructure argument of --spot"
@@ -122,15 +133,52 @@ class Amazon < Infrastructure
122
133
  end
123
134
 
124
135
  def load_instances
125
- terminated = []
126
- iss = ecc.describe_instances.map {|ins|
127
- if %w(terminated shutting-down).include? ins[:aws_state]
128
- terminated << ins[:aws_instance_id]
129
- nil
130
- else
131
- AmazonInstance.new(ins)
136
+ begin
137
+ res = sdb.select "select * from #{domain} where entry='machine'"
138
+ rescue RightAws::AwsError
139
+ unless domains.include? domain
140
+ sdb.create_domain domain
141
+ retry
132
142
  end
133
- }.compact
143
+ end
144
+ sdbs = self.class.from_sdb_results res
145
+
146
+ sdbs.map {|sd|
147
+ ins = AmazonInstance.new
148
+ ins.set_sdb_attributes sd
149
+ ins
150
+ }
151
+ end
152
+
153
+ =begin
154
+ def add_instance(*services)
155
+ update_machines
156
+ ins = current_instance
157
+ ins.services = services
158
+ sdb.put_attributes domain, ins.aws_id, ins.attributes, :replace
159
+ end
160
+ alias :add_machine :add_instance
161
+ =end
162
+
163
+ def instance_list
164
+ terminated = []
165
+ iss = @options.zones.map {|z|
166
+ e = ecc region: z
167
+ e.describe_instances.map {|ins|
168
+ if %w(terminated shutting-down).include? ins[:aws_state]
169
+ terminated << ins[:aws_instance_id]
170
+ nil
171
+ else
172
+ AmazonInstance.new(ins)
173
+ end
174
+ }.compact
175
+ }.flatten
176
+
177
+ [iss, terminated]
178
+ end
179
+
180
+ def update_instances
181
+ iss, terminated = instance_list
134
182
 
135
183
  begin
136
184
  res = sdb.select "select * from #{domain} where entry='machine'"
@@ -171,12 +219,13 @@ class Amazon < Infrastructure
171
219
  iss.each do |ins|
172
220
  if ins.no_sdb?
173
221
  puts "Cannot find cluster registration for #{ins.ec2_id} -- creating."
174
- sdb.put_attributes domain, ins.aws_id, ins.attributes, :replace
175
222
  end
223
+ sdb.put_attributes domain, ins.aws_id, ins.attributes, :replace
176
224
  end
177
225
 
178
226
  iss
179
227
  end
228
+ alias :update_machines :update_instances
180
229
 
181
230
  def alter_instances!(*iss)
182
231
  list = iss.empty? ? instances : iss
@@ -318,58 +367,46 @@ class Amazon < Infrastructure
318
367
  @options.cluster_domain
319
368
  end
320
369
 
321
- def sdb(params = {})
322
- return @sdb if @sdb
323
- @sdb = RightAws::SdbInterface.new(key, secret, connection_params(params))
324
- unless @sdb
325
- puts "Amazon cannot connect to SimpleDB"
326
- exit 3
327
- end
328
- @sdb
370
+ def balance
371
+ eid = current_instance.ec2_id
372
+
373
+ elb.register_instances_with_load_balancer @options.elb_name, eid
329
374
  end
330
375
 
331
- def connect_to_active_sdb(params = {})
332
- RightAws::ActiveSdb.establish_connection key, secret, connection_params(params)
376
+ def sdb(o = nil)
377
+ params = connection_params o
378
+ params.delete :region
379
+ @sdb ||= RightAws::SdbInterface.new(key, secret, params)
333
380
  end
334
381
 
335
- def sss(params = {})
336
- return @s3 if @s3
337
- @s3 = RightAws::S3.new(key, secret, connection_params(params))
338
- unless @s3
339
- puts "Amazon cannot connect to S3"
340
- exit 3
341
- end
342
- @s3
382
+ def connect_to_active_sdb(o = nil)
383
+ params = connection_params o
384
+ params.delete :region
385
+ RightAws::ActiveSdb.establish_connection key, secret, params
343
386
  end
344
387
 
345
- def sqs(params = {})
346
- return @sqs if @sqs
347
- @sqs = RightAws::SqsGen2.new(key, secret, connection_params(params))
348
- unless @sqs
349
- puts "Amazon cannot connect to S3"
350
- exit 3
351
- end
352
- @sqs
388
+ def sss(o = nil)
389
+ params = connection_params o
390
+ params.delete :region
391
+ @sqs ||= RightAws::ElbInterface.new(key, secret, params)
353
392
  end
354
393
 
355
- def elb(params = {})
356
- return @elb if @elb
357
- @elb = RightAws::ElbInterface.new(key, secret, connection_params(params))
358
- unless @elb
359
- puts "Amazon cannot connect to elb"
360
- exit 3
361
- end
362
- @elb
394
+ def sqs(o = nil)
395
+ params = connection_params o
396
+ @sqs ||= {}
397
+ @sqs[params[:region]] ||= RightAws::ElbInterface.new(key, secret, params)
363
398
  end
364
399
 
365
- def ecc(params = {})
366
- return @ec2 if @ec2
367
- @ec2 = RightAws::Ec2.new(key, secret, connection_params(params))
368
- unless @ec2
369
- puts "Amazon cannot connect to EC2"
370
- exit 3
371
- end
372
- @ec2
400
+ def elb(o = nil)
401
+ params = connection_params o
402
+ @elb ||= {}
403
+ @elb[params[:region]] ||= RightAws::ElbInterface.new(key, secret, params)
404
+ end
405
+
406
+ def ecc(o = nil)
407
+ params = connection_params o
408
+ @ec2 ||= {}
409
+ @ec2[params[:region]] ||= RightAws::Ec2.new key, secret, params
373
410
  end
374
411
 
375
412
  def domains(reload = false)
@@ -399,13 +436,14 @@ class Amazon < Infrastructure
399
436
  @check = check
400
437
  end
401
438
 
402
- def connection_params(params = {})
439
+ def connection_params(o = nil)
440
+ params = o ? o.clone : {}
403
441
  params = {:multi_thread => true} if params.empty?
404
- unless params.include?(:logger)
405
- params.merge(:logger => logger)
406
- else
407
- params
408
- end
442
+
443
+ params[:logger] ||= logger
444
+ params[:region] ||= @options.zones.first
445
+
446
+ params
409
447
  end
410
448
 
411
449
  def store(key, io)
@@ -2,6 +2,8 @@ class AmazonInstance < Instance
2
2
  attr_accessor :ssh_key_name,
3
3
  :private_dns_name,
4
4
  :dns_name,
5
+ :private_ip_address,
6
+ :ip_address,
5
7
  :aws_image_id,
6
8
  :spot_price,
7
9
  :aws_groups,
@@ -34,7 +36,11 @@ class AmazonInstance < Instance
34
36
  end
35
37
 
36
38
  def ip
37
- Infrastructure.dns.getaddress(dns).to_s
39
+ if Infrastructure.in_cluster?
40
+ private_ip_address
41
+ else
42
+ ip_address
43
+ end
38
44
  end
39
45
 
40
46
  def id
@@ -56,9 +62,9 @@ class AmazonInstance < Instance
56
62
  when 'entry', 'ec2_id'
57
63
  # NOP
58
64
  when 'services'
59
- @services = v.is_a?(Array) ? v : Array(v)
65
+ @services = Array(v)
60
66
  when 'disabled_services'
61
- @disabled_services = v.is_a?(Array) ? v : Array(v)
67
+ @disabled_services = Array(v)
62
68
  else
63
69
  self.send("#{k}=", v)
64
70
  end
@@ -79,7 +85,7 @@ class AmazonInstance < Instance
79
85
  end
80
86
 
81
87
  def fields
82
- %w(aws_id label start_time_sorted spot_price services disabled_services friendly_name ec2_id state)
88
+ %w(aws_id label start_time_sorted spot_price services disabled_services friendly_name ec2_id state ip_address private_ip_address dns_name private_dns_name)
83
89
  end
84
90
 
85
91
  def attributes
@@ -144,67 +150,7 @@ class AmazonInstance < Instance
144
150
  end
145
151
 
146
152
  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=$(type -p 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
- CLUSTER='X'
181
- if type -P cluster >/dev/null; then
182
- CLUSTER=cluster
183
- elif [[ -x $GEM_BIN_DIR/cluster ]]; then
184
- CLUSTER="$GEM_BIN_DIR/cluster"
185
- fi
186
-
187
- if [[ ! $CLUSTER == 'X' ]]; then
188
- CLUSTER="$CLUSTER --credentials=${CREDENTIALS} --logger=${LOGGER}"
189
- $CLUSTER instance_state starting
190
-
191
- $CLUSTER fetch_monitor ${MONITOR}
192
- if [[ -e $MONITOR ]]; then
193
- chmod 600 $MONITOR
194
- chown $CLUSTER_USER $MONITOR
195
- mv $MONITOR /etc/god/init.d/010_cluster.god
196
- $GOD load /etc/god/init.d/010_cluster.god
197
- else
198
- echo "NO MONITOR FILE!"
199
- exit 1
200
- fi
201
- else
202
- echo "NO CLUSTER!"
203
- exit 1
204
- fi
205
-
206
- chown -R $CLUSTER_USER:$CLUSTER_USER $CLUSTER_DIR
207
- @.gsub(/^ /, '')
153
+ ''
208
154
  end
209
155
 
210
156
  def set_state(state)
@@ -39,10 +39,6 @@ class Instance
39
39
  self.id == arg or self.label == arg or self.dns == arg or self.friendly_name == arg
40
40
  end
41
41
 
42
- def state
43
- @state ||= 'spinning'
44
- end
45
-
46
42
  def services
47
43
  @services ||= []
48
44
  end
@@ -4,22 +4,10 @@ class Cluster
4
4
  AUTHOR = 'Simon de Boer'
5
5
  EMAIL = 'sdeboer@InGamerSports.com'
6
6
  NAME = 'cluster'
7
- BUCKET = 'oven'
8
- LOCATION = "http://oven.s3.amazonaws.com/cluster.gem"
9
- IMAGES = 'http://oven.s3.amazonaws.com/cluster_images.yml'
10
-
11
- # Describes the current version of Capistrano.
12
- class Version < Net::SSH::Version
13
- MAJOR = 0
14
- MINOR = 6
15
- TINY = 5
16
-
17
- # The current version, as a Version instance
18
- CURRENT = new(MAJOR, MINOR, TINY)
19
-
20
- # The current version, as a String instance
21
- STRING = CURRENT.to_s
22
7
 
8
+ class << self
9
+ def version
10
+ Gem::Version.create('0.7.0')
11
+ end
23
12
  end
24
-
25
13
  end
@@ -0,0 +1,96 @@
1
+ #!/bin/bash
2
+ FRIENDLY=noble
3
+ SERVICES=web
4
+
5
+ CLUSTER_USER=ubuntu
6
+ CLUSTER_DIR=/home/${CLUSTER_USER}/.cluster
7
+ LOGGER=${CLUSTER_DIR}/cluster.log
8
+ # MONITOR=${CLUSTER_DIR}/monitor.god
9
+ CREDENTIALS=${CLUSTER_DIR}/credentials.yml
10
+ CLUSTER_EXECUTABLE=$(which cluster)
11
+ GEM_PATH=$(gem env gempath)
12
+ GEM_BIN_DIR=$(dirname ${CLUSTER_EXECUTABLE})
13
+ # GOD=$(type -p god)
14
+
15
+ CLUSTER='X'
16
+ if type -P cluster >/dev/null; then
17
+ CLUSTER=cluster
18
+ elif [[ -x $GEM_BIN_DIR/cluster ]]; then
19
+ CLUSTER="$GEM_BIN_DIR/cluster"
20
+ fi
21
+
22
+ if [[ ! $CLUSTER == 'X' ]]; then
23
+ CLUSTER="$CLUSTER --credentials=${CREDENTIALS} --logger=${LOGGER}"
24
+ else
25
+ echo "Cannot start without cluster command"
26
+ exit 1
27
+ fi
28
+
29
+ aws_id=$(${CLUSTER} add_self ${FRIENDLY} ${SERVICES})
30
+
31
+ echo >${CREDENTIALS} <<EOF
32
+ cluster:
33
+ id: ${aws_id}
34
+ services: ${SERVICES}
35
+ EOF
36
+ chown ${CLUSTER_USER}:${CLUSTER_USER} ${CREDENTIALS}
37
+ chmod 600 ${CREDENTIALS}
38
+
39
+ user=app
40
+ home=/mnt/home/${user}
41
+ app=${home}/inGamer
42
+ shared=${app}/shared
43
+ log=${shared}/log
44
+ cache=${shared}/cached-copy
45
+ ssh=${home}/.ssh
46
+ repo=$(${CLUSTER} service -d repository)
47
+ git_url="git://#{repo}/FireCat"
48
+ branch=origin/release
49
+ shared=/mnt/shared
50
+ bundles=${shared}/bundles
51
+
52
+ if [[ ! -e $ssh ]]; then
53
+ mkdir -m 700 $ssh
54
+ fi
55
+
56
+ ssh-keyscan -t dsa,rsa -H ${repo} localhost >>${ssh}/known_hosts
57
+ ${CLUSTER} retrieve web ${user}/authorized_keys ${ssh}/authorized_keys
58
+ wget -O /tmp/run_key http://169.254.169.254/latest/meta-data/public-keys/0/openssh-key
59
+ cat /tmp/run_key >>${ssh}/authorized_keys
60
+ rm /tmp/run_key
61
+ chmod 600 ${ssh}/*
62
+ chown -R ${user}:${user} ${ssh}
63
+
64
+ if [[ ! -e $log ]]; then
65
+ mkdir -p $log
66
+ chown -R ${user}:${user} ${app}
67
+ fi
68
+
69
+ if [[ ! -e $shared ]]; then
70
+ mkdir -m 1777 $shared
71
+ fi
72
+
73
+ if [[ ! -e $bundles ]]; then
74
+ mkdir -m 777 $bundles
75
+ fi
76
+
77
+ ${CLUSTER} instance_state cloning
78
+ if [[ ! -e $cache ]]; then
79
+ su -l ${user} -c "cd ${cache}; git pull; git checkout deploy; git merge ${branch}"
80
+ else
81
+ git clone ${git_url} ${cache}
82
+ chown -R ${user}:${user} ${cache}
83
+ su -l ${user} -c "cd ${cache}; git checkout -q -b deploy ${branch}"
84
+ fi
85
+
86
+ su -l ${user} -c "cd ${cache}; export NO_CAPS=true; APP_HOME=${cache}; cap local deploy:setup && cap local deploy"
87
+
88
+ ${CLUSTER} instance_state httpd
89
+
90
+ cd ${cache}/cluster/services.d/web/apache.d
91
+
92
+ source ./config.sh
93
+ apache2ctl graceful
94
+
95
+ ${CLUSTER} balance
96
+ ${CLUSTER} instance_state running