seesaw 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +6 -0
- data/lib/seesaw/init.rb +150 -21
- data/lib/seesaw/mongrel_cluster_patch.rb +1 -1
- metadata +2 -2
data/History.txt
CHANGED
data/lib/seesaw/init.rb
CHANGED
@@ -3,46 +3,49 @@ require 'mongrel'
|
|
3
3
|
require 'yaml'
|
4
4
|
require 'fileutils'
|
5
5
|
require 'seesaw/mongrel_cluster_patch'
|
6
|
+
require "erb"
|
6
7
|
|
7
8
|
module Seesaw
|
8
|
-
VERSION = '0.
|
9
|
+
VERSION = '0.2.0'
|
9
10
|
|
10
11
|
module CommandBase
|
12
|
+
def log(message)
|
13
|
+
puts message
|
14
|
+
end
|
15
|
+
|
11
16
|
def symlink(cluster)
|
12
|
-
|
17
|
+
log "symlink to #{cluster}"
|
13
18
|
file = File.join(@config_path, @config_files[cluster])
|
14
|
-
|
15
|
-
FileUtils.ln_sf( file, @config_symlink)
|
19
|
+
system("#{@symlink_cmd} #{file} #{@config_symlink}")
|
16
20
|
end
|
17
21
|
|
18
22
|
def restart_mongrels(cluster=nil)
|
19
|
-
|
23
|
+
log "restart mongrels #{cluster}"
|
20
24
|
stop_mongrels(cluster)
|
21
25
|
start_mongrels(cluster)
|
22
26
|
end
|
23
27
|
|
24
28
|
def start_mongrels(cluster=nil)
|
25
|
-
|
29
|
+
log "start mongrels #{cluster}"
|
26
30
|
cmd = "mongrel_rails seesaw::start"
|
27
|
-
cmd << " --cluster #{cluster}" if cluster
|
31
|
+
cmd << " --cluster #{cluster}" if cluster && cluster != "all"
|
28
32
|
system(cmd)
|
29
33
|
end
|
30
34
|
|
31
35
|
def stop_mongrels(cluster=nil)
|
32
|
-
|
36
|
+
log "stop mongrels #{cluster}"
|
33
37
|
cmd = "mongrel_rails seesaw::stop"
|
34
38
|
cmd << " --cluster #{cluster}" if cluster
|
35
39
|
system(cmd)
|
36
40
|
end
|
37
41
|
|
38
42
|
def restart_http(cluster=nil)
|
39
|
-
|
43
|
+
log "webserver restart"
|
40
44
|
system(@restart_cmd)
|
41
|
-
sleep 5
|
42
45
|
end
|
43
46
|
|
44
47
|
def shutdown_half_cluster(half)
|
45
|
-
|
48
|
+
log "shutdown half #{half}"
|
46
49
|
other_half = half == 1 ? 2 : 1
|
47
50
|
symlink(other_half)
|
48
51
|
restart_http
|
@@ -50,14 +53,14 @@ module Seesaw
|
|
50
53
|
end
|
51
54
|
|
52
55
|
def switch_to_half_cluster(half)
|
53
|
-
|
56
|
+
log "switch_to_half_cluster #{half}"
|
54
57
|
other_half = half == 1 ? 2 : 1
|
55
58
|
shutdown_half_cluster(other_half)
|
56
59
|
start_mongrels(other_half)
|
57
60
|
end
|
58
61
|
|
59
62
|
def start_cluster
|
60
|
-
|
63
|
+
log "start cluster"
|
61
64
|
symlink("all")
|
62
65
|
restart_http
|
63
66
|
end
|
@@ -72,6 +75,7 @@ module Seesaw
|
|
72
75
|
@config_symlink = @options["config_symlink"] || "cluster.conf"
|
73
76
|
@config_symlink = File.join(@config_path, @config_symlink)
|
74
77
|
@restart_cmd = @options["restart_cmd"] || "apachectl graceful"
|
78
|
+
@symlink_cmd = @options["symlink_cmd"] || "ln -sf"
|
75
79
|
end
|
76
80
|
|
77
81
|
def validate
|
@@ -87,21 +91,146 @@ module Seesaw
|
|
87
91
|
|
88
92
|
end
|
89
93
|
|
90
|
-
class
|
94
|
+
class Ripple < GemPlugin::Plugin "/commands"
|
91
95
|
include Mongrel::Command::Base
|
92
96
|
include CommandBase
|
93
97
|
|
94
98
|
def run
|
95
99
|
parse_options
|
96
|
-
p "c1"
|
97
100
|
switch_to_half_cluster(1)
|
98
|
-
p "c2"
|
99
101
|
switch_to_half_cluster(2)
|
100
|
-
p "nighty night"
|
101
|
-
sleep 20
|
102
|
-
p "all"
|
103
102
|
start_cluster
|
104
|
-
|
103
|
+
log "done"
|
105
104
|
end
|
106
105
|
end
|
107
|
-
|
106
|
+
|
107
|
+
class Switch < GemPlugin::Plugin "/commands"
|
108
|
+
include Mongrel::Command::Base
|
109
|
+
include CommandBase
|
110
|
+
|
111
|
+
def configure
|
112
|
+
options [
|
113
|
+
['-C', '--config PATH', "Path to cluster configuration file", :@config_file, "config/seesaw.yml"],
|
114
|
+
['', '--cluster CLUSTER', "Switch to cluster configuration CLUSTER: [1|2|all]", :@cluster, 'all']
|
115
|
+
]
|
116
|
+
end
|
117
|
+
|
118
|
+
def validate
|
119
|
+
valid?(["1","2","all"].include?(@cluster), "invalid option for --cluster")
|
120
|
+
@valid
|
121
|
+
end
|
122
|
+
|
123
|
+
def run
|
124
|
+
parse_options
|
125
|
+
unless "all" == @cluster
|
126
|
+
@cluster = @cluster.to_i
|
127
|
+
other_half = @cluster == 1 ? 2 : 1
|
128
|
+
end
|
129
|
+
start_mongrels(@cluster)
|
130
|
+
symlink(@cluster)
|
131
|
+
restart_http
|
132
|
+
stop_mongrels(other_half) unless "all" == @cluster
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
class Configure < GemPlugin::Plugin "/commands"
|
137
|
+
include Mongrel::Command::Base
|
138
|
+
|
139
|
+
def configure
|
140
|
+
options [
|
141
|
+
['-N', '--num-servers INT', "Number of Mongrel servers", :@servers, 2],
|
142
|
+
['-C', '--config PATH', "Path to seesaw configuration file", :@config_file, 'config/seesaw.yml'],
|
143
|
+
['-M', '--mongrel PATH', "Path to mongrel cluster configuration file", :@mongrel_config_file, 'config/mongrel_cluster.yml'],
|
144
|
+
['', '--http_config PATH', "Path to the http server configuration includes", :@http_config_path, "config/http_cluster"],
|
145
|
+
['', '--server TYPE', "Webserver to generate example configuration for. TYPE can be nginx or apache. Default is nginx.", :@server, 'nginx']
|
146
|
+
]
|
147
|
+
end
|
148
|
+
|
149
|
+
def validate
|
150
|
+
valid?(['nginx','apache'].include?(@server), "Server must be nginx or apache")
|
151
|
+
valid_dir? File.dirname(@config_file), "Path to config file not valid: #{@config_file}"
|
152
|
+
valid?(File.exist?(@mongrel_config_file), "Path to mongrel cluster config file not valid: #{@mongrel_config_file}")
|
153
|
+
|
154
|
+
return @valid
|
155
|
+
end
|
156
|
+
|
157
|
+
def write_config_include(file, ports)
|
158
|
+
|
159
|
+
log "writing #{file}"
|
160
|
+
|
161
|
+
ip = "127.0.0.1"
|
162
|
+
server_lines = ""
|
163
|
+
line_template = ERB.new(INCLUDES[@server][:server_line])
|
164
|
+
ports.each do |port|
|
165
|
+
server_lines << line_template.result(binding)
|
166
|
+
end
|
167
|
+
|
168
|
+
template = ERB.new(INCLUDES[@server][:template])
|
169
|
+
File.open(file, "w") { |f| f.write(template.result(binding)) }
|
170
|
+
end
|
171
|
+
|
172
|
+
def run
|
173
|
+
restart_cmds = {
|
174
|
+
'nginx' => "sudo kill -HUP `cat /opt/local/var/log/nginx.pid`",
|
175
|
+
'apache' => "sudo apachectl graceful"
|
176
|
+
}
|
177
|
+
|
178
|
+
@options = {}
|
179
|
+
|
180
|
+
@options["config_path"] = @http_config_path
|
181
|
+
@options["restart_cmd"] = restart_cmds[@server]
|
182
|
+
@options["symlink_cmd"] = "ln -sf"
|
183
|
+
@options["config_symlink"] = "cluster.conf"
|
184
|
+
@options["config_files"] = {}
|
185
|
+
@options["config_files"]["all"] = "cluster_all.conf"
|
186
|
+
@options["config_files"][1] = "cluster_1.conf"
|
187
|
+
@options["config_files"][2] = "cluster_2.conf"
|
188
|
+
|
189
|
+
# write seesaw configuration
|
190
|
+
log "Writing configuration file to #{@config_file}."
|
191
|
+
File.open(@config_file,"w") {|f| f.write(@options.to_yaml)}
|
192
|
+
|
193
|
+
# read mongrel cluster configuration to find number of servers
|
194
|
+
mongrel_conf = YAML.load(File.read(@mongrel_config_file))
|
195
|
+
|
196
|
+
# create cluster config directory if it doesn't exist
|
197
|
+
Dir.mkdir(@http_config_path) unless File.exist?(@http_config_path)
|
198
|
+
|
199
|
+
# write cluster configuration files for appropriate server
|
200
|
+
start_port = mongrel_conf["port"]
|
201
|
+
end_port = mongrel_conf["port"]+mongrel_conf["servers"] - 1
|
202
|
+
mid_port = ((end_port+start_port)/2.0).ceil
|
203
|
+
|
204
|
+
# full cluster
|
205
|
+
write_config_include(File.join(@http_config_path,@options["config_files"]["all"]), (start_port..end_port))
|
206
|
+
|
207
|
+
# front half
|
208
|
+
write_config_include(File.join(@http_config_path,@options["config_files"][1]), (start_port..mid_port-1))
|
209
|
+
|
210
|
+
# back half
|
211
|
+
write_config_include(File.join(@http_config_path,@options["config_files"][2]), (mid_port..end_port))
|
212
|
+
|
213
|
+
# symlink
|
214
|
+
system("#{@options["symlink_cmd"]} #{File.expand_path(File.join(@http_config_path,@options["config_files"]["all"]))} #{File.join(@http_config_path,@options["config_symlink"])}")
|
215
|
+
|
216
|
+
log "Don't forget to include #{File.expand_path("#{@http_config_path}/cluster.conf")} in your webserver configuration."
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
INCLUDES = {}
|
221
|
+
INCLUDES['nginx'] = {}
|
222
|
+
INCLUDES['apache'] = {}
|
223
|
+
INCLUDES['nginx'][:template]=<<-TEMPLATE
|
224
|
+
upstream mongrel_pack {
|
225
|
+
<%= server_lines %>}
|
226
|
+
TEMPLATE
|
227
|
+
INCLUDES['nginx'][:server_line] = " server <%=ip%>:<%=port%>;\n"
|
228
|
+
|
229
|
+
INCLUDES['apache'][:template]=<<-TEMPLATE
|
230
|
+
<Proxy balancer://mongrel_pack>
|
231
|
+
<%= server_lines %></Proxy>
|
232
|
+
TEMPLATE
|
233
|
+
INCLUDES['apache'][:server_line] = " BalancerMember http://<%=ip%>:<%=port%>;\n"
|
234
|
+
|
235
|
+
end
|
236
|
+
|
metadata
CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.9.4
|
|
3
3
|
specification_version: 1
|
4
4
|
name: seesaw
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 0.
|
7
|
-
date: 2007-08-
|
6
|
+
version: 0.2.0
|
7
|
+
date: 2007-08-19 00:00:00 +10:00
|
8
8
|
summary: Ripple-restart a mongrel cluster with no downtime
|
9
9
|
require_paths:
|
10
10
|
- lib
|