ey_cloud_server 1.0.1 → 1.1.1.pre5

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,3 @@
1
1
  module EY::CloudServer
2
- VERSION = '1.0.1'
2
+ VERSION = '1.1.1.pre5'
3
3
  end
data/lib/ey-flex.rb CHANGED
@@ -4,12 +4,9 @@ require 'date'
4
4
  require 'digest'
5
5
  require 'net/http'
6
6
  require 'fileutils'
7
- require 'eventmachine'
8
- require 'em-http'
9
7
  require 'json/ext'
10
8
  require 'right_aws'
11
9
  require 'open-uri'
12
- require 'rest_client'
13
10
  require 'dbi'
14
11
  require 'zlib'
15
12
  require 'stringio'
@@ -29,9 +26,7 @@ end
29
26
  require lib_dir + '/big-brother'
30
27
  require lib_dir + '/backups'
31
28
  require lib_dir + '/bucket_minder'
32
- require lib_dir + '/ey-api'
33
29
  require lib_dir + '/mysql_database'
34
30
  require lib_dir + '/postgresql_database'
35
31
  require lib_dir + '/snapshot_minder'
36
- require lib_dir + '/stonith'
37
32
  require lib_dir + '/version'
metadata CHANGED
@@ -1,7 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ey_cloud_server
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ prerelease: true
5
+ segments:
6
+ - 1
7
+ - 1
8
+ - 1
9
+ - pre5
10
+ version: 1.1.1.pre5
5
11
  platform: ruby
6
12
  authors:
7
13
  - Ezra Zygmuntowicz
@@ -9,75 +15,77 @@ autorequire:
9
15
  bindir: bin
10
16
  cert_chain: []
11
17
 
12
- date: 2010-01-20 00:00:00 -08:00
18
+ date: 2010-04-14 00:00:00 -07:00
13
19
  default_executable:
14
20
  dependencies:
15
21
  - !ruby/object:Gem::Dependency
16
- name: json
17
22
  type: :runtime
18
- version_requirement:
19
- version_requirements: !ruby/object:Gem::Requirement
23
+ version_requirements: &id001 !ruby/object:Gem::Requirement
20
24
  requirements:
21
25
  - - ">="
22
26
  - !ruby/object:Gem::Version
27
+ segments:
28
+ - 0
23
29
  version: "0"
24
- version:
25
- - !ruby/object:Gem::Dependency
26
- name: right_aws
27
- type: :runtime
28
- version_requirement:
29
- version_requirements: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - ">="
32
- - !ruby/object:Gem::Version
33
- version: "0"
34
- version:
30
+ requirement: *id001
31
+ name: json
32
+ prerelease: false
35
33
  - !ruby/object:Gem::Dependency
36
- name: open4
37
34
  type: :runtime
38
- version_requirement:
39
- version_requirements: !ruby/object:Gem::Requirement
35
+ version_requirements: &id002 !ruby/object:Gem::Requirement
40
36
  requirements:
41
37
  - - ">="
42
38
  - !ruby/object:Gem::Version
39
+ segments:
40
+ - 0
43
41
  version: "0"
44
- version:
42
+ requirement: *id002
43
+ name: right_aws
44
+ prerelease: false
45
45
  - !ruby/object:Gem::Dependency
46
- name: aws-s3
47
46
  type: :runtime
48
- version_requirement:
49
- version_requirements: !ruby/object:Gem::Requirement
47
+ version_requirements: &id003 !ruby/object:Gem::Requirement
50
48
  requirements:
51
49
  - - ">="
52
50
  - !ruby/object:Gem::Version
51
+ segments:
52
+ - 0
53
53
  version: "0"
54
- version:
54
+ requirement: *id003
55
+ name: open4
56
+ prerelease: false
55
57
  - !ruby/object:Gem::Dependency
56
- name: igrigorik-em-http-request
57
58
  type: :runtime
58
- version_requirement:
59
- version_requirements: !ruby/object:Gem::Requirement
59
+ version_requirements: &id004 !ruby/object:Gem::Requirement
60
60
  requirements:
61
61
  - - ">="
62
62
  - !ruby/object:Gem::Version
63
+ segments:
64
+ - 0
63
65
  version: "0"
64
- version:
66
+ requirement: *id004
67
+ name: aws-s3
68
+ prerelease: false
65
69
  - !ruby/object:Gem::Dependency
66
- name: rest-client
67
70
  type: :runtime
68
- version_requirement:
69
- version_requirements: !ruby/object:Gem::Requirement
71
+ version_requirements: &id005 !ruby/object:Gem::Requirement
70
72
  requirements:
71
- - - ">="
73
+ - - "="
72
74
  - !ruby/object:Gem::Version
