simonmenke-shuttle 0.1.07
Sign up to get free protection for your applications and to get access to all the features.
- 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
|