seesaw 0.1.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 +5 -0
- data/Manifest.txt +8 -0
- data/README.txt +48 -0
- data/Rakefile +19 -0
- data/bin/seesaw +0 -0
- data/lib/seesaw/init.rb +107 -0
- data/lib/seesaw/mongrel_cluster_patch.rb +368 -0
- data/test/test_seesaw.rb +0 -0
- metadata +91 -0
data/History.txt
ADDED
data/Manifest.txt
ADDED
data/README.txt
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
seesaw
|
2
|
+
by Matt Allen and Max Muermann
|
3
|
+
(http://rubyforge.org/projects/rails-oceania)
|
4
|
+
|
5
|
+
== DESCRIPTION:
|
6
|
+
|
7
|
+
FIX (describe your package)
|
8
|
+
|
9
|
+
== FEATURES/PROBLEMS:
|
10
|
+
|
11
|
+
* FIX (list of features or problems)
|
12
|
+
|
13
|
+
== SYNOPSIS:
|
14
|
+
|
15
|
+
FIX (code sample of usage)
|
16
|
+
|
17
|
+
== REQUIREMENTS:
|
18
|
+
|
19
|
+
* FIX (list of requirements)
|
20
|
+
|
21
|
+
== INSTALL:
|
22
|
+
|
23
|
+
sudo gem install seesaw
|
24
|
+
|
25
|
+
== LICENSE:
|
26
|
+
|
27
|
+
(The MIT License)
|
28
|
+
|
29
|
+
Copyright (c) 2007 FIX
|
30
|
+
|
31
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
32
|
+
a copy of this software and associated documentation files (the
|
33
|
+
'Software'), to deal in the Software without restriction, including
|
34
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
35
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
36
|
+
permit persons to whom the Software is furnished to do so, subject to
|
37
|
+
the following conditions:
|
38
|
+
|
39
|
+
The above copyright notice and this permission notice shall be
|
40
|
+
included in all copies or substantial portions of the Software.
|
41
|
+
|
42
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
43
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
44
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
45
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
46
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
47
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
48
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
# -*- ruby -*-
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'hoe'
|
5
|
+
require './lib/seesaw/init.rb'
|
6
|
+
|
7
|
+
Hoe.new('seesaw', Seesaw::VERSION) do |p|
|
8
|
+
p.rubyforge_name = 'seesaw'
|
9
|
+
p.author = 'Matt Allen, Max Muermann'
|
10
|
+
p.email = 'max@muermann.org'
|
11
|
+
p.summary = 'Ripple-restart a mongrel cluster with no downtime'
|
12
|
+
p.description = p.paragraphs_of('README.txt', 2..5).join("\n\n")
|
13
|
+
p.url = p.paragraphs_of('README.txt', 0).first.split(/\n/)[1..-1]
|
14
|
+
p.changes = p.paragraphs_of('History.txt', 0..1).join("\n\n")
|
15
|
+
p.extra_deps << ['gem_plugin', '>= 0.2.2'] << ['mongrel', '>= 1.0.1'] << ['mongrel_cluster', '>= 1.0.2']
|
16
|
+
p.spec_extras['autorequire'] = 'seesaw/init.rb'
|
17
|
+
end
|
18
|
+
|
19
|
+
# vim: syntax=Ruby
|
data/bin/seesaw
ADDED
File without changes
|
data/lib/seesaw/init.rb
ADDED
@@ -0,0 +1,107 @@
|
|
1
|
+
require 'gem_plugin'
|
2
|
+
require 'mongrel'
|
3
|
+
require 'yaml'
|
4
|
+
require 'fileutils'
|
5
|
+
require 'seesaw/mongrel_cluster_patch'
|
6
|
+
|
7
|
+
module Seesaw
|
8
|
+
VERSION = '0.1.0'
|
9
|
+
|
10
|
+
module CommandBase
|
11
|
+
def symlink(cluster)
|
12
|
+
p "symlink to #{cluster}"
|
13
|
+
file = File.join(@config_path, @config_files[cluster])
|
14
|
+
p "target: #{file}"
|
15
|
+
FileUtils.ln_sf( file, @config_symlink)
|
16
|
+
end
|
17
|
+
|
18
|
+
def restart_mongrels(cluster=nil)
|
19
|
+
p "restart mongrels #{cluster}"
|
20
|
+
stop_mongrels(cluster)
|
21
|
+
start_mongrels(cluster)
|
22
|
+
end
|
23
|
+
|
24
|
+
def start_mongrels(cluster=nil)
|
25
|
+
p "start mongrels #{cluster}"
|
26
|
+
cmd = "mongrel_rails seesaw::start"
|
27
|
+
cmd << " --cluster #{cluster}" if cluster
|
28
|
+
system(cmd)
|
29
|
+
end
|
30
|
+
|
31
|
+
def stop_mongrels(cluster=nil)
|
32
|
+
p "stop mongrels #{cluster}"
|
33
|
+
cmd = "mongrel_rails seesaw::stop"
|
34
|
+
cmd << " --cluster #{cluster}" if cluster
|
35
|
+
system(cmd)
|
36
|
+
end
|
37
|
+
|
38
|
+
def restart_http(cluster=nil)
|
39
|
+
p "nginx restart"
|
40
|
+
system(@restart_cmd)
|
41
|
+
sleep 5
|
42
|
+
end
|
43
|
+
|
44
|
+
def shutdown_half_cluster(half)
|
45
|
+
p "shutdown half #{half}"
|
46
|
+
other_half = half == 1 ? 2 : 1
|
47
|
+
symlink(other_half)
|
48
|
+
restart_http
|
49
|
+
stop_mongrels(half)
|
50
|
+
end
|
51
|
+
|
52
|
+
def switch_to_half_cluster(half)
|
53
|
+
p "switch_to_half_cluster #{half}"
|
54
|
+
other_half = half == 1 ? 2 : 1
|
55
|
+
shutdown_half_cluster(other_half)
|
56
|
+
start_mongrels(other_half)
|
57
|
+
end
|
58
|
+
|
59
|
+
def start_cluster
|
60
|
+
p "start cluster"
|
61
|
+
symlink("all")
|
62
|
+
restart_http
|
63
|
+
end
|
64
|
+
|
65
|
+
def parse_options
|
66
|
+
@options = YAML.load(File.read(@config_file))
|
67
|
+
@config_path = @options["config_path"] || "/opt/local/etc/apache"
|
68
|
+
@config_files = @options["config_files"] || {}
|
69
|
+
@config_files[1] ||= "cluster_1.conf"
|
70
|
+
@config_files[2] ||= "cluster_2.conf"
|
71
|
+
@config_files["all"] ||= "cluster_all.conf"
|
72
|
+
@config_symlink = @options["config_symlink"] || "cluster.conf"
|
73
|
+
@config_symlink = File.join(@config_path, @config_symlink)
|
74
|
+
@restart_cmd = @options["restart_cmd"] || "apachectl graceful"
|
75
|
+
end
|
76
|
+
|
77
|
+
def validate
|
78
|
+
valid_exists?(@config_file, "Configuration file does not exist. Run mongrel_rails seesaw::configure.")
|
79
|
+
return @valid
|
80
|
+
end
|
81
|
+
|
82
|
+
def configure
|
83
|
+
options [
|
84
|
+
['-C', '--config PATH', "Path to cluster configuration file", :@config_file, "config/seesaw.yml"],
|
85
|
+
]
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
89
|
+
|
90
|
+
class Migrate < GemPlugin::Plugin "/commands"
|
91
|
+
include Mongrel::Command::Base
|
92
|
+
include CommandBase
|
93
|
+
|
94
|
+
def run
|
95
|
+
parse_options
|
96
|
+
p "c1"
|
97
|
+
switch_to_half_cluster(1)
|
98
|
+
p "c2"
|
99
|
+
switch_to_half_cluster(2)
|
100
|
+
p "nighty night"
|
101
|
+
sleep 20
|
102
|
+
p "all"
|
103
|
+
start_cluster
|
104
|
+
p "done"
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
@@ -0,0 +1,368 @@
|
|
1
|
+
require 'gem_plugin'
|
2
|
+
require 'mongrel'
|
3
|
+
require 'yaml'
|
4
|
+
require 'enumerator'
|
5
|
+
|
6
|
+
module Seesaw
|
7
|
+
module ExecBase
|
8
|
+
include Mongrel::Command::Base
|
9
|
+
|
10
|
+
STATUS_OK = 0
|
11
|
+
STATUS_ERROR = 2
|
12
|
+
|
13
|
+
def validate
|
14
|
+
valid_exists?(@config_file, "Configuration file does not exist. Run mongrel_rails cluster::configure.")
|
15
|
+
return @valid
|
16
|
+
end
|
17
|
+
|
18
|
+
def read_options
|
19
|
+
@options = {
|
20
|
+
"environment" => ENV['RAILS_ENV'] || "development",
|
21
|
+
"port" => 3000,
|
22
|
+
"pid_file" => "tmp/pids/mongrel.pid",
|
23
|
+
"log_file" => "log/mongrel.log",
|
24
|
+
"servers" => 2
|
25
|
+
}
|
26
|
+
conf = YAML.load_file(@config_file)
|
27
|
+
@options.merge! conf if conf
|
28
|
+
|
29
|
+
process_pid_file @options["pid_file"]
|
30
|
+
process_log_file @options["log_file"]
|
31
|
+
|
32
|
+
start_port = end_port = @only
|
33
|
+
start_port ||= @options["port"].to_i
|
34
|
+
end_port ||= start_port + @options["servers"] - 1
|
35
|
+
@ports = (start_port..end_port).to_a
|
36
|
+
end
|
37
|
+
|
38
|
+
def process_pid_file(pid_file)
|
39
|
+
@pid_file_ext = File.extname(pid_file)
|
40
|
+
@pid_file_base = File.basename(pid_file, @pid_file_ext)
|
41
|
+
@pid_file_dir = File.dirname(pid_file)
|
42
|
+
end
|
43
|
+
|
44
|
+
def process_log_file(log_file)
|
45
|
+
@log_file_ext = File.extname(log_file)
|
46
|
+
@log_file_base = File.basename(log_file, @log_file_ext)
|
47
|
+
@log_file_dir = File.dirname(log_file)
|
48
|
+
end
|
49
|
+
|
50
|
+
def port_pid_file(port)
|
51
|
+
pid_file = [@pid_file_base, port].join(".") + @pid_file_ext
|
52
|
+
File.join(@pid_file_dir, pid_file)
|
53
|
+
end
|
54
|
+
|
55
|
+
def port_log_file(port)
|
56
|
+
log_file = [@log_file_base, port].join(".") + @log_file_ext
|
57
|
+
File.join(@log_file_dir, log_file)
|
58
|
+
end
|
59
|
+
|
60
|
+
def start
|
61
|
+
argv = [ "mongrel_rails" ]
|
62
|
+
argv << "start"
|
63
|
+
argv << "-d"
|
64
|
+
argv << "-e #{@options["environment"]}" if @options["environment"]
|
65
|
+
argv << "-a #{@options["address"]}" if @options["address"]
|
66
|
+
argv << "-c #{@options["cwd"]}" if @options["cwd"]
|
67
|
+
argv << "-t #{@options["timeout"]}" if @options["timeout"]
|
68
|
+
argv << "-m #{@options["mime_map"]}" if @options["mime_map"]
|
69
|
+
argv << "-r #{@options["docroot"]}" if @options["docroot"]
|
70
|
+
argv << "-n #{@options["num_procs"]}" if @options["num_procs"]
|
71
|
+
argv << "-B" if @options["debug"]
|
72
|
+
argv << "-S #{@options["config_script"]}" if @options["config_script"]
|
73
|
+
argv << "--user #{@options["user"]}" if @options["user"]
|
74
|
+
argv << "--group #{@options["group"]}" if @options["group"]
|
75
|
+
argv << "--prefix #{@options["prefix"]}" if @options["prefix"]
|
76
|
+
cmd = argv.join " "
|
77
|
+
|
78
|
+
@ports.each do |port|
|
79
|
+
if @clean && pid_file_exists?(port) && !check_process(port)
|
80
|
+
pid_file = port_pid_file(port)
|
81
|
+
log "missing process: removing #{pid_file}"
|
82
|
+
File.unlink(pid_file)
|
83
|
+
end
|
84
|
+
|
85
|
+
if pid_file_exists?(port) && check_process(port)
|
86
|
+
log "already started port #{port}"
|
87
|
+
next
|
88
|
+
end
|
89
|
+
|
90
|
+
exec_cmd = cmd + " -p #{port} -P #{port_pid_file(port)}"
|
91
|
+
exec_cmd += " -l #{port_log_file(port)}"
|
92
|
+
log "starting port #{port}"
|
93
|
+
log_verbose exec_cmd
|
94
|
+
output = `#{exec_cmd}`
|
95
|
+
log_error output unless $?.success?
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def stop
|
100
|
+
argv = [ "mongrel_rails" ]
|
101
|
+
argv << "stop"
|
102
|
+
argv << "-c #{@options["cwd"]}" if @options["cwd"]
|
103
|
+
argv << "-f" if @force
|
104
|
+
cmd = argv.join " "
|
105
|
+
|
106
|
+
@ports.each do |port|
|
107
|
+
pid = check_process(port)
|
108
|
+
if @clean && pid && !pid_file_exists?(port)
|
109
|
+
log "missing pid_file: killing mongrel_rails port #{port}, pid #{pid}"
|
110
|
+
Process.kill("KILL", pid.to_i)
|
111
|
+
end
|
112
|
+
|
113
|
+
if !check_process(port)
|
114
|
+
log "already stopped port #{port}"
|
115
|
+
next
|
116
|
+
end
|
117
|
+
|
118
|
+
exec_cmd = cmd + " -P #{port_pid_file(port)}"
|
119
|
+
log "stopping port #{port}"
|
120
|
+
log_verbose exec_cmd
|
121
|
+
output = `#{exec_cmd}`
|
122
|
+
log_error output unless $?.success?
|
123
|
+
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
def status
|
128
|
+
status = STATUS_OK
|
129
|
+
|
130
|
+
@ports.each do |port|
|
131
|
+
pid = check_process(port)
|
132
|
+
unless pid_file_exists?(port)
|
133
|
+
log "missing pid_file: #{port_pid_file(port)}"
|
134
|
+
status = STATUS_ERROR
|
135
|
+
else
|
136
|
+
log "found pid_file: #{port_pid_file(port)}"
|
137
|
+
end
|
138
|
+
if pid
|
139
|
+
log "found mongrel_rails: port #{port}, pid #{pid}"
|
140
|
+
else
|
141
|
+
log "missing mongrel_rails: port #{port}"
|
142
|
+
status = STATUS_ERROR
|
143
|
+
end
|
144
|
+
puts ""
|
145
|
+
end
|
146
|
+
|
147
|
+
return status
|
148
|
+
end
|
149
|
+
|
150
|
+
def pid_file_exists?(port)
|
151
|
+
pid_file = port_pid_file(port)
|
152
|
+
exists = false
|
153
|
+
chdir_cwd do
|
154
|
+
exists = File.exists?(pid_file)
|
155
|
+
end
|
156
|
+
exists
|
157
|
+
end
|
158
|
+
|
159
|
+
def check_process(port)
|
160
|
+
if pid_file_exists?(port)
|
161
|
+
pid = read_pid(port)
|
162
|
+
ps_output = `ps -o #{cmd_name}= -p #{pid}`
|
163
|
+
pid = ps_output =~ /mongrel_rails/ ? pid : nil
|
164
|
+
else
|
165
|
+
pid = find_pid(port)
|
166
|
+
end
|
167
|
+
return pid
|
168
|
+
end
|
169
|
+
|
170
|
+
def cmd_name
|
171
|
+
RUBY_PLATFORM =~ /solaris/i ? "args" : "command"
|
172
|
+
end
|
173
|
+
|
174
|
+
def chdir_cwd
|
175
|
+
pwd = Dir.pwd
|
176
|
+
Dir.chdir(@options["cwd"]) if @options["cwd"]
|
177
|
+
yield
|
178
|
+
Dir.chdir(pwd) if @options["cwd"]
|
179
|
+
end
|
180
|
+
|
181
|
+
def read_pid(port)
|
182
|
+
pid_file = port_pid_file(port)
|
183
|
+
pid = 0
|
184
|
+
chdir_cwd do
|
185
|
+
pid = File.read(pid_file)
|
186
|
+
end
|
187
|
+
return pid
|
188
|
+
end
|
189
|
+
|
190
|
+
def find_pid(port)
|
191
|
+
ps_cmd = "ps -ewwo pid,#{cmd_name}"
|
192
|
+
ps_output = `#{ps_cmd}`
|
193
|
+
ps_output.each do |line|
|
194
|
+
if line =~ /-P #{Regexp.escape(port_pid_file(port))} /
|
195
|
+
pid = line.split[0]
|
196
|
+
return pid
|
197
|
+
end
|
198
|
+
end
|
199
|
+
return nil
|
200
|
+
end
|
201
|
+
|
202
|
+
def log_error(message)
|
203
|
+
log(message)
|
204
|
+
end
|
205
|
+
|
206
|
+
def log_verbose(message)
|
207
|
+
log(message) if @verbose
|
208
|
+
end
|
209
|
+
|
210
|
+
def log(message)
|
211
|
+
puts message
|
212
|
+
end
|
213
|
+
|
214
|
+
def clustered &block
|
215
|
+
if @cluster
|
216
|
+
@only = nil
|
217
|
+
read_options
|
218
|
+
@ports.enum_slice((@ports.size/2.0).ceil).map{|x|x}[@cluster.to_i-1].each do |port|
|
219
|
+
@only = port
|
220
|
+
read_options
|
221
|
+
yield
|
222
|
+
end
|
223
|
+
else
|
224
|
+
read_options
|
225
|
+
yield
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
end
|
230
|
+
class Start < GemPlugin::Plugin "/commands"
|
231
|
+
include ExecBase
|
232
|
+
|
233
|
+
def configure
|
234
|
+
options [
|
235
|
+
['-C', '--config PATH', "Path to cluster configuration file", :@config_file, "config/mongrel_cluster.yml"],
|
236
|
+
['-v', '--verbose', "Print all called commands and output.", :@verbose, false],
|
237
|
+
['', '--clean', "Remove pid_file if needed before starting", :@clean, false],
|
238
|
+
['', '--only PORT', "Port number of cluster member", :@only, nil],
|
239
|
+
['', '--cluster NUMBER', "1 or 2 - first half or second half of cluster", :@cluster, nil]
|
240
|
+
]
|
241
|
+
end
|
242
|
+
|
243
|
+
def run
|
244
|
+
clustered {start}
|
245
|
+
end
|
246
|
+
end
|
247
|
+
|
248
|
+
class Stop < GemPlugin::Plugin "/commands"
|
249
|
+
include ExecBase
|
250
|
+
|
251
|
+
def configure
|
252
|
+
options [
|
253
|
+
['-C', '--config PATH', "Path to cluster configuration file", :@config_file, "config/mongrel_cluster.yml"],
|
254
|
+
['-f', '--force', "Force the shutdown.", :@force, false],
|
255
|
+
['-v', '--verbose', "Print all called commands and output.", :@verbose, false],
|
256
|
+
['', '--clean', "Remove orphaned process if needed before stopping", :@clean, false],
|
257
|
+
['', '--only PORT', "Port number of cluster member", :@only, nil],
|
258
|
+
['', '--cluster NUMBER', "1 or 2 - first half or second half of cluster", :@cluster, nil]
|
259
|
+
]
|
260
|
+
end
|
261
|
+
|
262
|
+
def run
|
263
|
+
clustered {stop}
|
264
|
+
end
|
265
|
+
end
|
266
|
+
|
267
|
+
class Restart < GemPlugin::Plugin "/commands"
|
268
|
+
include ExecBase
|
269
|
+
|
270
|
+
def configure
|
271
|
+
options [
|
272
|
+
['-C', '--config PATH', "Path to cluster configuration file", :@config_file, "config/mongrel_cluster.yml"],
|
273
|
+
['-f', '--force', "Force the shutdown.", :@force, false],
|
274
|
+
['-v', '--verbose', "Print all called commands and output.", :@verbose, false],
|
275
|
+
['', '--clean', "Call stop and start with --clean", :@clean, false],
|
276
|
+
['', '--only PORT', "Port number of cluster member", :@only, nil],
|
277
|
+
['', '--cluster NUMBER', "1 or 2 - first half or second half of cluster", :@cluster, nil]
|
278
|
+
]
|
279
|
+
end
|
280
|
+
|
281
|
+
def run
|
282
|
+
clustered do
|
283
|
+
stop
|
284
|
+
start
|
285
|
+
end
|
286
|
+
end
|
287
|
+
|
288
|
+
end
|
289
|
+
|
290
|
+
class Configure < GemPlugin::Plugin "/commands"
|
291
|
+
include ExecBase
|
292
|
+
|
293
|
+
def configure
|
294
|
+
options [
|
295
|
+
["-e", "--environment ENV", "Rails environment to run as", :@environment, nil],
|
296
|
+
['-p', '--port PORT', "Starting port to bind to", :@port, 3000],
|
297
|
+
['-a', '--address ADDR', "Address to bind to", :@address, nil],
|
298
|
+
['-l', '--log FILE', "Where to write log messages", :@log_file, "log/mongrel.log"],
|
299
|
+
['-P', '--pid FILE', "Where to write the PID", :@pid_file, "tmp/pids/mongrel.pid"],
|
300
|
+
['-c', '--chdir PATH', "Change to dir before starting (will be expanded)", :@cwd, nil],
|
301
|
+
['-t', '--timeout SECONDS', "Timeout all requests after SECONDS time", :@timeout, nil],
|
302
|
+
['-m', '--mime PATH', "A YAML file that lists additional MIME types", :@mime_map, nil],
|
303
|
+
['-r', '--root PATH', "Set the document root (default 'public')", :@docroot, nil],
|
304
|
+
['-n', '--num-procs INT', "Number of processor threads to use", :@num_procs, nil],
|
305
|
+
['-B', '--debug', "Enable debugging mode", :@debug, nil],
|
306
|
+
['-S', '--script PATH', "Load the given file as an extra config script.", :@config_script, nil],
|
307
|
+
['-N', '--num-servers INT', "Number of Mongrel servers", :@servers, 2],
|
308
|
+
['-C', '--config PATH', "Path to cluster configuration file", :@config_file, "config/mongrel_cluster.yml"],
|
309
|
+
['', '--user USER', "User to run as", :@user, nil],
|
310
|
+
['', '--group GROUP', "Group to run as", :@group, nil],
|
311
|
+
['', '--prefix PREFIX', "Rails prefix to use", :@prefix, nil]
|
312
|
+
]
|
313
|
+
end
|
314
|
+
|
315
|
+
def validate
|
316
|
+
@servers = @servers.to_i
|
317
|
+
|
318
|
+
valid?(@servers > 0, "Must give a valid number of servers")
|
319
|
+
valid_dir? File.dirname(@config_file), "Path to config file not valid: #{@config_file}"
|
320
|
+
|
321
|
+
return @valid
|
322
|
+
end
|
323
|
+
|
324
|
+
def run
|
325
|
+
@options = {
|
326
|
+
"port" => @port,
|
327
|
+
"servers" => @servers,
|
328
|
+
"pid_file" => @pid_file
|
329
|
+
}
|
330
|
+
|
331
|
+
@options["log_file"] = @log_file if @log_file
|
332
|
+
@options["debug"] = @debug if @debug
|
333
|
+
@options["num_procs"] = @num_procs if @num_procs
|
334
|
+
@options["docroot"] = @docroot if @docroots
|
335
|
+
@options["address"] = @address if @address
|
336
|
+
@options["timeout"] = @timeout if @timeout
|
337
|
+
@options["environment"] = @environment if @environment
|
338
|
+
@options["mime_map"] = @mime_map if @mime_map
|
339
|
+
@options["config_script"] = @config_script if @config_script
|
340
|
+
@options["cwd"] = @cwd if @cwd
|
341
|
+
@options["user"] = @user if @user
|
342
|
+
@options["group"] = @group if @group
|
343
|
+
@options["prefix"] = @prefix if @prefix
|
344
|
+
|
345
|
+
log "Writing configuration file to #{@config_file}."
|
346
|
+
File.open(@config_file,"w") {|f| f.write(@options.to_yaml)}
|
347
|
+
end
|
348
|
+
end
|
349
|
+
|
350
|
+
class Status < GemPlugin::Plugin "/commands"
|
351
|
+
include ExecBase
|
352
|
+
|
353
|
+
def configure
|
354
|
+
options [
|
355
|
+
['-C', '--config PATH', "Path to cluster configuration file", :@config_file, "config/mongrel_cluster.yml"],
|
356
|
+
['-v', '--verbose', "Print all called commands and output.", :@verbose, false],
|
357
|
+
['', '--only PORT', "Port number of cluster member", :@only, nil],
|
358
|
+
['', '--cluster NUMBER', "1 or 2 - first half or second half of cluster", :@cluster, nil]
|
359
|
+
]
|
360
|
+
end
|
361
|
+
|
362
|
+
def run
|
363
|
+
clustered {status}
|
364
|
+
end
|
365
|
+
|
366
|
+
end
|
367
|
+
end
|
368
|
+
|
data/test/test_seesaw.rb
ADDED
File without changes
|
metadata
ADDED
@@ -0,0 +1,91 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
rubygems_version: 0.9.4
|
3
|
+
specification_version: 1
|
4
|
+
name: seesaw
|
5
|
+
version: !ruby/object:Gem::Version
|
6
|
+
version: 0.1.0
|
7
|
+
date: 2007-08-18 00:00:00 +10:00
|
8
|
+
summary: Ripple-restart a mongrel cluster with no downtime
|
9
|
+
require_paths:
|
10
|
+
- lib
|
11
|
+
email: max@muermann.org
|
12
|
+
homepage: " by Matt Allen and Max Muermann"
|
13
|
+
rubyforge_project: seesaw
|
14
|
+
description: "== FEATURES/PROBLEMS: * FIX (list of features or problems) == SYNOPSIS: FIX (code sample of usage) == REQUIREMENTS:"
|
15
|
+
autorequire: seesaw/init.rb
|
16
|
+
default_executable:
|
17
|
+
bindir: bin
|
18
|
+
has_rdoc: true
|
19
|
+
required_ruby_version: !ruby/object:Gem::Version::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">"
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 0.0.0
|
24
|
+
version:
|
25
|
+
platform: ruby
|
26
|
+
signing_key:
|
27
|
+
cert_chain:
|
28
|
+
post_install_message:
|
29
|
+
authors:
|
30
|
+
- Matt Allen, Max Muermann
|
31
|
+
files:
|
32
|
+
- History.txt
|
33
|
+
- Manifest.txt
|
34
|
+
- README.txt
|
35
|
+
- Rakefile
|
36
|
+
- bin/seesaw
|
37
|
+
- lib/seesaw/init.rb
|
38
|
+
- lib/seesaw/mongrel_cluster_patch.rb
|
39
|
+
- test/test_seesaw.rb
|
40
|
+
test_files:
|
41
|
+
- test/test_seesaw.rb
|
42
|
+
rdoc_options:
|
43
|
+
- --main
|
44
|
+
- README.txt
|
45
|
+
extra_rdoc_files:
|
46
|
+
- History.txt
|
47
|
+
- Manifest.txt
|
48
|
+
- README.txt
|
49
|
+
executables:
|
50
|
+
- seesaw
|
51
|
+
extensions: []
|
52
|
+
|
53
|
+
requirements: []
|
54
|
+
|
55
|
+
dependencies:
|
56
|
+
- !ruby/object:Gem::Dependency
|
57
|
+
name: gem_plugin
|
58
|
+
version_requirement:
|
59
|
+
version_requirements: !ruby/object:Gem::Version::Requirement
|
60
|
+
requirements:
|
61
|
+
- - ">="
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
version: 0.2.2
|
64
|
+
version:
|
65
|
+
- !ruby/object:Gem::Dependency
|
66
|
+
name: mongrel
|
67
|
+
version_requirement:
|
68
|
+
version_requirements: !ruby/object:Gem::Version::Requirement
|
69
|
+
requirements:
|
70
|
+
- - ">="
|
71
|
+
- !ruby/object:Gem::Version
|
72
|
+
version: 1.0.1
|
73
|
+
version:
|
74
|
+
- !ruby/object:Gem::Dependency
|
75
|
+
name: mongrel_cluster
|
76
|
+
version_requirement:
|
77
|
+
version_requirements: !ruby/object:Gem::Version::Requirement
|
78
|
+
requirements:
|
79
|
+
- - ">="
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: 1.0.2
|
82
|
+
version:
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: hoe
|
85
|
+
version_requirement:
|
86
|
+
version_requirements: !ruby/object:Gem::Version::Requirement
|
87
|
+
requirements:
|
88
|
+
- - ">="
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
version: 1.2.2
|
91
|
+
version:
|