simonmenke-shuttle 0.1.07
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/app_generators/engine/engine_generator.rb +39 -0
- data/app_generators/engine/templates/config/routes.rb +2 -0
- data/app_generators/engine/templates/init.rb +1 -0
- data/app_generators/engine/templates/lib/engine.rb +1 -0
- data/app_generators/engine/templates/rails/init.rb +1 -0
- data/bin/shuttle +20 -0
- data/lib/rubygems_plugin.rb +1 -0
- data/lib/shuttle/actor/actions.rb +76 -0
- data/lib/shuttle/actor.rb +23 -0
- data/lib/shuttle/actors/apache_actor.rb +56 -0
- data/lib/shuttle/actors/base_actor.rb +276 -0
- data/lib/shuttle/actors/mysql_actor.rb +20 -0
- data/lib/shuttle/actors/passenger_actor.rb +19 -0
- data/lib/shuttle/actors/plesk_actor.rb +210 -0
- data/lib/shuttle/actors/sqlite3_actor.rb +44 -0
- data/lib/shuttle/app_runner.rb +118 -0
- data/lib/shuttle/apps/dev.rb +27 -0
- data/lib/shuttle/apps/engines.rb +33 -0
- data/lib/shuttle/apps/jobs.rb +35 -0
- data/lib/shuttle/apps/satellite.rb +32 -0
- data/lib/shuttle/apps/server.rb +70 -0
- data/lib/shuttle/client/auth_token.rb +98 -0
- data/lib/shuttle/client.rb +48 -0
- data/lib/shuttle/exception_handler.rb +53 -0
- data/lib/shuttle/extentions/rubygems_plugin.rb +27 -0
- data/lib/shuttle/extentions/thor_extentions.rb +32 -0
- data/lib/shuttle/job_queue.rb +199 -0
- data/lib/shuttle/satellite/actions.rb +35 -0
- data/lib/shuttle/satellite/dependency_loader.rb +79 -0
- data/lib/shuttle/satellite/persistence.rb +50 -0
- data/lib/shuttle/satellite.rb +49 -0
- data/lib/shuttle/server/daemon.rb +85 -0
- data/lib/shuttle/server/proxy.rb +25 -0
- data/lib/shuttle/server/security.rb +113 -0
- data/lib/shuttle/server.rb +113 -0
- data/lib/shuttle/system/config.rb +36 -0
- data/lib/shuttle/system/helper.rb +21 -0
- data/lib/shuttle/system/options.rb +79 -0
- data/lib/shuttle/system/process_user.rb +75 -0
- data/lib/shuttle/system/satellites.rb +44 -0
- data/lib/shuttle/system/shell.rb +80 -0
- data/lib/shuttle/system.rb +159 -0
- data/lib/shuttle/systems/centos_plesk_system.rb +28 -0
- data/lib/shuttle/systems/macports_system.rb +14 -0
- data/lib/shuttle.rb +82 -0
- data/spec/actor/actions_spec.rb +13 -0
- data/spec/spec_helper.rb +1 -0
- metadata +129 -0
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'drb'
|
2
|
+
require 'drb/ssl'
|
3
|
+
require 'uri'
|
4
|
+
|
5
|
+
module Shuttle
|
6
|
+
class Client
|
7
|
+
|
8
|
+
autoload :AuthToken, File.dirname(__FILE__)+'/client/auth_token'
|
9
|
+
|
10
|
+
# return a DRb uri for the given Shuttle uri.
|
11
|
+
def self.parse_uri(uri)
|
12
|
+
uri = URI.parse(uri)
|
13
|
+
use_ssl = (uri.scheme == 'ssl+shuttle')
|
14
|
+
uri.scheme = 'druby'
|
15
|
+
return use_ssl, uri.to_s
|
16
|
+
end
|
17
|
+
|
18
|
+
# return an potentialy initialize the client to the given token.
|
19
|
+
def self.current(token=nil)
|
20
|
+
@client = connect(token) unless @client
|
21
|
+
@client
|
22
|
+
end
|
23
|
+
|
24
|
+
# connect to the server referenced by the given token.
|
25
|
+
def self.connect(token=nil)
|
26
|
+
token ||= 'core.token'
|
27
|
+
|
28
|
+
[Shuttle::DEFAULT_ROOT_SYSTEM_DIR,
|
29
|
+
Shuttle::DEFAULT_USER_SYSTEM_DIR,
|
30
|
+
File.join(Shuttle::DEFAULT_USER_SYSTEM_DIR, 'tokens'),
|
31
|
+
'.'].each do |path|
|
32
|
+
path = File.expand_path(File.join(path, token))
|
33
|
+
if File.file? path
|
34
|
+
token = path
|
35
|
+
break
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
unless File.file? token
|
40
|
+
raise "Unable to read the token at: #{token}"
|
41
|
+
end
|
42
|
+
|
43
|
+
token = Shuttle::Client::AuthToken.load_file(token) if String === token
|
44
|
+
token.connect if token
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
autoload :Logger, 'logger'
|
2
|
+
|
3
|
+
module Shuttle
|
4
|
+
module ExceptionHandler
|
5
|
+
|
6
|
+
def self.setup(out=STDOUT, err=STDERR)
|
7
|
+
if String === out
|
8
|
+
@out = Logger.new(out, 'daily')
|
9
|
+
else
|
10
|
+
@out = Logger.new(out)
|
11
|
+
end
|
12
|
+
if String === err
|
13
|
+
@err = Logger.new(err, 'daily')
|
14
|
+
else
|
15
|
+
@err = Logger.new(err)
|
16
|
+
end
|
17
|
+
@out.level = Logger::DEBUG
|
18
|
+
@err.level = Logger::DEBUG
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.err
|
22
|
+
@err
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.out
|
26
|
+
@out
|
27
|
+
end
|
28
|
+
|
29
|
+
def logger
|
30
|
+
Shuttle::ExceptionHandler
|
31
|
+
end
|
32
|
+
|
33
|
+
def log(*args, &block)
|
34
|
+
logger.out.info(*args, &block)
|
35
|
+
end
|
36
|
+
|
37
|
+
def report
|
38
|
+
yield
|
39
|
+
rescue Exception => e
|
40
|
+
if StandardError === e
|
41
|
+
logger.err.error(e)
|
42
|
+
else
|
43
|
+
logger.err.fatal(e)
|
44
|
+
end
|
45
|
+
raise e
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def FileUtils.fu_output_message(msg)
|
52
|
+
Shuttle::ExceptionHandler.out.info(msg)
|
53
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'rubygems/specification'
|
2
|
+
|
3
|
+
module Gem # :nodoc:
|
4
|
+
class Specification
|
5
|
+
attribute :engine_dependencies, {}
|
6
|
+
|
7
|
+
def add_engine_dependency(name, options={})
|
8
|
+
name = name.to_s
|
9
|
+
add_runtime_dependency(name, *[options[:version]].compact)
|
10
|
+
@engine_dependencies ||= {}
|
11
|
+
@engine_dependencies[name] = options
|
12
|
+
end
|
13
|
+
|
14
|
+
alias_method :ruby_code_without_engines, :ruby_code # :nodoc:
|
15
|
+
def ruby_code(obj) # :nodoc:
|
16
|
+
return obj.inspect if Hash === obj
|
17
|
+
return ruby_code_without_engines(obj)
|
18
|
+
end
|
19
|
+
|
20
|
+
alias_method :to_ruby_without_engines, :to_ruby # :nodoc:
|
21
|
+
def to_ruby # :nodoc:
|
22
|
+
code = to_ruby_without_engines
|
23
|
+
code.gsub! /s\.engine_dependencies\s+[=]([^\n]+)/, 's.instance_variable_set(:@engine_dependencies,\1)'
|
24
|
+
code
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'thor'
|
2
|
+
|
3
|
+
class Thor
|
4
|
+
class << self
|
5
|
+
attr_accessor :real_namespace # :nodoc:
|
6
|
+
end
|
7
|
+
def self.namespace=(value)
|
8
|
+
Thor.real_namespace = value
|
9
|
+
end
|
10
|
+
def self.namespace
|
11
|
+
Thor.real_namespace
|
12
|
+
end
|
13
|
+
self.namespace = nil
|
14
|
+
end
|
15
|
+
|
16
|
+
module Thor::Util # :nodoc:
|
17
|
+
class << self
|
18
|
+
alias_method :old_constant_to_thor_path, :constant_to_thor_path
|
19
|
+
alias_method :old_constant_from_thor_path, :constant_from_thor_path
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.constant_to_thor_path(*args) # :nodoc:
|
23
|
+
path = old_constant_to_thor_path(*args)
|
24
|
+
path.sub! /^#{Thor.namespace}:/, '' if Thor.namespace
|
25
|
+
path
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.constant_from_thor_path(path) # :nodoc:
|
29
|
+
path = "#{Thor.namespace}:"+path if Thor.namespace
|
30
|
+
old_constant_from_thor_path(path)
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,199 @@
|
|
1
|
+
require 'thread'
|
2
|
+
|
3
|
+
module Shuttle
|
4
|
+
class JobQueue
|
5
|
+
include DRbUndumped
|
6
|
+
|
7
|
+
# create a new job queue
|
8
|
+
def initialize
|
9
|
+
@immediated_jobs = Array.new
|
10
|
+
@canceled_jobs = Array.new
|
11
|
+
@job_queue = Array.new
|
12
|
+
@jobs = Hash.new
|
13
|
+
@mutex = Mutex.new
|
14
|
+
@next_id = 1
|
15
|
+
|
16
|
+
@worker = Thread.new(self) do |job_queue|
|
17
|
+
while job_queue.running? or job_queue.peek
|
18
|
+
|
19
|
+
if job = job_queue.peek
|
20
|
+
job.run(job_queue)
|
21
|
+
job_queue.delete(job.id)
|
22
|
+
else
|
23
|
+
sleep(1)
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# enqueue a new job with the given +name+, +options+ and +proc+
|
31
|
+
def enqueue(name, options={}, &proc)
|
32
|
+
@mutex.synchronize do
|
33
|
+
job = Job.new(@next_id, name, options, &proc)
|
34
|
+
@next_id += 1
|
35
|
+
@jobs[job.id] = job
|
36
|
+
@job_queue.push job.id
|
37
|
+
return job.id
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# dequeue the next job of the queue.
|
42
|
+
def dequeue
|
43
|
+
@mutex.synchronize do
|
44
|
+
id = @job_queue.shift
|
45
|
+
return @jobs.delete(id) if id
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# delete the job associated with the given +id+.
|
50
|
+
def delete(id)
|
51
|
+
@mutex.synchronize do
|
52
|
+
id = @job_queue.delete(id)
|
53
|
+
return @jobs.delete(id) if id
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
# peek at the next job in the queue
|
58
|
+
def peek
|
59
|
+
job = nil
|
60
|
+
@mutex.synchronize do
|
61
|
+
id = @job_queue.first
|
62
|
+
job = @jobs[id] if id
|
63
|
+
end
|
64
|
+
job
|
65
|
+
end
|
66
|
+
|
67
|
+
# get the size of the job queue
|
68
|
+
def size
|
69
|
+
@mutex.synchronize do
|
70
|
+
@job_queue.size
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
# cancel the job associated with the given +id+.
|
75
|
+
def cancel(id)
|
76
|
+
@mutex.synchronize do
|
77
|
+
id = @job_queue.delete(id)
|
78
|
+
if id
|
79
|
+
@jobs.delete(id)
|
80
|
+
@canceled_jobs.push(id)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
# is the job associated with the given +id+ canceled.
|
86
|
+
def canceled?(id)
|
87
|
+
@mutex.synchronize do
|
88
|
+
return !@canceled_jobs.delete(id).nil?
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
# run the job associated with the given +id+ immediately.
|
93
|
+
def immediate(id)
|
94
|
+
@mutex.synchronize do
|
95
|
+
@immediated_jobs.push(id) if @jobs[id]
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
# should the job associated with the given +id+ be run immediately.
|
100
|
+
def immediated?(id)
|
101
|
+
@mutex.synchronize do
|
102
|
+
return !@immediated_jobs.delete(id).nil?
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
# join the worker thread
|
107
|
+
def join!
|
108
|
+
@worker.join
|
109
|
+
end
|
110
|
+
|
111
|
+
# wait until the queue is empty then stop the worker
|
112
|
+
def stop!
|
113
|
+
@mutex.synchronize do
|
114
|
+
@stopped = true
|
115
|
+
end
|
116
|
+
join!
|
117
|
+
end
|
118
|
+
|
119
|
+
# is the queue stopping or stopped?
|
120
|
+
def stopped?
|
121
|
+
@mutex.synchronize do
|
122
|
+
return !!@stopped
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
# is the queue running
|
127
|
+
def running?
|
128
|
+
!stopped?
|
129
|
+
end
|
130
|
+
|
131
|
+
# iterate through all the jobs on the queue
|
132
|
+
def each
|
133
|
+
@mutex.synchronize do
|
134
|
+
@job_queue.each do |id|
|
135
|
+
job = @jobs[id]
|
136
|
+
canceled = @canceled_jobs.include?(id)
|
137
|
+
immediated = @immediated_jobs.include?(id)
|
138
|
+
|
139
|
+
yield(job, canceled, immediated)
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
class Job
|
145
|
+
include DRbUndumped
|
146
|
+
|
147
|
+
attr_accessor :id, :name, :options, :proc
|
148
|
+
|
149
|
+
def initialize(id, name, options={}, &proc)
|
150
|
+
@id = id.to_i
|
151
|
+
@mutex = Mutex.new
|
152
|
+
@name, @options, @proc = name, options, proc
|
153
|
+
@run_at = Time.now + (options.delete(:delay) || 30)
|
154
|
+
end
|
155
|
+
|
156
|
+
def delay
|
157
|
+
@mutex.synchronize do
|
158
|
+
delay = @run_at - Time.now
|
159
|
+
delay = 0 if delay < 0
|
160
|
+
return delay
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
def running?
|
165
|
+
@mutex.synchronize do
|
166
|
+
return @running
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
def waiting?
|
171
|
+
@mutex.synchronize do
|
172
|
+
return @waiting
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
def run(job_queue)
|
177
|
+
Shuttle.report do
|
178
|
+
@waiting = true
|
179
|
+
immediated = canceled = false
|
180
|
+
Shuttle.log "waiting #{@run_at - Time.now}s."
|
181
|
+
until immediated or canceled or @run_at <= Time.now
|
182
|
+
sleep(1)
|
183
|
+
canceled = job_queue.canceled?(self.id)
|
184
|
+
immediated = job_queue.immediated?(self.id)
|
185
|
+
end
|
186
|
+
|
187
|
+
unless canceled
|
188
|
+
@waiting = false
|
189
|
+
@running = true
|
190
|
+
Shuttle.log("[queue]> #{@name}")
|
191
|
+
@proc.call(@options)
|
192
|
+
end
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
end
|
197
|
+
|
198
|
+
end
|
199
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
|
2
|
+
module Shuttle
|
3
|
+
class Satellite
|
4
|
+
module Actions
|
5
|
+
|
6
|
+
def add_engine(name, options={})
|
7
|
+
unless @engines.key? name
|
8
|
+
@engines[name] = options
|
9
|
+
true
|
10
|
+
else
|
11
|
+
false
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def update_engine(name, options={})
|
16
|
+
if @engines.key? name
|
17
|
+
@engines[name] = options
|
18
|
+
true
|
19
|
+
else
|
20
|
+
false
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def remove_engine(name)
|
25
|
+
if @engines.key? name
|
26
|
+
@engines.delete(name)
|
27
|
+
true
|
28
|
+
else
|
29
|
+
false
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
|
2
|
+
autoload :TSort, 'tsort'
|
3
|
+
|
4
|
+
module Shuttle
|
5
|
+
class Satellite
|
6
|
+
class DependencyLoader
|
7
|
+
|
8
|
+
attr_reader :names, :specs, :engines
|
9
|
+
|
10
|
+
def self.load_for(engines)
|
11
|
+
dependency_loader = self.new(engines)
|
12
|
+
dependency_loader.add_dependecies!
|
13
|
+
dependency_loader.order_by_dependecies!
|
14
|
+
|
15
|
+
return dependency_loader
|
16
|
+
end
|
17
|
+
|
18
|
+
def initialize(engines)
|
19
|
+
specs = engines.collect do |k,r|
|
20
|
+
s = Gem.source_index.find_name(k, Gem::Requirement.new(r[:version] || ">= 0.0.0"))
|
21
|
+
s.last
|
22
|
+
end.compact
|
23
|
+
|
24
|
+
@names = specs.collect { |spec| spec.name }
|
25
|
+
@specs = specs.inject({}) { |h, spec| h[spec.name] = spec ; h }
|
26
|
+
@engines = engines
|
27
|
+
end
|
28
|
+
|
29
|
+
def add_dependecies!
|
30
|
+
@specs.values.each do |spec|
|
31
|
+
add_dependecies_for spec
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def order_by_dependecies!
|
36
|
+
@names = tsort
|
37
|
+
end
|
38
|
+
|
39
|
+
def each
|
40
|
+
@names.each do |name|
|
41
|
+
yield(@specs[name])
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def reverse_each
|
46
|
+
@names.reverse.each do |name|
|
47
|
+
yield(@specs[name])
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
include TSort
|
54
|
+
|
55
|
+
def add_dependecies_for(spec)
|
56
|
+
engine_dependencies = spec.engine_dependencies || {}
|
57
|
+
engine_dependencies.each do |name, options|
|
58
|
+
gems = Gem.source_index.find_name(name, [options[:version]].compact)
|
59
|
+
next unless gem = gems.last
|
60
|
+
next if @names.include?(name) and gem.version <= @specs[gem.name].version
|
61
|
+
@specs[gem.name] = gem
|
62
|
+
@names.push(gem.name)
|
63
|
+
add_dependecies_for(gem)
|
64
|
+
end
|
65
|
+
@engines = @engines.merge(engine_dependencies)
|
66
|
+
end
|
67
|
+
|
68
|
+
def tsort_each_node(&block)
|
69
|
+
@names.each(&block)
|
70
|
+
end
|
71
|
+
|
72
|
+
def tsort_each_child(node, &block)
|
73
|
+
engine_dependencies = @specs[node].engine_dependencies || {}
|
74
|
+
engine_dependencies.keys.each(&block)
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
|
3
|
+
module Shuttle
|
4
|
+
class Satellite
|
5
|
+
module Persistence
|
6
|
+
|
7
|
+
def self.included(base)
|
8
|
+
base.extend Shuttle::Satellite::Persistence::ClassMethods
|
9
|
+
end
|
10
|
+
|
11
|
+
module ClassMethods
|
12
|
+
|
13
|
+
def load(data)
|
14
|
+
Shuttle::Satellite.new(YAML.load(data))
|
15
|
+
end
|
16
|
+
|
17
|
+
def load_file(path)
|
18
|
+
return nil unless File.exist?(path)
|
19
|
+
Shuttle::Satellite.new(YAML.load_file(path))
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
def dump(io=nil)
|
25
|
+
data = {}
|
26
|
+
|
27
|
+
private_vars = %w( basedomain subdomain )
|
28
|
+
instance_variables.each do |ivar_name|
|
29
|
+
ivar_name = ivar_name.to_s
|
30
|
+
ivar_name =~ /^@(.+)$/
|
31
|
+
name = $1
|
32
|
+
unless private_vars.include? name
|
33
|
+
data[name] = instance_variable_get(ivar_name.to_sym)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
if io
|
38
|
+
io.write YAML.dump(data)
|
39
|
+
else
|
40
|
+
YAML.dump(data)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def dump_file(path)
|
45
|
+
File.open(path, 'w+') { |f| dump(f) }
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
|
2
|
+
module Shuttle
|
3
|
+
class Satellite
|
4
|
+
|
5
|
+
autoload :Actions, File.dirname(__FILE__)+'/satellite/actions'
|
6
|
+
autoload :Persistence, File.dirname(__FILE__)+'/satellite/persistence'
|
7
|
+
autoload :DependencyLoader, File.dirname(__FILE__)+'/satellite/dependency_loader'
|
8
|
+
|
9
|
+
include Shuttle::Satellite::Actions
|
10
|
+
include Shuttle::Satellite::Persistence
|
11
|
+
|
12
|
+
attr_reader :domain, :engines
|
13
|
+
|
14
|
+
def initialize(domain)
|
15
|
+
if Hash === domain
|
16
|
+
domain.each do |name, value|
|
17
|
+
instance_variable_set("@#{name}".to_sym, value)
|
18
|
+
end
|
19
|
+
else
|
20
|
+
@domain = domain
|
21
|
+
@engines = {}
|
22
|
+
end
|
23
|
+
@domain.gsub! /^www\./, ''
|
24
|
+
end
|
25
|
+
|
26
|
+
def basedomain
|
27
|
+
unless @basedomain
|
28
|
+
parts = self.domain.split('.')
|
29
|
+
parts = parts[-2..-1]
|
30
|
+
@basedomain = parts.join('.')
|
31
|
+
end
|
32
|
+
@basedomain
|
33
|
+
end
|
34
|
+
|
35
|
+
def subdomain
|
36
|
+
unless @subdomain
|
37
|
+
parts = self.domain.split('.')
|
38
|
+
parts = parts[0..-3]
|
39
|
+
@subdomain = parts.join('.')
|
40
|
+
end
|
41
|
+
@subdomain unless @subdomain == ''
|
42
|
+
end
|
43
|
+
|
44
|
+
def subdomain?
|
45
|
+
!self.subdomain.nil?
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
require 'uri'
|
2
|
+
|
3
|
+
module Shuttle
|
4
|
+
class Server
|
5
|
+
|
6
|
+
module Daemon # :nodoc:
|
7
|
+
|
8
|
+
def self.included(base)
|
9
|
+
base.extend Shuttle::Server::Daemon::ClassMethods
|
10
|
+
end
|
11
|
+
|
12
|
+
# all a daemon needs to run
|
13
|
+
module ClassMethods
|
14
|
+
|
15
|
+
# construct a Shuttle uri from a DRb uri
|
16
|
+
def construct_uri(uri)
|
17
|
+
uri = URI.parse(uri)
|
18
|
+
uri.scheme = ( Shuttle.system.use_ssl? ? 'ssl+shuttle' : 'shuttle')
|
19
|
+
uri.to_s
|
20
|
+
end
|
21
|
+
|
22
|
+
# stop teh server
|
23
|
+
def stop
|
24
|
+
Shuttle.client.stop_server
|
25
|
+
end
|
26
|
+
|
27
|
+
# start the server
|
28
|
+
def start
|
29
|
+
start_with_failsafe
|
30
|
+
end
|
31
|
+
|
32
|
+
# start the failsafe runner.
|
33
|
+
def start_with_failsafe
|
34
|
+
stop_server = false
|
35
|
+
wait_before_start = 0
|
36
|
+
retries = 0
|
37
|
+
until stop_server
|
38
|
+
if wait_before_start > 0
|
39
|
+
sleep(wait_before_start)
|
40
|
+
wait_before_start = 0
|
41
|
+
end
|
42
|
+
|
43
|
+
pid = Process.fork { self.run_server }
|
44
|
+
Process.waitpid(pid, 0)
|
45
|
+
case $?.exitstatus
|
46
|
+
when Shuttle::STOP_STATUS
|
47
|
+
stop_server = true
|
48
|
+
when Shuttle::RESTART_STATUS
|
49
|
+
wait_before_start = 2
|
50
|
+
when Shuttle::RELOAD_STATUS
|
51
|
+
stop_server = true
|
52
|
+
Shuttle.system.run(%{sleep 2 ; #{Shuttle::BIN_PATH} #{ORIGINAL_ARGV.join(' ')}})
|
53
|
+
else
|
54
|
+
retries += 1
|
55
|
+
stop_server = true if retries >= 3
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
path = Shuttle.system.path('Server.pid')
|
60
|
+
File.unlink(path) if File.file?(path)
|
61
|
+
end
|
62
|
+
|
63
|
+
# start the actual DRb server
|
64
|
+
def run_server
|
65
|
+
Dir.chdir(Shuttle.system.root)
|
66
|
+
|
67
|
+
Shuttle.log "Server started"
|
68
|
+
DRb.start_service "druby://localhost:5000", self.proxy, self.options_for_server
|
69
|
+
Shuttle.log "listening at #{self.construct_uri("druby://#{`hostname`.strip}:5000")}"
|
70
|
+
make_client_cert_public!
|
71
|
+
|
72
|
+
at_exit do
|
73
|
+
unless $task_child
|
74
|
+
Shuttle.system.queue.stop!
|
75
|
+
Shuttle.log "Server stopped"
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
DRb.thread.join
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
|
2
|
+
module Shuttle
|
3
|
+
class Server
|
4
|
+
# the proxy object hides all the server internals from the clients.
|
5
|
+
class Proxy
|
6
|
+
|
7
|
+
def initialize(server)
|
8
|
+
@server = server
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.allow(*methods)
|
12
|
+
methods.each do |method|
|
13
|
+
module_eval %{ def #{method}(*args,&block) ; @server.#{method}(*args,&block) ; end }
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
allow :stop_server, :restart_server, :reload_server, :server_version, :update_server, :install_satellite, :uninstall_satellite, :install_engine, :update_engine, :uninstall_engine, :satellites, :queued_jobs, :cancel_job, :immediate_job
|
18
|
+
|
19
|
+
class << self
|
20
|
+
undef_method :allow
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|