73
- version: "0"
74
- version:
75
+ segments:
76
+ - 0
77
+ - 1
78
+ - 5
79
+ - pre
80
+ version: 0.1.5.pre
81
+ requirement: *id005
82
+ name: ey_stonith
83
+ prerelease: false
75
84
  description: Server side components for Engine Yard's cloud
76
85
  email: awsmdev@engineyard.com
77
86
  executables:
78
87
  - eybackup
79
88
  - ey-snapshots
80
- - ey-monitor
81
89
  - ey-agent
82
90
  extensions: []
83
91
 
@@ -90,11 +98,9 @@ files:
90
98
  - lib/ey-flex/backups.rb
91
99
  - lib/ey-flex/big-brother.rb
92
100
  - lib/ey-flex/bucket_minder.rb
93
- - lib/ey-flex/ey-api.rb
94
101
  - lib/ey-flex/mysql_database.rb
95
102
  - lib/ey-flex/postgresql_database.rb
96
103
  - lib/ey-flex/snapshot_minder.rb
97
- - lib/ey-flex/stonith.rb
98
104
  - lib/ey-flex/version.rb
99
105
  - lib/ey-flex.rb
100
106
  has_rdoc: true
@@ -110,18 +116,22 @@ required_ruby_version: !ruby/object:Gem::Requirement
110
116
  requirements:
111
117
  - - ">="
112
118
  - !ruby/object:Gem::Version
119
+ segments:
120
+ - 0
113
121
  version: "0"
114
- version:
115
122
  required_rubygems_version: !ruby/object:Gem::Requirement
116
123
  requirements:
117
- - - ">="
124
+ - - ">"
118
125
  - !ruby/object:Gem::Version
119
- version: "0"
120
- version:
126
+ segments:
127
+ - 1
128
+ - 3
129
+ - 1
130
+ version: 1.3.1
121
131
  requirements: []
122
132
 
123
133
  rubyforge_project:
124
- rubygems_version: 1.3.5
134
+ rubygems_version: 1.3.6
125
135
  signing_key:
126
136
  specification_version: 3
127
137
  summary: Server side components for Engine Yard's cloud
