auser-poolparty 1.2.11 → 1.2.12
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.
- data/README.txt +2 -1
- data/VERSION.yml +1 -1
- data/examples/metavirt_cloud.rb +1 -1
- data/lib/poolparty/core/array.rb +12 -0
- data/lib/poolparty/modules/searchable_paths.rb +6 -1
- data/lib/poolparty/modules/user_helpers.rb +1 -1
- data/lib/poolparty/monitors/base_monitor.rb +49 -1
- data/lib/poolparty/monitors/monitor_daemon.rb +49 -40
- data/lib/poolparty/monitors/monitor_rack.rb +5 -1
- data/lib/poolparty/monitors/monitors/cloud_monitor.rb +34 -0
- data/lib/poolparty/monitors/monitors/elections_monitor.rb +47 -20
- data/lib/poolparty/monitors/monitors/stats_monitor.rb +26 -35
- data/lib/poolparty/net/remoter_base.rb +4 -0
- data/lib/poolparty/net/remoter_bases/vmrun/vmrun_instance.rb +4 -0
- data/lib/poolparty/plugins/apache2/php5.rb +1 -1
- data/lib/poolparty/plugins/sshkey.rb +2 -1
- data/lib/poolparty/poolparty/cloud.rb +1 -1
- data/lib/poolparty/poolparty/pool.rb +10 -1
- data/lib/poolparty/provision/boot_strapper.rb +7 -11
- data/lib/poolparty/provision/dr_configure.rb +4 -0
- data/lib/poolparty/templates/monitor.ru +1 -1
- data/spec/poolparty/poolparty/key_spec.rb +1 -1
- data/tasks/spec.rake +1 -1
- data/test/poolparty/core/array_test.rb +11 -0
- metadata +3 -2
data/README.txt
CHANGED
@@ -63,4 +63,5 @@ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
63
63
|
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
64
64
|
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
65
65
|
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
66
|
-
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
66
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
67
|
+
|
data/VERSION.yml
CHANGED
data/examples/metavirt_cloud.rb
CHANGED
data/lib/poolparty/core/array.rb
CHANGED
@@ -7,6 +7,18 @@ class Array
|
|
7
7
|
map {|a| a.to_os }
|
8
8
|
end
|
9
9
|
|
10
|
+
def histogram
|
11
|
+
out = {}
|
12
|
+
map do |ele|
|
13
|
+
if out.has_key?(ele)
|
14
|
+
out[ele] += 1
|
15
|
+
else
|
16
|
+
out.merge!(ele => 1)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
out
|
20
|
+
end
|
21
|
+
|
10
22
|
def collect_with_index &block
|
11
23
|
self.enum_for(:each_with_index).collect &block
|
12
24
|
end
|
@@ -47,7 +47,7 @@ module PoolParty
|
|
47
47
|
# * /etc/poolparty
|
48
48
|
# * /var/poolparty
|
49
49
|
def default_paths
|
50
|
-
[
|
50
|
+
@default_searchable_paths ||= [
|
51
51
|
Dir.pwd,
|
52
52
|
PoolParty::Default.poolparty_home_path,
|
53
53
|
PoolParty::Default.base_keypair_path,
|
@@ -58,6 +58,11 @@ module PoolParty
|
|
58
58
|
]
|
59
59
|
end
|
60
60
|
|
61
|
+
def add_searchable_path(path)
|
62
|
+
default_paths # instantiate @default_searchable_paths
|
63
|
+
@default_searchable_paths << path
|
64
|
+
end
|
65
|
+
|
61
66
|
# returns the full set of valid searchable paths, given the options
|
62
67
|
def searchable_paths
|
63
68
|
return @paths_override if @paths_override && @paths_override.size > 0
|
@@ -12,7 +12,7 @@ module PoolParty
|
|
12
12
|
# Add to the suitcase files below the clouds.rb base directory
|
13
13
|
def pack_user_directory(dirname)
|
14
14
|
begin
|
15
|
-
::Suitcase::Zipper.add("#{::File.dirname($pool_specfile)}/#{dirname}", "etc")
|
15
|
+
::Suitcase::Zipper.add("#{::File.dirname($pool_specfile)}/#{dirname}", "/etc/poolparty")
|
16
16
|
rescue Exception => e
|
17
17
|
vputs "Error packing user directory #{dirname}: #{e}"
|
18
18
|
end
|
@@ -12,15 +12,24 @@ module Monitors
|
|
12
12
|
end
|
13
13
|
|
14
14
|
class BaseMonitor
|
15
|
+
attr_reader :log_file, :log_file_path, :last_cloud_loaded_time
|
15
16
|
|
16
17
|
def self.inherited(subclass)
|
17
18
|
unless Monitors.available.include?(subclass)
|
18
|
-
Monitors.available << subclass
|
19
|
+
Monitors.available << subclass unless subclass.to_s =~ /MonitorDaemon/
|
19
20
|
end
|
20
21
|
end
|
21
22
|
|
22
23
|
def initialize(env=nil)
|
23
24
|
@env=env
|
25
|
+
log_filename = "poolparty_monitor.log"
|
26
|
+
@log_file_path = "/var/log/poolparty/#{log_filename}"
|
27
|
+
|
28
|
+
unless ::File.file?(log_file_path)
|
29
|
+
::FileUtils.mkdir_p ::File.dirname(log_file_path) unless ::File.directory?(::File.dirname(log_file_path))
|
30
|
+
::File.open(log_file_path, 'a+') {|f| f << "------ #{Time.now} ------"}
|
31
|
+
log_file_path
|
32
|
+
end
|
24
33
|
end
|
25
34
|
|
26
35
|
def env(env=@env)
|
@@ -38,6 +47,22 @@ module Monitors
|
|
38
47
|
|
39
48
|
end
|
40
49
|
|
50
|
+
# Load the cloud
|
51
|
+
# Reload the cloud if necessary after 60 seconds
|
52
|
+
# of cache time
|
53
|
+
def my_cloud
|
54
|
+
@my_cloud = nil if last_cloud_loaded_time && last_cloud_loaded_time > 60
|
55
|
+
@my_cloud ||= begin
|
56
|
+
require '/etc/poolparty/clouds.rb'
|
57
|
+
name = open("/etc/poolparty/cloud_name").read
|
58
|
+
last_cloud_loaded_time = Time.now.to_i
|
59
|
+
clouds[name.chomp.to_sym]
|
60
|
+
rescue Exception => e
|
61
|
+
JSON.parse( open('/etc/poolparty/clouds.json' ).read )
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
|
41
66
|
def before_close_callbacks
|
42
67
|
@before_close_callbacks ||= []
|
43
68
|
end
|
@@ -45,5 +70,28 @@ module Monitors
|
|
45
70
|
@after_close_callbacks ||= []
|
46
71
|
end
|
47
72
|
|
73
|
+
def log(msg)
|
74
|
+
log_file.flush
|
75
|
+
log_file << "[INFO] - #{Time.now} -- #{msg}\n"
|
76
|
+
end
|
77
|
+
|
78
|
+
private
|
79
|
+
|
80
|
+
def log_file
|
81
|
+
if @logfile
|
82
|
+
@logfile
|
83
|
+
else
|
84
|
+
begin
|
85
|
+
::FileUtils.mkdir_p ::File.dirname(log_file_path) unless ::File.directory?(::File.dirname(log_file_path))
|
86
|
+
@logfile ||= ::File.open(log_file_path, 'a+')
|
87
|
+
rescue Exception => e
|
88
|
+
puts "ERROR: #{e.inspect}"
|
89
|
+
@logfile = $stdout
|
90
|
+
end
|
91
|
+
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
|
48
96
|
end
|
49
97
|
end
|
@@ -1,9 +1,11 @@
|
|
1
1
|
require "open-uri"
|
2
|
+
require "json"
|
3
|
+
require "#{::File.dirname(__FILE__)}/base_monitor"
|
2
4
|
|
3
5
|
module PoolParty
|
4
|
-
class MonitorDaemon
|
6
|
+
class MonitorDaemon < Monitors::BaseMonitor
|
5
7
|
|
6
|
-
attr_reader :should_daemonize, :pid_file, :
|
8
|
+
attr_reader :should_daemonize, :pid_file, :sleep_time
|
7
9
|
|
8
10
|
def self.run(o={})
|
9
11
|
new(o).run
|
@@ -12,23 +14,32 @@ module PoolParty
|
|
12
14
|
def initialize(o={})
|
13
15
|
@should_daemonize = o.delete(:daemonize)
|
14
16
|
@pid_file = o.delete(:daemonize) || "/tmp/poolparty_monitor.pid"
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
unless ::File.file?(temp_log_file_path)
|
19
|
-
::FileUtils.mkdir_p ::File.dirname(temp_log_file_path) unless ::File.directory?(::File.dirname(temp_log_file_path))
|
20
|
-
::File.open(temp_log_file_path, 'a+')
|
21
|
-
temp_log_file_path
|
22
|
-
end
|
23
|
-
@sleep_time = o.delete(:sleep_time) || 5
|
17
|
+
@sleep_time = o.delete(:sleep_time) || 20
|
18
|
+
|
19
|
+
super
|
24
20
|
end
|
25
21
|
|
26
22
|
def pass_the_baton
|
27
|
-
|
28
|
-
|
29
|
-
|
23
|
+
# Handle stats
|
24
|
+
my_nominations = JSON.parse(open("http://localhost:8642/stats/get_nominations").read)
|
25
|
+
unless my_nominations.empty?
|
26
|
+
running_nodes = my_cloud.nodes(:status => "running")
|
27
|
+
nominations = []
|
28
|
+
running_nodes.each do |node|
|
29
|
+
timeout(10) do
|
30
|
+
log "Checking with #{node.internal_ip} for nominations: #{open("http://#{node.internal_ip}:8642/stats/get_nominations").read}"
|
31
|
+
nominations << begin
|
32
|
+
JSON.parse(open("http://#{node.internal_ip}:8642/stats/nominations").read) || "none"
|
33
|
+
rescue
|
34
|
+
log "Error when connecting to #{node.internal_ip}: #{e.inspect}"
|
35
|
+
"none"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
log "Sending #{nominations.flatten.to_json} to #{server["/elections"].inspect}"
|
40
|
+
# put to "http://localhost:8642/elections/handle_election", data => nominations.to_json
|
41
|
+
server["/elections"].put(nominations.flatten.to_json)
|
30
42
|
end
|
31
|
-
sleep sleep_time
|
32
43
|
end
|
33
44
|
|
34
45
|
def run
|
@@ -37,7 +48,14 @@ module PoolParty
|
|
37
48
|
daemonize
|
38
49
|
else
|
39
50
|
log "Starting MonitorDaemon"
|
40
|
-
loop {
|
51
|
+
loop {
|
52
|
+
begin
|
53
|
+
pass_the_baton
|
54
|
+
rescue Exception => e
|
55
|
+
log "There was an error with pass_the_baton: #{e}"
|
56
|
+
end
|
57
|
+
sleep sleep_time
|
58
|
+
}
|
41
59
|
end
|
42
60
|
end
|
43
61
|
|
@@ -71,29 +89,7 @@ module PoolParty
|
|
71
89
|
|
72
90
|
Process.detach(pid)
|
73
91
|
end
|
74
|
-
|
75
|
-
def log(msg)
|
76
|
-
log_file.flush
|
77
|
-
log_file << "[INFO] - #{Time.now} -- #{msg}\n"
|
78
|
-
end
|
79
|
-
|
80
|
-
private
|
81
|
-
|
82
|
-
def log_file
|
83
|
-
if @logfile
|
84
|
-
@logfile
|
85
|
-
else
|
86
|
-
begin
|
87
|
-
::FileUtils.mkdir_p ::File.dirname(log_file_path) unless ::File.directory?(::File.dirname(log_file_path))
|
88
|
-
@logfile ||= ::File.open(log_file_path, 'a+')
|
89
|
-
rescue Exception => e
|
90
|
-
puts "ERROR: #{e.inspect}"
|
91
|
-
@logfile = $stdout
|
92
|
-
end
|
93
92
|
|
94
|
-
end
|
95
|
-
end
|
96
|
-
|
97
93
|
def pid
|
98
94
|
@pid ||= File.file?(pid_file) ? open(pid_file).read.to_i : nil
|
99
95
|
end
|
@@ -132,7 +128,7 @@ module PoolParty
|
|
132
128
|
puts "process not found!"
|
133
129
|
nil
|
134
130
|
end
|
135
|
-
|
131
|
+
|
136
132
|
protected
|
137
133
|
def remove_pid_file
|
138
134
|
File.delete(pid_file) if pid_file && File.exists?(pid_file)
|
@@ -153,7 +149,20 @@ module PoolParty
|
|
153
149
|
end
|
154
150
|
end
|
155
151
|
end
|
156
|
-
|
152
|
+
|
153
|
+
def server
|
154
|
+
if @server
|
155
|
+
@server
|
156
|
+
else
|
157
|
+
opts = { :content_type =>'application/json',
|
158
|
+
:accept => 'application/json',
|
159
|
+
:host => 'http://localhost',
|
160
|
+
:port => '8642'
|
161
|
+
}
|
162
|
+
@uri = "#{opts.delete(:host)}:#{opts.delete(:port)}"
|
163
|
+
@server = RestClient::Resource.new( @uri, opts)
|
164
|
+
end
|
165
|
+
end
|
157
166
|
|
158
167
|
end
|
159
168
|
end
|
@@ -45,7 +45,11 @@ module Monitors
|
|
45
45
|
begin
|
46
46
|
path_array= path_map(env['REQUEST_PATH']) || []
|
47
47
|
verb = env['REQUEST_METHOD'].downcase
|
48
|
-
|
48
|
+
|
49
|
+
new_body = map_to_method(path_array, verb)
|
50
|
+
new_body = new_body.to_json unless (!path_array || path_array.empty? || path_array[0].nil?)
|
51
|
+
|
52
|
+
@response.write new_body
|
49
53
|
setup_callbacks
|
50
54
|
|
51
55
|
# rescue Exception=>e
|
@@ -0,0 +1,34 @@
|
|
1
|
+
=begin rdoc
|
2
|
+
Cloud monitor just is a test monitor to hold cloud info
|
3
|
+
=end
|
4
|
+
|
5
|
+
module Monitors
|
6
|
+
|
7
|
+
class Cloud < BaseMonitor
|
8
|
+
|
9
|
+
def get(_unused=nil)
|
10
|
+
<<-EOE
|
11
|
+
#{my_cloud.name}
|
12
|
+
#{my_cloud.minimum_instances}..#{my_cloud.maximum_instances}
|
13
|
+
EOE
|
14
|
+
end
|
15
|
+
|
16
|
+
def nominations(_unused=nil)
|
17
|
+
running_nodes = my_cloud.nodes(:status => "running")
|
18
|
+
nominations = []
|
19
|
+
running_nodes.each do |node|
|
20
|
+
timeout(10) do
|
21
|
+
log "Checking with #{node.internal_ip} for nominations: #{open("http://#{node.internal_ip}:8642/stats/get_nominations").read}"
|
22
|
+
nominations << begin
|
23
|
+
JSON.parse(open("http://#{node.internal_ip}:8642/stats/nominations").read) || "none"
|
24
|
+
rescue
|
25
|
+
log "Error when connecting to #{node.internal_ip}: #{e.inspect}"
|
26
|
+
"none"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end.histogram
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
@@ -1,11 +1,28 @@
|
|
1
1
|
module Monitors
|
2
2
|
class Elections < BaseMonitor
|
3
3
|
|
4
|
+
# these are the rules that define the
|
5
|
+
# elected actions
|
6
|
+
def self.candidates
|
7
|
+
{
|
8
|
+
:expand => :contract,
|
9
|
+
:contract => :expand,
|
10
|
+
:configure => nil,
|
11
|
+
:none => nil
|
12
|
+
}
|
13
|
+
end
|
14
|
+
|
4
15
|
def get(data=nil)
|
5
16
|
'hello'
|
6
17
|
end
|
7
18
|
|
8
|
-
def
|
19
|
+
def put(data=nil)
|
20
|
+
elections = JSON.parse(data)
|
21
|
+
log "Received #{elections.histogram.inspect} in Elections Monitor"
|
22
|
+
handle_election(elections.histogram)
|
23
|
+
end
|
24
|
+
|
25
|
+
def count_ballots(ballots={}, candidates={:expand => 0, :contract => 0})
|
9
26
|
# Ballots look like:
|
10
27
|
# {host => ["contract"]}
|
11
28
|
# Count the number of nominations for each candidate action
|
@@ -20,29 +37,39 @@ module Monitors
|
|
20
37
|
end
|
21
38
|
|
22
39
|
# Handle the elections
|
23
|
-
|
24
|
-
|
40
|
+
# ballots: {"contract" => 1, "expand" => 4}
|
41
|
+
def handle_election(ballots={})
|
25
42
|
# Expand the cloud if 50+% of the votes are for expansion
|
26
43
|
# Contract the cloud if 51+% of the votes are for contraction
|
27
|
-
# Check to make sure an elected action is not already in progress
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
44
|
+
# Check to make sure an elected action is not already in progress
|
45
|
+
log "handle_election: #{ballots.inspect}"
|
46
|
+
ballots.symbolize_keys!
|
47
|
+
total_votes = ballots.inject(0) {|total, arr| total += arr[1] }
|
48
|
+
|
49
|
+
ballots.each do |ballot, pro_votes|
|
50
|
+
contra = self.class.candidates[ballot]
|
51
|
+
con_votes = ballots[contra] || 0
|
52
|
+
|
53
|
+
if (pro_votes - con_votes)/total_votes > 0.5
|
54
|
+
return run_elected_action(ballot)
|
55
|
+
end
|
34
56
|
end
|
35
|
-
|
36
|
-
reload_data!
|
37
|
-
stats[my_ip]["elected_action"] = @elected_action if @elected_action
|
38
|
-
log << "#{Time.now.strftime("%Y-%m-%d-%H-%M")}, #{stats.to_json}\n"
|
39
|
-
stats.to_json
|
40
57
|
end
|
41
|
-
|
42
|
-
def
|
43
|
-
|
44
|
-
|
45
|
-
|
58
|
+
|
59
|
+
def run_elected_action(ballot)
|
60
|
+
log "Electing #{ballot}"
|
61
|
+
case ballot
|
62
|
+
when :expand
|
63
|
+
my_cloud.running_action = :expanding
|
64
|
+
my_cloud.launch_instance!(:cloud_name => my_cloud.name)
|
65
|
+
my_cloud.running_action = nil
|
66
|
+
when :contract
|
67
|
+
my_cloud.running_action = :contracting
|
68
|
+
my_cloud.terminate_youngest_instance!
|
69
|
+
my_cloud.running_action = nil
|
70
|
+
else
|
71
|
+
"none"
|
72
|
+
end
|
46
73
|
end
|
47
74
|
|
48
75
|
end
|
@@ -26,7 +26,6 @@ module Monitors
|
|
26
26
|
})
|
27
27
|
end
|
28
28
|
make_aska_rules(@cloud["options"]["rules"])
|
29
|
-
log << "#{::Time.now.strftime("%Y-%m-%d-%H-%M")}, #{stats.to_json}\n"
|
30
29
|
end
|
31
30
|
|
32
31
|
def get(data=nil)
|
@@ -36,7 +35,6 @@ module Monitors
|
|
36
35
|
else
|
37
36
|
stats[request.params[0].to_sym] ||= self.send(request.params[0])
|
38
37
|
stats[request.params[0].to_sym]
|
39
|
-
log << "#{::Time.now.strftime("%Y-%m-%d-%H-%M")}, #{stats.to_json}\n"
|
40
38
|
stats.to_json
|
41
39
|
end
|
42
40
|
rescue Exception => e
|
@@ -44,11 +42,16 @@ module Monitors
|
|
44
42
|
end
|
45
43
|
end
|
46
44
|
|
45
|
+
#alias to allow access thru http route GET /stats/nominations
|
46
|
+
def get_nominations(_nodes=[])
|
47
|
+
nominations
|
48
|
+
end
|
49
|
+
|
47
50
|
def put(data)
|
48
51
|
if d = JSON.parse(request.params)
|
49
52
|
hsh = d.reject {|ip, _node| ip == my_ip }
|
50
53
|
stats.merge!(hsh)
|
51
|
-
handle_election
|
54
|
+
# handle_election
|
52
55
|
else
|
53
56
|
"boom"
|
54
57
|
end
|
@@ -57,21 +60,6 @@ module Monitors
|
|
57
60
|
|
58
61
|
protected
|
59
62
|
|
60
|
-
def log(log_file_path="/var/log/poolparty/stats_monitor.log")
|
61
|
-
if @logfile
|
62
|
-
@logfile
|
63
|
-
else
|
64
|
-
begin
|
65
|
-
::File.file? log_file_path
|
66
|
-
::FileUtils.mkdir_p ::File.dirname(log_file_path) unless ::File.directory?(::File.dirname(log_file_path))
|
67
|
-
@logfile ||= ::File.open(log_file_path, 'a+')
|
68
|
-
rescue Exception => e
|
69
|
-
@log_file = $stdout
|
70
|
-
end
|
71
|
-
|
72
|
-
end
|
73
|
-
end
|
74
|
-
|
75
63
|
# Handle the elections
|
76
64
|
def handle_election
|
77
65
|
# Ballots look like:
|
@@ -96,7 +84,7 @@ module Monitors
|
|
96
84
|
|
97
85
|
reload_data!
|
98
86
|
stats[my_ip]["elected_action"] = @elected_action if @elected_action
|
99
|
-
log
|
87
|
+
log "#{Time.now.strftime("%Y-%m-%d-%H-%M")}, #{stats.to_json}\n"
|
100
88
|
stats.to_json
|
101
89
|
end
|
102
90
|
|
@@ -128,9 +116,7 @@ module Monitors
|
|
128
116
|
end
|
129
117
|
|
130
118
|
def instances(_n=nil)
|
131
|
-
|
132
|
-
res ||= %x[server-list-active internal_ip].split("\t")
|
133
|
-
res
|
119
|
+
my_cloud.nodes(:status => "running")
|
134
120
|
end
|
135
121
|
|
136
122
|
def can_expand?(_n=nil)
|
@@ -142,45 +128,50 @@ module Monitors
|
|
142
128
|
end
|
143
129
|
|
144
130
|
def min_instances(_n=nil)
|
145
|
-
(
|
131
|
+
(my_cloud.minimum_instances || PoolParty::Default.minimum_instances).to_i
|
146
132
|
end
|
147
133
|
|
148
134
|
def max_instances(_n=nil)
|
149
|
-
(
|
135
|
+
(my_cloud.maximum_instances || PoolParty::Default.maximum_instances).to_i
|
150
136
|
end
|
151
137
|
|
152
138
|
def nominations(_n=nil)
|
153
139
|
# return ['expand'] if instances.size<min_instances
|
154
140
|
load = stats[my_ip]["load"] ||= self.send(:load)
|
155
|
-
|
141
|
+
nominations = if my_cloud.running_action
|
142
|
+
["none"]
|
143
|
+
else
|
144
|
+
collect_nominations
|
145
|
+
end
|
146
|
+
# Hackity hack hack
|
147
|
+
nominations << "expand" if my_cloud.nodes(:status => "running").size < min_instances
|
148
|
+
nominations << "contract" if my_cloud.nodes(:status => "running").size > max_instances
|
149
|
+
stats[my_ip]["nominations"] = nominations #TODO: Deprecate
|
150
|
+
nominations
|
151
|
+
end
|
152
|
+
|
153
|
+
def collect_nominations
|
154
|
+
nominations = rules.collect do |k,cld_rules|
|
156
155
|
t = cld_rules.collect do |r|
|
157
156
|
# If the comparison works
|
158
157
|
if self.send(r.key.to_sym).to_f.send(r.comparison, r.var.to_f)
|
159
158
|
# if we are facing an expansion rule
|
160
159
|
if k =~ /expand/
|
161
160
|
k if can_expand?
|
162
|
-
neigborhood.each do |i|
|
163
|
-
RestClient.put "#{i.ip}/elections", stats.to_json, :content_type => 'text/x-json'
|
164
|
-
end
|
165
161
|
# if we are facing a contraction rule
|
166
162
|
elsif k =~ /contract/
|
167
163
|
k if can_contract?
|
168
164
|
else
|
169
165
|
k
|
170
166
|
end
|
171
|
-
end
|
167
|
+
end
|
172
168
|
end.compact
|
173
|
-
end.flatten.compact
|
169
|
+
end.flatten.compact
|
174
170
|
end
|
175
171
|
|
176
172
|
def neighborhood
|
177
173
|
@neighborhood ||= clouds[open('/etc/poolparty/cloud_name').read].nodes
|
178
174
|
end
|
179
|
-
|
180
|
-
#alias to allow access thru http route GET /stats/nominations
|
181
|
-
def get_nominations(_nodes=[])
|
182
|
-
nominations.to_json
|
183
|
-
end
|
184
175
|
|
185
176
|
def get_hello(_n=nil)
|
186
177
|
'hi there'
|
@@ -191,6 +191,10 @@ module PoolParty
|
|
191
191
|
def self.launch_instance!(o={}, &block)
|
192
192
|
new(o, &block).launch_instance!
|
193
193
|
end
|
194
|
+
|
195
|
+
def terminate_youngest_instance!(o={})
|
196
|
+
terminate_instance!(:instance_id => nodes(:status => "running").last.instance_id)
|
197
|
+
end
|
194
198
|
|
195
199
|
# Called after an instance is launched
|
196
200
|
def after_launch_instance(instance=nil)
|
@@ -27,6 +27,7 @@ The sshkey resource specifies an ssh key that should be distributed on all the n
|
|
27
27
|
|
28
28
|
dsl_methods(:key,
|
29
29
|
:keypath,
|
30
|
+
:content,
|
30
31
|
:name)
|
31
32
|
|
32
33
|
default_options(:type => 'rsa', :mode => "600")
|
@@ -39,7 +40,7 @@ The sshkey resource specifies an ssh key that should be distributed on all the n
|
|
39
40
|
|
40
41
|
def loaded(opts={}, &block)
|
41
42
|
has_directory(::File.dirname(opts[:name]))
|
42
|
-
has_file(:name => opts[:name], :content =>
|
43
|
+
has_file(:name => opts[:name], :content => opts[:content], :mode => opts[:mode])
|
43
44
|
end
|
44
45
|
|
45
46
|
|
@@ -21,7 +21,7 @@ module PoolParty
|
|
21
21
|
|
22
22
|
class Cloud < PoolParty::PoolPartyBaseClass
|
23
23
|
attr_reader :templates, :cloud_name, :remote_base
|
24
|
-
attr_accessor :started_instance
|
24
|
+
attr_accessor :started_instance, :running_action
|
25
25
|
|
26
26
|
# Default set of options. Most take the Default options from the default class
|
27
27
|
default_options(
|
@@ -51,6 +51,7 @@ module PoolParty
|
|
51
51
|
#%w(monitors plugins verifiers).each do |lib|
|
52
52
|
# Dir[File.join(::File.dirname(::File.basename(filename)), lib, '*')].each{|f| require f }
|
53
53
|
# end
|
54
|
+
call_before_all_loaded(pool_specfile || filename)
|
54
55
|
o = File.open(filename, 'r') do |f|
|
55
56
|
instance_eval f.read, (pool_specfile || filename)
|
56
57
|
end
|
@@ -58,7 +59,15 @@ module PoolParty
|
|
58
59
|
o
|
59
60
|
end
|
60
61
|
|
61
|
-
#
|
62
|
+
# callbacks
|
63
|
+
def self.call_before_all_loaded(filepath)
|
64
|
+
# Load the plugins
|
65
|
+
$:.unshift(::File.dirname(filepath))
|
66
|
+
Dir["#{::File.dirname(filepath)}/plugins/*"].each do |plugin_path|
|
67
|
+
$:.unshift(plugin_path)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
62
71
|
def after_all_loaded(&block)
|
63
72
|
@after_all_loaded ||= block
|
64
73
|
end
|
@@ -134,24 +134,20 @@ module PoolParty
|
|
134
134
|
|
135
135
|
commands << [
|
136
136
|
"mkdir -p /etc/poolparty",
|
137
|
+
"echo #{cloud.name} > /etc/poolparty/cloud_name",
|
138
|
+
"echo #{cloud.pool.name}>/etc/poolparty/pool_name",
|
137
139
|
"mkdir -p /var/log/poolparty",
|
138
140
|
"groupadd -f poolparty",
|
139
141
|
# "useradd poolparty --home-dir /var/poolparty --groups poolparty --create-home",
|
140
|
-
|
141
|
-
"cp /var/poolparty/dependencies/etc/poolparty/gemrc_template /etc/poolparty",
|
142
|
+
"cd /var/poolparty/dependencies && cp /var/poolparty/dependencies/etc/poolparty/gemrc_template /etc/poolparty",
|
142
143
|
"#{installer} update",
|
143
144
|
"#{installer} install -y ruby ruby1.8-dev irb libopenssl-ruby1.8 build-essential wget", #optional, but nice to have
|
144
|
-
"tar -zxvf packages/rubygems-1.3.4.tgz",
|
145
|
-
"cd rubygems-1.3.4",
|
146
|
-
"ruby setup.rb --no-ri --no-rdoc",
|
147
|
-
"ln -sfv /usr/bin/gem1.8 /usr/bin/gem", #TODO: check if this is really needed
|
148
|
-
"cd ../ && rm -rf rubygems-1.3.1*",
|
145
|
+
"tar -zxvf packages/rubygems-1.3.4.tgz && cd rubygems-1.3.4 && ruby setup.rb --no-ri --no-rdoc && ln -sfv /usr/bin/gem1.8 /usr/bin/gem && cd ../ && rm -rf rubygems-1.3.1*",
|
149
146
|
"gem source --add http://gems.github.com",
|
150
|
-
"gem
|
147
|
+
"gem source -a http://gems.opscode.com",
|
151
148
|
"cd /var/poolparty/dependencies/gems/",
|
152
149
|
"gem install --no-rdoc --no-ri *.gem",
|
153
|
-
"cd /var/poolparty/dependencies",
|
154
|
-
"cp /var/poolparty/dependencies/etc/poolparty/* /etc/poolparty/",
|
150
|
+
"cd /var/poolparty/dependencies && cp /var/poolparty/dependencies/etc/poolparty/* /etc/poolparty/",
|
155
151
|
'touch /var/poolparty/POOLPARTY.PROGRESS',
|
156
152
|
"mkdir -p /root/.ssh",
|
157
153
|
"cp /var/poolparty/dependencies/keys/* /root/.ssh/",
|
@@ -160,7 +156,7 @@ module PoolParty
|
|
160
156
|
"mkdir -p /var/log/poolparty/",
|
161
157
|
"echo '-- Starting monitor_rack --'",
|
162
158
|
# NOTE: if someone has an old version of thin/rack on their system, this will fail silently and never finish bootstrapping
|
163
|
-
"thin -R /etc/poolparty/monitor.ru -p 8642 --pid /var/run/stats_monitor.pid --daemon -l /var/log/poolparty/monitor.log start 2>/dev/null",
|
159
|
+
"ps aux | grep thin | grep -v grep | awk '{print $2}' | xargs kill -9; thin -R /etc/poolparty/monitor.ru -p 8642 --pid /var/run/stats_monitor.pid --daemon -l /var/log/poolparty/monitor.log start 2>/dev/null",
|
164
160
|
"tail -n 20 /var/log/poolparty/monitor.log",
|
165
161
|
'echo "bootstrap" >> /var/poolparty/POOLPARTY.PROGRESS']
|
166
162
|
commands << self.class.class_commands unless self.class.class_commands.empty?
|
@@ -97,6 +97,8 @@ module PoolParty
|
|
97
97
|
commands << [
|
98
98
|
'chmod 644 /var/poolparty/dr_configure/clouds.json',
|
99
99
|
'chmod 644 /var/poolparty/dr_configure/clouds.rb',
|
100
|
+
"cp -R /var/poolparty/dr_configure/etc/poolparty/* /etc/poolparty/",
|
101
|
+
# TODO: slightly redundant
|
100
102
|
'cp /var/poolparty/dr_configure/clouds.json /etc/poolparty',
|
101
103
|
'cp /var/poolparty/dr_configure/clouds.rb /etc/poolparty',
|
102
104
|
# 'server-manage-election', #ensures that the monitor gets some data
|
@@ -107,6 +109,8 @@ module PoolParty
|
|
107
109
|
end
|
108
110
|
|
109
111
|
def pack_up_and_ship_off_suitcase
|
112
|
+
::Suitcase::Zipper.add(::File.dirname(pool_specfile), "/etc/poolparty")
|
113
|
+
|
110
114
|
::Suitcase::Zipper.build_dir!("#{cloud.tmp_path}/dr_configure")
|
111
115
|
rsync "#{cloud.tmp_path}/dr_configure/", "/var/poolparty/dr_configure/", ['-a --stats']
|
112
116
|
end
|
@@ -25,7 +25,7 @@ describe "Key" do
|
|
25
25
|
before(:each) do
|
26
26
|
@keypair = "sshkey_test"
|
27
27
|
Dir.stub!(:pwd).and_return "#{::File.dirname(__FILE__)}/test_plugins"
|
28
|
-
|
28
|
+
Key.add_searchable_path("#{::File.dirname(__FILE__)}/test_plugins")
|
29
29
|
@key = Key.new(@keypair)
|
30
30
|
end
|
31
31
|
it "should search in known locations for the key" do
|
data/tasks/spec.rake
CHANGED
@@ -5,7 +5,7 @@ require 'rake/rdoctask'
|
|
5
5
|
|
6
6
|
task :default => [:spec, :test, :cleanup_test]
|
7
7
|
desc "Update vendor directory and run tests"
|
8
|
-
task :ci => ["
|
8
|
+
task :ci => ["pp:vendor:setup", "pp:vendor:update", :spec, :test]
|
9
9
|
|
10
10
|
task :cleanup_test do
|
11
11
|
::FileUtils.rm_rf "/tmp/poolparty"
|
@@ -18,4 +18,15 @@ class TestWrappingArray < Test::Unit::TestCase
|
|
18
18
|
end
|
19
19
|
end
|
20
20
|
|
21
|
+
context "histogram" do
|
22
|
+
should "provide a histogram" do
|
23
|
+
out = %w(tart q a b a a b c).histogram
|
24
|
+
assert_equal 1, out["tart"]
|
25
|
+
assert_equal 3, out["a"]
|
26
|
+
assert_equal 2, out["b"]
|
27
|
+
assert_equal 1, out["c"]
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
|
21
32
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: auser-poolparty
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.2.
|
4
|
+
version: 1.2.12
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ari Lerner
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-06-
|
12
|
+
date: 2009-06-23 00:00:00 -07:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -165,6 +165,7 @@ files:
|
|
165
165
|
- lib/poolparty/monitors/monitor_rack.rb
|
166
166
|
- lib/poolparty/monitors/monitors
|
167
167
|
- lib/poolparty/monitors/monitors/clock_monitor.rb
|
168
|
+
- lib/poolparty/monitors/monitors/cloud_monitor.rb
|
168
169
|
- lib/poolparty/monitors/monitors/elections_monitor.rb
|
169
170
|
- lib/poolparty/monitors/monitors/favicon_monitor.rb
|
170
171
|
- lib/poolparty/monitors/monitors/load_monitor.rb
|