svdir 0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +29 -0
- data/LICENSE +19 -0
- data/README +67 -0
- data/Rakefile +66 -0
- data/example/svctl +117 -0
- data/lib/sys/sv/statusbytes.rb +53 -0
- data/lib/sys/sv/svdir.rb +224 -0
- data/lib/sys/sv/util.rb +36 -0
- data/test/fixtures/PrefabSvDir.rb +22 -0
- data/test/fixtures/TempSvDir.rb +62 -0
- data/test/services/corrupt-normd/down +0 -0
- data/test/services/corrupt-normd/supervise/ok +0 -0
- data/test/services/corrupt-normd/supervise/status +0 -0
- data/test/services/corrupt-normu/supervise/ok +0 -0
- data/test/services/corrupt-normu/supervise/status +0 -0
- data/test/services/corrupt-zero-normd/down +0 -0
- data/test/services/corrupt-zero-normd/supervise/ok +0 -0
- data/test/services/corrupt-zero-normd/supervise/status +0 -0
- data/test/services/corrupt-zero-normu/supervise/ok +0 -0
- data/test/services/corrupt-zero-normu/supervise/status +0 -0
- data/test/services/down-0-normd-nowant/down +0 -0
- data/test/services/down-0-normd-nowant/supervise/ok +0 -0
- data/test/services/down-0-normd-nowant/supervise/status +0 -0
- data/test/services/down-0-normu-nowant/supervise/ok +0 -0
- data/test/services/down-0-normu-nowant/supervise/status +0 -0
- data/test/services/up-12526-normu-wantd/supervise/ok +0 -0
- data/test/services/up-12526-normu-wantd/supervise/status +0 -0
- data/test/services/up-12581-normd-wantd-paused/down +0 -0
- data/test/services/up-12581-normd-wantd-paused/supervise/ok +0 -0
- data/test/services/up-12581-normd-wantd-paused/supervise/status +0 -0
- data/test/services/up-12581-normu-wantd-paused/supervise/ok +0 -0
- data/test/services/up-12581-normu-wantd-paused/supervise/status +0 -0
- data/test/services/up-12816-normd-nowant/down +0 -0
- data/test/services/up-12816-normd-nowant/supervise/ok +0 -0
- data/test/services/up-12816-normd-nowant/supervise/status +0 -0
- data/test/services/up-12816-normu-nowant/supervise/ok +0 -0
- data/test/services/up-12816-normu-nowant/supervise/status +0 -0
- data/test/services/up-12868-normd-wantu-paused/down +0 -0
- data/test/services/up-12868-normd-wantu-paused/supervise/ok +0 -0
- data/test/services/up-12868-normd-wantu-paused/supervise/status +0 -0
- data/test/services/up-12868-normd-wantu/down +0 -0
- data/test/services/up-12868-normd-wantu/supervise/ok +0 -0
- data/test/services/up-12868-normd-wantu/supervise/status +0 -0
- data/test/services/up-12868-normu-wantu-paused/supervise/ok +0 -0
- data/test/services/up-12868-normu-wantu-paused/supervise/status +0 -0
- data/test/services/up-12868-normu-wantu/supervise/ok +0 -0
- data/test/services/up-12868-normu-wantu/supervise/status +0 -0
- data/test/services/up-16464-normd-wantd/down +0 -0
- data/test/services/up-16464-normd-wantd/supervise/ok +0 -0
- data/test/services/up-16464-normd-wantd/supervise/status +0 -0
- data/test/testbase.rb +30 -0
- data/test/ts_corrupt.rb +133 -0
- data/test/ts_nosupervisor.rb +81 -0
- data/test/ts_signal.rb +128 -0
- data/test/ts_svstat.rb +548 -0
- metadata +117 -0
data/lib/sys/sv/util.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Mike Pomraning
|
3
|
+
# Copyright:: Copyright (c) 2011 Qualys, Inc.
|
4
|
+
# License:: MIT (see the file LICENSE)
|
5
|
+
#
|
6
|
+
|
7
|
+
require 'fcntl' # O_RDONLY | O_NONBLOCK
|
8
|
+
|
9
|
+
module Sys # :nodoc:
|
10
|
+
module Sv # :nodoc:
|
11
|
+
|
12
|
+
module Util #:nodoc:
|
13
|
+
def self.open_read(fn, &p)
|
14
|
+
open_nonblock(fn, Fcntl::O_RDONLY, p)
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.open_write(fn, &p)
|
18
|
+
open_nonblock(fn, Fcntl::O_WRONLY, p)
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
def self.open_nonblock(fn, mode, p)
|
23
|
+
mode |= Fcntl::O_NONBLOCK
|
24
|
+
return File.open(fn, mode) if p.nil?
|
25
|
+
|
26
|
+
begin
|
27
|
+
f = File.open(fn, mode)
|
28
|
+
return p.call(f)
|
29
|
+
ensure
|
30
|
+
f.close if f
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end #-- module Util
|
34
|
+
|
35
|
+
end #-- module Sv
|
36
|
+
end #-- module Sys
|
@@ -0,0 +1,22 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# Author:: Mike Pomraning
|
4
|
+
# Copyright:: Copyright (c) 2011 Qualys, Inc.
|
5
|
+
# License:: MIT (see the file LICENSE)
|
6
|
+
|
7
|
+
require 'sys/sv/svdir'
|
8
|
+
|
9
|
+
module Fixtures
|
10
|
+
module PrefabSvDir
|
11
|
+
# Test::Unit::TestCase helper to recognize "static" supervisory
|
12
|
+
# directories.
|
13
|
+
def setup
|
14
|
+
dirname = self.class.name.gsub(/^TC_/, '').tr('_', '-')
|
15
|
+
dirname = File.join(File.dirname(__FILE__), '..', 'services', dirname)
|
16
|
+
|
17
|
+
raise RuntimeError.new("Expected static testing dir #{dirname} not found") unless File.directory? dirname
|
18
|
+
@svdir = Sys::Sv::SvDir.new dirname
|
19
|
+
super
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end # -- module Fixtures
|
@@ -0,0 +1,62 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# Author:: Mike Pomraning
|
4
|
+
# Copyright:: Copyright (c) 2011 Qualys, Inc.
|
5
|
+
# License:: MIT (see the file LICENSE)
|
6
|
+
|
7
|
+
require 'tmpdir' # Dir.tmpdir
|
8
|
+
require 'fileutils' # FileUtils.rm_rf
|
9
|
+
require 'sys/sv/svdir'
|
10
|
+
|
11
|
+
module Fixtures
|
12
|
+
module TempSvDir
|
13
|
+
# Test::Unit::TestCase mixin to create one-off service directories
|
14
|
+
|
15
|
+
# Make a temp sv-style dir with supervise/ subdir and two FIFOs
|
16
|
+
def setup
|
17
|
+
i = 0
|
18
|
+
|
19
|
+
# make a temporary dir
|
20
|
+
begin
|
21
|
+
@svdirname = File.join(Dir::tmpdir, "TempSvDir.#{$$}.#{i}")
|
22
|
+
i += 1
|
23
|
+
Dir::mkdir(@svdirname)
|
24
|
+
rescue Errno::EEXIST
|
25
|
+
retry if i < 100
|
26
|
+
raise RuntimeError.new("Unable to create a mock svc dir. Check #{Dir::tmpdir}")
|
27
|
+
end
|
28
|
+
|
29
|
+
Dir::mkdir File.join(@svdirname, "supervise")
|
30
|
+
|
31
|
+
# Make and hold open our FIFOs
|
32
|
+
@fifos = {}
|
33
|
+
for fn in %w(control ok)
|
34
|
+
@fifos[ fn.to_sym ] = openfifo(File.join(@svdirname, "supervise", fn))
|
35
|
+
end
|
36
|
+
|
37
|
+
@svdir = Sys::Sv::SvDir.new(@svdirname)
|
38
|
+
super
|
39
|
+
end
|
40
|
+
|
41
|
+
def fifo_control
|
42
|
+
@fifos[:control]
|
43
|
+
end
|
44
|
+
|
45
|
+
def fifo_ok
|
46
|
+
@fifos[:ok]
|
47
|
+
end
|
48
|
+
|
49
|
+
def teardown
|
50
|
+
@fifos.each_value {|f| f.close rescue nil}
|
51
|
+
FileUtils.rm_rf( @svdirname )
|
52
|
+
super
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
def openfifo(fn)
|
57
|
+
system "mkfifo #{Regexp.quote(fn)}"
|
58
|
+
File.open(fn, Fcntl::O_NONBLOCK|Fcntl::O_RDONLY)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
end # -- module Fixtures
|
File without changes
|
File without changes
|
Binary file
|
File without changes
|
Binary file
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
Binary file
|
File without changes
|
Binary file
|
File without changes
|
Binary file
|
File without changes
|
File without changes
|
Binary file
|
File without changes
|
Binary file
|
File without changes
|
File without changes
|
Binary file
|
File without changes
|
Binary file
|
File without changes
|
File without changes
|
Binary file
|
File without changes
|
File without changes
|
Binary file
|
File without changes
|
Binary file
|
File without changes
|
Binary file
|
File without changes
|
File without changes
|
Binary file
|
data/test/testbase.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# Author:: Mike Pomraning
|
4
|
+
# Copyright:: Copyright (c) 2011 Qualys, Inc.
|
5
|
+
# License:: MIT (see the file LICENSE)
|
6
|
+
|
7
|
+
require 'test/unit'
|
8
|
+
|
9
|
+
class Test::Unit::TestCase
|
10
|
+
# Load the appropriate Fixtures::Blah
|
11
|
+
def self.include_fixtures(sym, *optional)
|
12
|
+
raise RuntimeError.new("Must subclass Test::Unit::TestCase") \
|
13
|
+
if self == Test::Unit::TestCase
|
14
|
+
|
15
|
+
for s in [sym, *optional]
|
16
|
+
load "fixtures/#{sym}.rb"
|
17
|
+
self.__send__(:include, Module.const_get(:Fixtures).const_get(sym))
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.include_fixture(sym)
|
23
|
+
include_fixtures(sym)
|
24
|
+
end
|
25
|
+
|
26
|
+
def assert_elapsed_time(elapsed)
|
27
|
+
assert_kind_of(::Float, elapsed, "elapsed time measurement was wrong type")
|
28
|
+
assert(elapsed > 0.0, "elapsed time measurement was not > 0")
|
29
|
+
end
|
30
|
+
end
|
data/test/ts_corrupt.rb
ADDED
@@ -0,0 +1,133 @@
|
|
1
|
+
# Test the basics of service status interrogation
|
2
|
+
#
|
3
|
+
# Author:: Mike Pomraning
|
4
|
+
# Copyright:: Copyright (c) 2011 Qualys, Inc.
|
5
|
+
# License:: MIT (see the file LICENSE)
|
6
|
+
#
|
7
|
+
|
8
|
+
require 'testbase'
|
9
|
+
require 'sys/sv/svdir'
|
10
|
+
|
11
|
+
class TC_corrupt_normu < Test::Unit::TestCase
|
12
|
+
include_fixture :PrefabSvDir
|
13
|
+
|
14
|
+
def test_down?
|
15
|
+
assert_raise(::Errno::EPROTO) do
|
16
|
+
@svdir.down?
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_want_up?
|
21
|
+
assert_raise(::Errno::EPROTO) do
|
22
|
+
@svdir.want_up?
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_pid
|
27
|
+
assert_raise(::Errno::EPROTO) do
|
28
|
+
@svdir.pid
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_want_down?
|
33
|
+
assert_raise(::Errno::EPROTO) do
|
34
|
+
@svdir.want_down?
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_normally_up?
|
39
|
+
assert(@svdir.normally_up?, "normally_up? should still succeed even on corrupted SvDir")
|
40
|
+
end
|
41
|
+
|
42
|
+
def test_paused?
|
43
|
+
assert_raise(::Errno::EPROTO) do
|
44
|
+
@svdir.paused?
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def test_normally_down?
|
49
|
+
assert(!@svdir.normally_down?, "normally_down? should still succeed even on corrupted SvDir")
|
50
|
+
end
|
51
|
+
|
52
|
+
def test_up?
|
53
|
+
assert_raise(::Errno::EPROTO) do
|
54
|
+
@svdir.up?
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def test_downtime
|
59
|
+
assert_raise(::Errno::EPROTO) do
|
60
|
+
@svdir.downtime
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def test_uptime
|
65
|
+
assert_raise(::Errno::EPROTO) do
|
66
|
+
@svdir.uptime
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
class TC_corrupt_normd < Test::Unit::TestCase
|
72
|
+
include_fixture :PrefabSvDir
|
73
|
+
|
74
|
+
def test_down?
|
75
|
+
assert_raise(::Errno::EPROTO) do
|
76
|
+
@svdir.down?
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def test_want_up?
|
81
|
+
assert_raise(::Errno::EPROTO) do
|
82
|
+
@svdir.want_up?
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def test_pid
|
87
|
+
assert_raise(::Errno::EPROTO) do
|
88
|
+
@svdir.pid
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def test_want_down?
|
93
|
+
assert_raise(::Errno::EPROTO) do
|
94
|
+
@svdir.want_down?
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
def test_normally_up?
|
99
|
+
assert(!@svdir.normally_up?, "normally_up? should still succeed even on corrupted SvDir")
|
100
|
+
end
|
101
|
+
|
102
|
+
def test_paused?
|
103
|
+
assert_raise(::Errno::EPROTO) do
|
104
|
+
@svdir.paused?
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
def test_normally_down?
|
109
|
+
assert(@svdir.normally_down?, "normally_down? should still succeed even on corrupted SvDir")
|
110
|
+
end
|
111
|
+
|
112
|
+
def test_up?
|
113
|
+
assert_raise(::Errno::EPROTO) do
|
114
|
+
@svdir.up?
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
def test_downtime
|
119
|
+
assert_raise(::Errno::EPROTO) do
|
120
|
+
@svdir.downtime
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
def test_uptime
|
125
|
+
assert_raise(::Errno::EPROTO) do
|
126
|
+
@svdir.uptime
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
# Zero-byte status files take a slightly different code path to reach EPROTO
|
132
|
+
class TC_corrupt_zero_normd < TC_corrupt_normd; end
|
133
|
+
class TC_corrupt_zero_normu < TC_corrupt_normu; end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# Handle the case of no supervisor running
|
4
|
+
#
|
5
|
+
# Author:: Mike Pomraning
|
6
|
+
# Copyright:: Copyright (c) 2011 Qualys, Inc.
|
7
|
+
# License:: MIT (see the file LICENSE)
|
8
|
+
#
|
9
|
+
|
10
|
+
$:.unshift File.join(File.dirname(__FILE__), "lib")
|
11
|
+
|
12
|
+
require 'testbase'
|
13
|
+
require 'sys/sv/svdir'
|
14
|
+
|
15
|
+
class TestSvcNoSupervisor < Test::Unit::TestCase
|
16
|
+
|
17
|
+
include_fixture :TempSvDir
|
18
|
+
|
19
|
+
def setup
|
20
|
+
ret = super
|
21
|
+
# close .../control and .../ok
|
22
|
+
fifo_control.close
|
23
|
+
fifo_ok.close
|
24
|
+
ret
|
25
|
+
end
|
26
|
+
|
27
|
+
# Verify that unknown signal arguments still throw ArgumentError
|
28
|
+
def test_signal_unknown
|
29
|
+
[ :invalid, 'invalid' ].each do |bogus|
|
30
|
+
assert_raise ArgumentError do
|
31
|
+
@svdir.signal bogus
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# Verify that a known signal generates ENXIO
|
37
|
+
def test_signal_up
|
38
|
+
[ :up, 'up' ].each do |c|
|
39
|
+
assert_raise Errno::ENXIO do
|
40
|
+
@svdir.signal c
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
# Verify svok? == false
|
46
|
+
def test_not_svok
|
47
|
+
assert @svdir.svok? == false
|
48
|
+
end
|
49
|
+
|
50
|
+
# Verify that the StatusBytes delegates throw ENXIO
|
51
|
+
[:down?, :downtime, :paused?, :pid, :up?, :uptime, :want_down?, :want_up?].
|
52
|
+
each do |m|
|
53
|
+
define_method "test_err_#{m}" do
|
54
|
+
assert_raise Errno::ENXIO do
|
55
|
+
@svdir.__send__(m)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
# Verify that normally_up? still functions
|
61
|
+
def test_normally_up?
|
62
|
+
assert_nothing_raised do
|
63
|
+
@svdir.normally_up?
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
# Verify that normally_down? still functions
|
68
|
+
def test_normally_down?
|
69
|
+
assert_nothing_raised do
|
70
|
+
@svdir.normally_down?
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
# Verify that log() still functions
|
75
|
+
def test_normally_down?
|
76
|
+
assert_nothing_raised do
|
77
|
+
@svdir.log
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|