data/bin/ey-monitor DELETED
@@ -1,5 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- require File.dirname(__FILE__) + '/../lib/ey-flex'
4
-
5
- EY::Stonith.run
@@ -1,21 +0,0 @@
1
- module EyApi
2
- def call_api(path, opts={})
3
- JSON.parse(@rest["/api/#{path}"].post(@keys.merge(opts), {"Accept" => "application/json"}))
4
- rescue RestClient::RequestFailed => e
5
- case e.http_code
6
- when 503
7
- sleep 10 # Nanite, save us...
8
- retry
9
- else
10
- raise "API call to Engine Yard failed with status #{e.http_code}."
11
- end
12
- end
13
-
14
- def get_envs
15
- @_envs ||= call_api("environments")
16
- end
17
-
18
- def get_json(instance_id)
19
- call_api("json_for_instance", :instance_id => instance_id)
20
- end
21
- end
@@ -1,190 +0,0 @@
1
- module EY
2
- class Log
3
- def self.write(str)
4
- puts str
5
- File.open("/root/ey-monitor2.log", "a") do |f|
6
- f.write("#{str}\n")
7
- end
8
- end
9
- end
10
-
11
- class Stonith
12
- include EyApi
13
-
14
- def self.run
15
- opts = YAML::load(File.read("/etc/.mysql.backups.yml"))
16
- opts.merge!(YAML::load(File.read("/etc/.ey-cloud.yml")))
17
- EventMachine.run {
18
- EY::Stonith.new(opts.merge(:heartbeat => 10))
19
- }
20
- end
21
-
22
- def initialize(opts={})
23
- Log.write "Starting up"
24
- @opts = opts
25
- @rest = RestClient::Resource.new(opts[:api])
26
- @keys = {:aws_secret_id => @opts[:aws_secret_id], :aws_secret_key => @opts[:aws_secret_key]}
27
- @bad_checks = 0
28
- @seen_good_check = false
29
- @ec2 = RightAws::Ec2.new(@opts[:aws_secret_id], @opts[:aws_secret_key])
30
- @taking_over = false
31
- get_local_json
32
- get_master_from_json
33
- setup_traps
34
- start
35
- am_i_master?
36
- end
37
-
38
- def setup_traps
39
- trap("HUP") { cancel_master_check_timer; Log.write "timer canceled, not monitoring until you wake me up again"}
40
- trap("USR1") { EM.add_timer(600) { setup_master_check_timer unless am_i_master? }; Log.write "woke up, starting monitoring again in 10 minutes"}
41
- end
42
-
43
- def get_mysql_handle
44
- DBI.connect("DBI:Mysql:engineyard:#{@json['db_host']}", 'root', @opts[:dbpass])
45
- end
46
-
47
- def try_lock(nodename)
48
- Log.write("Trying to grab the lock for: #{nodename}")
49
- db = get_mysql_handle
50
- db.execute("begin")
51
- res = db.execute("select master_lock from locks for update")
52
- master = res.fetch[0]
53
- res.finish
54
- got_lock = false
55
- if master == @master
56
- got_lock = true
57
- @master = "http://#{private_dns_name}/haproxy/monitor"
58
- db.do("update locks set master_lock = '#{@master}'")
59
- else
60
- # new master, don't start monitoring till it comes up
61
- @seen_good_check = false
62
- @taking_over = false
63
- @master = master
64
- Log.write("Failed to grab lock, relenting: #{nodename}\nmaster is: #{@master}")
65
- EM.add_timer(600) { Log.write "restarting monitoring"; setup_master_check_timer }
66
- end
67
- db.do("commit")
68
- db.disconnect
69
- got_lock
70
- end
71
-
72
- def start
73
- setup_master_check_timer
74
- EM.add_periodic_timer(300) { get_local_json }
75
- end
76
-
77
- def setup_master_check_timer
78
- cancel_master_check_timer
79
- unless self_monitor_url == @master
80
- @check_master_timer = EventMachine::PeriodicTimer.new(@opts[:heartbeat]) { check_master }
81
- end
82
- end
83
-
84
- def cancel_master_check_timer
85
- @check_master_timer && @check_master_timer.cancel
86
- end
87
-
88
- def check_master
89
- http = EventMachine::HttpRequest.new(@master).get :timeout => 10
90
-
91
- http.callback {
92
- unless http.response_header.status == 200
93
- take_over_as_master
94
- else
95
- @seen_good_check = true
96
- @bad_checks = 0
97
- end
98
- http.response_header.status
99
- }
100
- http.errback { |msg, err|
101
- take_over_as_master
102
- }
103
- end
104
-
105
- def take_over_as_master
106
- Log.write("Got a bad check: seen good check is #{@seen_good_check.inspect}")
107
- @bad_checks += 1
108
- if @bad_checks > 5 && @seen_good_check && !@taking_over
109
- Log.write "I'm trying to take over!"
110
- @taking_over = true
111
- cancel_master_check_timer
112
- if try_lock(private_dns_name)
113
- Log.write("I got the lock!")
114
- steal_ip
115
- unless notify_awsm
116
- timer = EventMachine::PeriodicTimer.new(5) { timer.cancel if notify_awsm }
117
- end
118
- end
119
- end
120
- end
121
-
122
- def am_i_master?
123
- res = false
124
- @ec2.describe_addresses.each do |desc|
125
- res = true if (desc[:public_ip] == public_ip && desc[:instance_id] == instance_id)
126
- end
127
- if res
128
- db = get_mysql_handle
129
- db.execute("begin")
130
- rows = db.execute("select master_lock from locks for update")
131
- master = rows.fetch[0]
132
- rows.finish
133
- db.do("update locks set master_lock = '#{self_monitor_url}'")
134
- @master = self_monitor_url
135
- cancel_master_check_timer
136
- db.do("commit")
137
- end
138
- res
139
- end
140
-
141
- def notify_awsm
142
- Log.write "Notifying awsm that I won"
143
- res = call_api("promote_instance_to_master", :instance_id => instance_id)
144
- case res['status']
145
- when 'ok'
146
- true
147
- when 'already_promoted'
148
- am_i_master?
149
- EM.add_timer(600) { setup_master_check_timer unless am_i_master? }
150
- true
151
- else
152
- false
153
- end
154
- end
155
-
156
- def instance_id
157
- @instance_id ||= open("http://169.254.169.254/latest/meta-data/instance-id").read
158
- end
159
-
160
- def private_dns_name
161
- @private_dns_name ||= open("http://169.254.169.254/latest/meta-data/local-hostname").read
162
- end
163
-
164
- def self_monitor_url
165
- "http://#{private_dns_name}/haproxy/monitor"
166
- end
167
-
168
- def steal_ip
169
- if @ec2.disassociate_address(public_ip)
170
- @ec2.associate_address(instance_id, public_ip)
171
- end
172
- end
173
-
174
- def public_ip
175
- @public_ip ||= @json['master_app_server']['public_ip']
176
- end
177
-
178
- def get_local_json
179
- @json = JSON.parse(File.read("/etc/chef/dna.json"))
180
- end
181
-
182
- def get_master_from_json
183
- if host = @json['master_app_server']['private_dns_name']
184
- @master = "http://#{host}/haproxy/monitor"
185
- end
186
- end
187
-
188
- end
189
- end
190
-