seesaw 0.1.0 → 0.2.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.
- 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
|