ey_stonith 0.1.4 → 0.1.5.pre

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.
Files changed (41) hide show
  1. data/bin/ey-monitor +2 -5
  2. data/bin/{ey-monitor-reset → stonith} +1 -1
  3. data/bin/{ey-monitor-stop → stonith-check} +1 -1
  4. data/bin/stonith-claim +5 -0
  5. data/bin/{ey-monitor-resume → stonith-cron} +1 -1
  6. data/bin/stonith-notify +5 -0
  7. data/bin/stonith-reset +5 -0
  8. data/bin/stonith-resume +5 -0
  9. data/bin/stonith-status +5 -0
  10. data/bin/{ey-monitor-status → stonith-stop} +1 -1
  11. data/bin/stonith-takeover +5 -0
  12. data/lib/ey_stonith/address_stealer.rb +1 -6
  13. data/lib/ey_stonith/awsm_notifier.rb +28 -29
  14. data/lib/ey_stonith/check_recorder.rb +19 -17
  15. data/lib/ey_stonith/commands/abstract.rb +94 -0
  16. data/lib/ey_stonith/commands/check.rb +58 -0
  17. data/lib/ey_stonith/commands/claim.rb +113 -0
  18. data/lib/ey_stonith/commands/commands.rb +26 -0
  19. data/lib/ey_stonith/commands/cron.rb +40 -0
  20. data/lib/ey_stonith/commands/help.rb +16 -0
  21. data/lib/ey_stonith/commands/not_found.rb +11 -0
  22. data/lib/ey_stonith/commands/notify.rb +85 -0
  23. data/lib/ey_stonith/commands/reset.rb +21 -0
  24. data/lib/ey_stonith/commands/resume.rb +19 -0
  25. data/lib/ey_stonith/commands/status.rb +23 -0
  26. data/lib/ey_stonith/commands/stop.rb +21 -0
  27. data/lib/ey_stonith/commands/takeover.rb +106 -0
  28. data/lib/ey_stonith/commands.rb +40 -0
  29. data/lib/ey_stonith/config.rb +107 -14
  30. data/lib/ey_stonith/data.rb +5 -1
  31. data/lib/ey_stonith/database.rb +28 -6
  32. data/lib/ey_stonith/history.rb +1 -1
  33. data/lib/ey_stonith.rb +2 -8
  34. metadata +57 -61
  35. data/lib/ey_stonith/abstract_master.rb +0 -15
  36. data/lib/ey_stonith/box.rb +0 -61
  37. data/lib/ey_stonith/cli.rb +0 -138
  38. data/lib/ey_stonith/local_master.rb +0 -28
  39. data/lib/ey_stonith/master.rb +0 -37
  40. data/lib/ey_stonith/meta_data.rb +0 -11
  41. data/lib/ey_stonith/slave.rb +0 -41
metadata CHANGED
@@ -1,12 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ey_stonith
3
3
  version: !ruby/object:Gem::Version
4
- prerelease: false
4
+ prerelease: true
5
5
  segments:
6
6
  - 0
7
7
  - 1
8
- - 4
9
- version: 0.1.4
8
+ - 5
9
+ - pre
10
+ version: 0.1.5.pre
10
11
  platform: ruby
11
12
  authors:
12
13
  - Ezra Zygmuntowicz
@@ -16,25 +17,24 @@ autorequire:
16
17
  bindir: bin
17
18
  cert_chain: []
18
19
 
19
- date: 2010-03-23 00:00:00 -07:00
20
+ date: 2010-04-14 00:00:00 -07:00
20
21
  default_executable:
21
22
  dependencies:
22
23
  - !ruby/object:Gem::Dependency
23
- name: json
24
- prerelease: false
25
- requirement: &id001 !ruby/object:Gem::Requirement
24
+ type: :runtime
25
+ version_requirements: &id001 !ruby/object:Gem::Requirement
26
26
  requirements:
27
27
  - - ">="
28
28
  - !ruby/object:Gem::Version
29
29
  segments:
30
30
  - 0
31
31
  version: "0"
32
- type: :runtime
33
- version_requirements: *id001
34
- - !ruby/object:Gem::Dependency
35
- name: fog
32
+ requirement: *id001
33
+ name: json
36
34
  prerelease: false
37
- requirement: &id002 !ruby/object:Gem::Requirement
35
+ - !ruby/object:Gem::Dependency
36
+ type: :runtime
37
+ version_requirements: &id002 !ruby/object:Gem::Requirement
38
38
  requirements:
39
39
  - - "="
40
40
  - !ruby/object:Gem::Version
@@ -43,38 +43,12 @@ dependencies:
43
43
  - 0
44
44
  - 58
45
45
  version: 0.0.58
46
- type: :runtime
47
- version_requirements: *id002
48
- - !ruby/object:Gem::Dependency
49
- name: eventmachine
46
+ requirement: *id002
47
+ name: fog
50
48
  prerelease: false
51
- requirement: &id003 !ruby/object:Gem::Requirement
52
- requirements:
53
- - - ">="
54
- - !ruby/object:Gem::Version
55
- segments:
56
- - 0
57
- version: "0"
58
- type: :runtime
59
- version_requirements: *id003
60
49
  - !ruby/object:Gem::Dependency
61
- name: em-http-request
62
- prerelease: false
63
- requirement: &id004 !ruby/object:Gem::Requirement
64
- requirements:
65
- - - ~>
66
- - !ruby/object:Gem::Version
67
- segments:
68
- - 0
69
- - 2
70
- - 7
71
- version: 0.2.7
72
50
  type: :runtime
73
- version_requirements: *id004
74
- - !ruby/object:Gem::Dependency
75
- name: redis
76
- prerelease: false
77
- requirement: &id005 !ruby/object:Gem::Requirement
51
+ version_requirements: &id003 !ruby/object:Gem::Requirement
78
52
  requirements:
79
53
  - - ~>
80
54
  - !ruby/object:Gem::Version
@@ -83,42 +57,62 @@ dependencies:
83
57
  - 1
84
58
  - 2
85
59
  version: 0.1.2
86
- type: :runtime
87
- version_requirements: *id005
60
+ requirement: *id003
61
+ name: redis
62
+ prerelease: false
88
63
  description: Shoot The Other Node In The Head
89
64
  email: awsmdev@engineyard.com
90
65
  executables:
91
66
  - ey-monitor
92
- - ey-monitor-stop
93
- - ey-monitor-status
94
- - ey-monitor-resume
95
- - ey-monitor-reset
67
+ - stonith
68
+ - stonith-check
69
+ - stonith-claim
70
+ - stonith-cron
71
+ - stonith-notify
72
+ - stonith-reset
73
+ - stonith-resume
74
+ - stonith-status
75
+ - stonith-stop
76
+ - stonith-takeover
96
77
  extensions: []
97
78
 
98
79
  extra_rdoc_files:
99
80
  - README.rdoc
100
81
  - LICENSE
101
82
  files:
102
- - lib/ey_stonith/abstract_master.rb
103
83
  - lib/ey_stonith/address_stealer.rb
104
84
  - lib/ey_stonith/awsm_notifier.rb
105
- - lib/ey_stonith/box.rb
106
85
  - lib/ey_stonith/check_recorder.rb
107
- - lib/ey_stonith/cli.rb
86
+ - lib/ey_stonith/commands/abstract.rb
87
+ - lib/ey_stonith/commands/check.rb
88
+ - lib/ey_stonith/commands/claim.rb
89
+ - lib/ey_stonith/commands/commands.rb
90
+ - lib/ey_stonith/commands/cron.rb
91
+ - lib/ey_stonith/commands/help.rb
92
+ - lib/ey_stonith/commands/not_found.rb
93
+ - lib/ey_stonith/commands/notify.rb
94
+ - lib/ey_stonith/commands/reset.rb
95
+ - lib/ey_stonith/commands/resume.rb
96
+ - lib/ey_stonith/commands/status.rb
97
+ - lib/ey_stonith/commands/stop.rb
98
+ - lib/ey_stonith/commands/takeover.rb
99
+ - lib/ey_stonith/commands.rb
108
100
  - lib/ey_stonith/config.rb
109
101
  - lib/ey_stonith/data.rb
110
102
  - lib/ey_stonith/database.rb
111
103
  - lib/ey_stonith/history.rb
112
- - lib/ey_stonith/local_master.rb
113
- - lib/ey_stonith/master.rb
114
- - lib/ey_stonith/meta_data.rb
115
- - lib/ey_stonith/slave.rb
116
104
  - lib/ey_stonith.rb
117
105
  - bin/ey-monitor
118
- - bin/ey-monitor-reset
119
- - bin/ey-monitor-resume
120
- - bin/ey-monitor-status
121
- - bin/ey-monitor-stop
106
+ - bin/stonith
107
+ - bin/stonith-check
108
+ - bin/stonith-claim
109
+ - bin/stonith-cron
110
+ - bin/stonith-notify
111
+ - bin/stonith-reset
112
+ - bin/stonith-resume
113
+ - bin/stonith-status
114
+ - bin/stonith-stop
115
+ - bin/stonith-takeover
122
116
  - README.rdoc
123
117
  - LICENSE
124
118
  has_rdoc: true
@@ -139,11 +133,13 @@ required_ruby_version: !ruby/object:Gem::Requirement
139
133
  version: "0"
140
134
  required_rubygems_version: !ruby/object:Gem::Requirement
141
135
  requirements:
142
- - - ">="
136
+ - - ">"
143
137
  - !ruby/object:Gem::Version
144
138
  segments:
145
- - 0
146
- version: "0"
139
+ - 1
140
+ - 3
141
+ - 1
142
+ version: 1.3.1
147
143
  requirements: []
148
144
 
149
145
  rubyforge_project:
@@ -1,15 +0,0 @@
1
- require 'json'
2
- require 'json/ext'
3
- module EY
4
- module Stonith
5
- class AbstractMaster
6
- private
7
-
8
- # ips are elastic, do not cache!
9
- def public_ip() meta_data('public-ipv4') end
10
- def local_hostname() @local_hostname ||= meta_data("local-hostname") end
11
-
12
- def meta_data(key) EY::Stonith.meta_data[key] end
13
- end
14
- end
15
- end
@@ -1,61 +0,0 @@
1
- module EY
2
- module Stonith
3
- class Box
4
- def initialize(config, history)
5
- EY::Stonith.logger.info "Booting Stonith"
6
-
7
- @config, @history = config, history
8
- database = Database.new(@config)
9
- @master = Master.new(database, @config.master_hostname_from_dna)
10
-
11
- trap("HUP") { stop }
12
- trap("USR1") do
13
- stop
14
- EM.next_tick { start }
15
- end
16
- end
17
-
18
- def start
19
- if @master.local?
20
- @local_master = LocalMaster.new(@config.notify_uri, @config.cloud_credentials)
21
- @master.update @local_master.data
22
- @history << :claim
23
- else
24
- @slave = Slave.new(self, @config.monitor_heartbeat)
25
- @slave.monitor!(@master)
26
- @history << :monitor
27
- end
28
- end
29
-
30
- def try_takeover(master_unchanged)
31
- @master.with_locked_data do |data|
32
- if master_unchanged.call(data.key)
33
- begin
34
- Stonith.logger.info("Locked! Taking over.")
35
- @slave = nil
36
- @history << :takeover
37
- @local_master = LocalMaster.new(@config.notify_uri, @config.cloud_credentials)
38
- new_data = @local_master.takeover!(data.instance_id, data.ip)
39
- @master.update new_data
40
- ensure
41
- @history << :done
42
- end
43
- else
44
- Stonith.logger.info("Failed to grab lock, relenting.")
45
- @slave.start!
46
- @history << :relent
47
- end
48
- end
49
- end
50
-
51
- private
52
-
53
- def stop
54
- EM.next_tick {
55
- @slave.stop! if @slave
56
- @history << :stop
57
- }
58
- end
59
- end
60
- end
61
- end
@@ -1,138 +0,0 @@
1
- require 'eventmachine'
2
- require 'optparse'
3
- require 'pathname'
4
-
5
- module EY
6
- module Stonith
7
- class CLI
8
- DEFAULT_FILES = {
9
- :ey => "/etc/.ey-cloud.yml",
10
- :redis => "/etc/redis.yml",
11
- :dna => "/etc/chef/dna.json",
12
- :history => "/var/run/ey-monitor.history",
13
- :pid_path => "/var/run/ey-monitor.pid",
14
- :log_path => "/var/log/ey-monitor.log",
15
- }
16
-
17
- def self.commands
18
- @commands ||= Hash.new do |commands, command|
19
- lambda {
20
- puts "Command not found: #{command}"
21
- puts @parser
22
- exit(1)
23
- }
24
- end
25
- end
26
-
27
- def self.command(cmd,&block)
28
- commands[cmd.to_sym] = block
29
- end
30
-
31
- command :start do
32
- with_pid do
33
- Stonith.meta_data = @options[:meta_data] if @options[:meta_data]
34
- Stonith.logger = Logger.new(@config.log_path)
35
- Stonith.logger.level = Logger::INFO
36
- begin
37
- EM.run { Box.new(@config, @history).start }
38
- rescue Exception => e
39
- Stonith.logger.info "#{e.class.to_s}: #{e.message}\n#{e.backtrace.join("\n")}"
40
- end
41
- end
42
- end
43
-
44
- command :stop do
45
- system("kill -HUP #{get_pid}")
46
- sleep(1) until @history.last == "stop"
47
- puts "takeover" if @history.include?(:takeover)
48
- end
49
-
50
- command :resume do
51
- system("kill -USR1 #{get_pid}")
52
- end
53
-
54
- command :status do
55
- puts @history
56
- end
57
-
58
- command :reset do
59
- Database.new(@config).reset
60
- @history.reset
61
- end
62
-
63
- def initialize(command, argv)
64
- parse!(argv)
65
- @config = Config.new(@options[:ey], @options[:redis], @options[:dna], @options[:history], @options[:pid_path], @options[:log_path])
66
- cmd = command ? command.to_sym : :start
67
- @history = History.new(@config.history_path)
68
- instance_eval(&self.class.commands[cmd.to_sym])
69
- end
70
-
71
- def with_pid
72
- @config.pid_path.open('w') { |file| file << $$ }
73
- yield
74
- @config.pid_path.delete
75
- end
76
-
77
- def get_pid
78
- @config.pid_path.read
79
- end
80
-
81
- def parse!(argv)
82
- @options = DEFAULT_FILES
83
- parser.parse!(argv)
84
- end
85
-
86
- def parser
87
- @parser ||= OptionParser.new do |parser|
88
- parser.banner = <<-USAGE
89
- Usage: ey-monitor [FLAGS] [COMMAND]
90
-
91
- COMMANDS
92
- start Begin monitoring (default).
93
- stop Safely stop running ey-monitor agents.
94
- Reports shutdown status to stdout.
95
- Exits with non-zero status if there is a problem.
96
-
97
- USAGE
98
-
99
- parser.separator "FLAGS"
100
-
101
- parser.on('-e', '--ey [FILE]', "Path to the ey-cloud.yml file (default #{@options[:ey]})") do |ey|
102
- @options[:ey] = Pathname.new(ey)
103
- end
104
-
105
- parser.on('-r', '--redis [FILE]', "Path to the redis.yml file (default #{@options[:redis]})") do |redis|
106
- @options[:redis] = Pathname.new(redis)
107
- end
108
-
109
- parser.on('-d', '--dna [FILE]', "Path to the chef/dna.json file (default #{@options[:dna]})") do |dna|
110
- @options[:dna] = Pathname.new(dna)
111
- end
112
-
113
- parser.on('-m', '--meta-data [FILE]', "Mocked AWS meta_data yaml file") do |path|
114
- @options[:meta_data] = YAML.load_file(Pathname.new(path))
115
- end
116
-
117
- parser.on('-t', '--history [FILE]', "Location of stonith history file (default #{@options[:history]}") do |path|
118
- @options[:history] = Pathname.new(path)
119
- end
120
-
121
- parser.on('-p', '--pid [FILE]', "Location of stonith pid file (default #{@options[:pid_path]}") do |path|
122
- @options[:pid_path] = Pathname.new(path)
123
- end
124
-
125
- parser.on('-l', '--log [FILE]', "Location of stonith log file (default #{@options[:log_path]}") do |path|
126
- @options[:log_path] = Pathname.new(path)
127
- end
128
-
129
- parser.on_tail("-h", "--help", "Show this message") do
130
- puts parser
131
- exit
132
- end
133
- end
134
- end
135
- end
136
- end
137
- end
138
-
@@ -1,28 +0,0 @@
1
- require 'open-uri'
2
- require 'fog'
3
-
4
- module EY
5
- module Stonith
6
- class LocalMaster < AbstractMaster
7
- def initialize(notify_uri, cloud_credentials)
8
- @notify_uri, @cloud_credentials = notify_uri, cloud_credentials
9
- end
10
- alias hostname local_hostname
11
-
12
- def takeover!(master_instance_id, master_ip)
13
- address = AddressStealer.new(master_instance_id, master_ip, @cloud_credentials)
14
- address.associate(instance_id)
15
- AwsmNotifier.new(instance_id, @notify_uri, @cloud_credentials)
16
- data(address.ip)
17
- end
18
-
19
- def data(ip = public_ip)
20
- Data.new(hostname, instance_id, ip)
21
- end
22
-
23
- private
24
-
25
- def instance_id() @instance_id ||= EY::Stonith.meta_data["instance-id"] end
26
- end
27
- end
28
- end
@@ -1,37 +0,0 @@
1
- require 'ey_stonith'
2
- require 'eventmachine'
3
- require 'em-http'
4
-
5
- module EY
6
- module Stonith
7
- class Master < AbstractMaster
8
- def initialize(database, hostname_from_dna)
9
- @database, @hostname_from_dna = database, hostname_from_dna
10
- end
11
-
12
- def check(good, bad)
13
- @database.with_data do |data|
14
- http = EM::HttpRequest.new("http://#{data.hostname}/haproxy/monitor").get :timeout => 10
15
- http.callback {
16
- unless http.response_header.status == 200
17
- bad.call data.key
18
- else
19
- good.call data.key
20
- end
21
- }
22
- http.errback { bad.call data.key }
23
- end
24
- end
25
-
26
- def local?() hostname == local_hostname end
27
- def hostname() hostname_from_db || hostname_from_dna end
28
- def with_locked_data(&block) @database.with_locked_data(&block) end
29
- def update(data) @database.set(data) end
30
-
31
- private
32
-
33
- attr_reader :hostname_from_dna
34
- def hostname_from_db() @database.with_data { |data| data.hostname } end
35
- end
36
- end
37
- end
@@ -1,11 +0,0 @@
1
- require 'open-uri'
2
-
3
- module EY
4
- module Stonith
5
- module MetaData
6
- def self.[](key)
7
- open("http://169.254.169.254/latest/meta-data/#{key}").read
8
- end
9
- end
10
- end
11
- end
@@ -1,41 +0,0 @@
1
- module EY
2
- module Stonith
3
- class Slave
4
- def initialize(box, heartbeat)
5
- @box, @heartbeat = box, heartbeat
6
- end
7
-
8
- def monitor!(master)
9
- return if @checking
10
- Stonith.logger.info "Monitoring started"
11
- @check_recorder = CheckRecorder.new
12
- @checking = EM.add_periodic_timer(@heartbeat) { check(master) }
13
- end
14
-
15
- def stop!
16
- if @checking
17
- Stonith.logger.info "Stopped: Not monitoring until SIGUSR1 received"
18
- @checking.cancel
19
- @checking = nil
20
- end
21
- end
22
-
23
- private
24
-
25
- def check(master)
26
- good = lambda { |master_key| @check_recorder.good_check!(master_key) }
27
- bad = lambda { |master_key|
28
- @check_recorder.bad_check!(master_key)
29
- takeover! if @check_recorder.limit_exceeded?
30
- }
31
- master.check(good, bad)
32
- end
33
-
34
- def takeover!
35
- Stonith.logger.info("Trying to grab the lock for takeover")
36
- stop!
37
- @box.try_takeover(@check_recorder.method(:checking_key?))
38
- end
39
- end
40
- end
41
- end