spiderfw 0.6.6 → 0.6.7

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG CHANGED
@@ -1,3 +1,7 @@
1
+ = 0.6.7
2
+ == 26 July, 2011
3
+ * Process management and app setup enhancements
4
+
1
5
  = 0.6.6
2
6
  == 19 July, 2011
3
7
  * Fix: use SEE_OTHER as default redirect code to avoid FF 5 caching
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.6.6
1
+ 0.6.7
data/apps/master/_init.rb CHANGED
@@ -14,6 +14,8 @@ require 'apps/master/master'
14
14
  require 'apps/master/models/admin'
15
15
  require 'apps/master/models/customer'
16
16
  require 'apps/master/models/installation'
17
+ require 'apps/master/models/command'
18
+ require 'apps/master/models/event'
17
19
  require 'apps/master/models/remote_log'
18
20
  require 'apps/master/models/server'
19
21
  require 'apps/master/models/scout_plugin_info'
@@ -18,7 +18,7 @@ module Spider; module Master
18
18
  #route /servers\/([^\/]+)/, ServerController, :do => lambda{ |id| @request.misc[:server] = Server.new(id) }
19
19
  route 'login', LoginController
20
20
 
21
- require_user Master::Admin, :unless => [:login, :admin, :ping], :redirect => 'login'
21
+ require_user Master::Admin, :unless => [:login, :admin, :ping, :servant_event], :redirect => 'login'
22
22
  require_user Spider::Auth::SuperUser, :only => [:admin]
23
23
 
24
24
 
@@ -118,28 +118,34 @@ module Spider; module Master
118
118
  @installation = Installation.new(id) unless id == 'new'
119
119
  @scene.edit = (@request.params['_w'] && @request.params['_w'].key?('installation_form')) || @request.params.key?('edit') || id == 'new'
120
120
  @scene.pk = id
121
-
122
- # if id == 'new'
123
- # if @request.params.key?('installation_create') && !@request.params['installation_name'].empty?
124
- # i = Installation.new(:name => @request.params['installation_name'])
125
- # i.customer = @customer
126
- # i.save
127
- # redirect(File.dirname(@request.path)+"/#{i.id}")
128
- # end
129
- # else
130
- # if @request.params.key?('save_apps')
131
- # @installation.apps = @request.params['apps'].keys.join(',')
132
- # @installation.save
133
- # redirect(request.path)
134
- # end
135
- # @scene.install_apps = JSON.parse(@installation.apps) unless @installation.apps.blank?
136
- # @scene.install_apps ||= []
137
- # @scene.apps = Spider::AppServer.apps_by_id
138
- # end
121
+
122
+ if @request.params['add_command']
123
+ command = @request.params['command']
124
+ args = @request.params['arguments']
125
+ arguments = args
126
+ # FIXME: move somewhere else
127
+ case command
128
+ when 'gems', 'apps'
129
+ arguments = args.split(/\s*,\s*/).to_json
130
+ end
131
+ Master::Command.create(
132
+ :installation => @installation,
133
+ :name => @request.params['command'],
134
+ :arguments => arguments,
135
+ :status => 'pending'
136
+ )
137
+ redirect(@request.path)
138
+
139
+ end
139
140
  @scene.install_apps = JSON.parse(@installation.apps) unless @installation.apps.blank?
140
141
  @scene.install_apps ||= []
141
142
  @scene.apps = Spider::AppServer.apps_by_id
142
143
  @scene.logs = RemoteLog.where(:installation => @installation)
144
+ @scene.commands = Master::Command.where{ |c| (c.installation == @installation) }.order_by(:obj_created)
145
+ @scene.available_commands = {
146
+ 'gems' => _('Install or update gems'),
147
+ 'apps' => _('Install or update apps')
148
+ }
143
149
  @scene << {
144
150
  :customer => @customer,
145
151
  :installation => @installation
@@ -345,15 +351,66 @@ module Spider; module Master
345
351
  RemoteLog.create(:text => desc, :level => level, :time => time, :installation => install)
346
352
  end
347
353
  response = {
348
- :pong => DateTime.new
354
+ :pong => DateTime.now
349
355
  }
350
- # server.pending_commands.each do |command|
351
- # response[:commands] ||= []
352
- # response[:commands] << command.to_h
353
- # end
356
+ commands = []
357
+ Master::Command.where{ |c| (c.installation == install) & (c.status == 'pending') }.each do |c|
358
+ commands << {
359
+ :id => c.uuid,
360
+ :name => c.name,
361
+ :arguments => c.arguments ? JSON.parse(c.arguments) : nil
362
+ }
363
+ end
364
+ response[:commands] = commands unless commands.empty?
354
365
  $out << response.to_json
366
+ Master::Command.where{ |c| (c.installation == install) & (c.status == 'pending') }.each do |c|
367
+ c.sent = DateTime.now
368
+ c.status = 'sent'
369
+ c.save
370
+ end
355
371
  end
356
372
 
373
+ __.json
374
+ def servant_event
375
+ params = @request.params.clone
376
+ name = params.delete('event')
377
+ install_id = params.delete('install_id')
378
+ unless install_id
379
+ Spider.logger.error("No install_id passed in ping")
380
+ done
381
+ end
382
+ install = Spider::Master::Installation.load_or_create(:uuid => install_id)
383
+ details = @request.params['details']
384
+ params = JSON.parse(details)
385
+ Event.create(
386
+ :installation => install,
387
+ :name => name,
388
+ :details => details
389
+ )
390
+ case name.to_sym
391
+ when :command_done
392
+ cmd = Master::Command.load(:uuid => params['id'])
393
+ cmd.done = DateTime.now
394
+ cmd.result = params['res'].to_json
395
+ cmd.status = 'success'
396
+ cmd.save
397
+ when :plan_done
398
+ results = params['results']
399
+ results.each do |res|
400
+ cmd = Master::Command.load(:uuid => res['command_id'])
401
+ if res['previous_error']
402
+ cmd.status = 'not_done'
403
+ cmd.save
404
+ elsif res['error']
405
+ cmd.status = 'error'
406
+ cmd.save
407
+ end
408
+ end
409
+ end
410
+ end
411
+
412
+
413
+
357
414
  private
358
415
 
359
416
  def decompress_string(str)
@@ -1,17 +1,24 @@
1
1
  module Spider; module Master
2
2
 
3
- class Command < Spider::Model::BaseModel
4
- remove_element :id
5
- element :id, UUID
3
+ class Command < Spider::Model::Managed
4
+ element :installation, Installation, :add_multiple_reverse => :commands
5
+ element :uuid, UUID
6
6
  element :name, String
7
7
  element :arguments, Text
8
8
  element :status, {
9
9
  'pending' => 'Pending',
10
+ 'sent' => 'Sent',
10
11
  'success' => 'Success',
11
- 'failure' => 'Failure'
12
+ 'failure' => 'Failure',
13
+ 'not_done' => 'Not done'
12
14
  }, :default => 'pending'
13
- element :executed, DateTime
15
+ element :sent, DateTime
16
+ element :done, DateTime
14
17
  element :result, Text
18
+
19
+ def to_s
20
+ "#{self.name} '#{self.arguments}' - #{self.status}"
21
+ end
15
22
  end
16
23
 
17
24
  end; end
@@ -0,0 +1,9 @@
1
+ module Spider; module Master
2
+
3
+ class Event < Spider::Model::Managed
4
+ element :installation, Installation, :add_multiple_reverse => :events
5
+ element :name, String
6
+ element :details, Text
7
+ end
8
+
9
+ end; end
@@ -20,6 +20,12 @@
20
20
  <h2>_(Installation "%s") % [@installation]</h2>
21
21
  <a href="?edit" class="manage edit">_(Edit)</a>
22
22
  </div>
23
+ <div class="details">
24
+ _(Last check-in): { @installation.last_check.lformat(:short) }
25
+ <tpl:pass sp:if="@installation.interval">
26
+ _(Next check-in): { (@installation.last_check + @installation.interval).lformat(:short) }
27
+ </tpl:pass>
28
+ </div>
23
29
  <core:tabs id="tabs">
24
30
  <tab label="_(Apps)" id="apps">
25
31
  <div class="apps">
@@ -43,6 +49,22 @@
43
49
  <core:table id="logs_table" queryset="@logs" sort="time,desc" />
44
50
  </div>
45
51
  </tab>
52
+ <tab label="_(Commands)" id="commands">
53
+ <div class="commands">
54
+ <h4>_(Commands)</h4><a href="#" class="manage add">_(Add command)</a>
55
+ <div id="add_command">
56
+ <form>
57
+ <select name="command">
58
+ <option></option>
59
+ <option sp:each="@available_commands |k, v|" value="{ k }">{ v }</option>
60
+ </select>
61
+ <input type="text" name="arguments">
62
+ <input type="submit" name="add_command" value="_(Ok)">
63
+ </form>
64
+ </div>
65
+ <core:list id="commands_list" queryset="@commands" delete="true" />
66
+ </div>
67
+ </tab>
46
68
  </core:tabs>
47
69
  </div>
48
70
  </div>
@@ -10,9 +10,14 @@ module Spider
10
10
  def initialize(url)
11
11
  @url = url
12
12
  end
13
+
14
+ def http_client
15
+ HTTPClient.new
16
+ end
13
17
 
14
- def ping_server(url=@url)
15
- clnt = HTTPClient.new
18
+ def ping_server(url=nil)
19
+ url ||= @url
20
+ clnt = self.http_client
16
21
  status = Servant.status
17
22
  status[:apps] = status[:apps].to_json
18
23
  last_check_file = File.join(Spider.paths[:var], 'memory', 'servant_last_check')
@@ -29,15 +34,24 @@ module Spider
29
34
  end
30
35
  File.open(last_check_file, 'w'){ |f| f << Time.now.to_s }
31
36
  res = JSON.parse(res.content)
32
- if res[:commands]
33
- res[:commands].each do |command|
34
- command_result = execute_command(command[:name], command[:arguments])
35
- clnt.post()
36
- end
37
+ if res['commands']
38
+ processor = Servant.command_processor.new(url)
39
+ processor.run_commands(res['commands'])
37
40
  end
38
41
  end
39
42
 
43
+ def process_commands(commands)
44
+ end
45
+
46
+ def send_event(name, details)
47
+ self.http_client.post("#{@url}/servant_event", {
48
+ :event => name, :install_id => Servant.install_id, :details => details.to_json
49
+ })
50
+ end
51
+
52
+
40
53
  private
54
+
41
55
 
42
56
  def compress_string(str)
43
57
  compr = ""
@@ -0,0 +1,109 @@
1
+ module Spider; module Servant
2
+
3
+ class CommandsProcessor
4
+ attr_reader :client
5
+
6
+ def self.plan_file
7
+ File.join(Spider.paths[:var], 'servant_command_plan')
8
+ end
9
+
10
+ def self.progress_file
11
+ File.join(Spider.paths[:var], 'servant_command_progress')
12
+ end
13
+
14
+ def self.save_plan(commands)
15
+ File.open(self.plan_file, 'w'){ |f| f << commands.to_json }
16
+ end
17
+
18
+ def self.read_plan
19
+ return nil unless File.exists?(self.plan_file)
20
+ JSON.parse(File.readfile(self.plan_file))
21
+ end
22
+
23
+ def self.unfinished_plan?
24
+ File.exists?(self.plan_file)
25
+ end
26
+
27
+ def initialize(master_url)
28
+ @url = master_url
29
+ @client = Servant::Client.new(@url)
30
+ @progress = {}
31
+ end
32
+
33
+ def resume_plan
34
+ plan = self.class.read_plan
35
+ progress = JSON.parse(File.read(self.progress_file)) if File.exists?(self.progress_file)
36
+ progress ||= {}
37
+ plan.reject!{ |c| progress[c['id']] }
38
+ process_commands(plan)
39
+ end
40
+
41
+ def save_progress
42
+ File.open(self.class.progress_file, 'w'){ |f| f << @progress.to_json }
43
+ end
44
+
45
+ def run_commands(commands)
46
+ self.class.save_plan(commands)
47
+ process_commands(commands)
48
+ end
49
+
50
+ def process_commands(commands)
51
+ results = []
52
+ error = nil
53
+ commands.each do |command|
54
+ command_result = {:command_id => command['id']}
55
+ if error
56
+ command_result[:previous_error] = true
57
+ else
58
+ begin
59
+ command_result[:res] = execute_command(command)
60
+ rescue => exc
61
+ error = exc.message
62
+ command_result[:error] = error
63
+ end
64
+ end
65
+ results << command_result
66
+ end
67
+ self.client.send_event(:plan_done, {:results => results})
68
+ File.unlink(self.class.plan_file) if File.exists?(self.class.plan_file)
69
+ File.unlink(self.class.progress_file) if File.exists?(self.class.progress_file)
70
+ end
71
+
72
+ def execute_command(command)
73
+ args = command["arguments"]
74
+ res = case command["name"]
75
+ when "gems"
76
+ install_gems(args)
77
+ when "apps"
78
+ install_apps(args)
79
+ when "configure"
80
+
81
+ end
82
+ @progress[command['id']] = true
83
+ save_progress
84
+ self.client.send_event(:command_done, {:id => command['id'], :res => res})
85
+ res
86
+ end
87
+
88
+ def install_gems(gems)
89
+ inst = Gem::DependencyInstaller.new
90
+ installed = []
91
+ gems.each do |g|
92
+ v = g['version'] || Gem::Requirement.default
93
+ unless Gem.available?(g['name'], v)
94
+ inst.install g['name'], v
95
+ installed << g
96
+ end
97
+
98
+ end
99
+ return {:installed => gems}
100
+ end
101
+
102
+ def install_apps(apps)
103
+ require 'spiderfw/setup/app_manager'
104
+ Spider::AppManager.install_or_update(apps)
105
+ end
106
+
107
+ end
108
+
109
+ end; end
@@ -1,9 +1,19 @@
1
1
  require 'uuidtools'
2
+ require 'apps/servant/lib/client'
3
+ require 'apps/servant/lib/commands_processor'
2
4
 
3
5
  module Spider
4
6
 
5
7
  module Servant
8
+
9
+ def self.command_processor
10
+ @command_processor ||= Spider::Servant::CommandsProcessor
11
+ end
6
12
 
13
+ def self.command_processor=(klass)
14
+ @command_processor = klass
15
+ end
16
+
7
17
  def self.install_id
8
18
  uuid_file = File.join(Spider.paths[:var], 'install_id')
9
19
  return File.read(uuid_file) if File.exists?(uuid_file)
@@ -5,7 +5,6 @@ class AppCommand < CmdParse::Command
5
5
  super('app', true, true )
6
6
  @short_desc = _("Manage apps")
7
7
 
8
- @server_url = 'http://www.soluzionipa.it/euroservizi/spider/app_server'
9
8
 
10
9
  self.options = CmdParse::OptionParserWrapper.new do |opt|
11
10
  opt.on("--proxy [SERVER]", _("Proxy server to use (http://user:pass@host:port)"), "-p"){ |p|
@@ -57,6 +56,11 @@ class AppCommand < CmdParse::Command
57
56
  end
58
57
  if @remote
59
58
  require 'spiderfw/setup/app_server_client'
59
+ unless @server_url
60
+ require 'spiderfw/spider'
61
+ Spider.init_base
62
+ @server_url = Spider.config.get('app_server.url')
63
+ end
60
64
  client = Spider::AppServerClient.new(@server_url)
61
65
  remote = {}
62
66
  client.specs.each do |app|
@@ -119,56 +123,26 @@ class AppCommand < CmdParse::Command
119
123
  puts _("Please execute this command from the home folder")
120
124
  exit
121
125
  end
122
- require 'spiderfw/setup/app_server_client'
123
- use_git = false
124
- unless @no_git
125
- begin
126
- require 'grit'
127
- use_git = true
128
- rescue => exc
129
- puts exc.message
130
- puts "Grit not available; install Grit for Git support"
131
- end
132
- end
133
-
134
- apps = args
135
- existent = []
136
- apps.each do |app|
137
- if File.exist?("apps/#{app}")
138
- puts _("%s already exists, skipping") % app
139
- existent << app
140
- end
141
- end
142
126
  require 'spiderfw/setup/app_manager'
143
- specs = []
144
- client = Spider::AppServerClient.new(@server_url)
145
- if @no_deps
146
- specs = client.get_specs(apps)
147
- else
148
- specs = client.get_deps(apps, :no_optional => @no_optional)
149
- end
150
- deps = specs.map{ |s| s.app_id }
151
- unless (deps - apps).empty?
152
- puts _("The following apps will be installed as a dependency:")
153
- puts (deps - apps).inspect
154
- end
155
127
  options = {
156
- :use_git => use_git,
157
- :no_gems => @no_gems,
158
- :no_optional_gems => @no_optional_gems
128
+ :no_git => @no_git, :all => @all, :no_deps => @no_deps, :no_optional => @no_optional,
129
+ :no_gems => @no_gems, :no_optional_gems => @no_optional_gems, :no_activate => @no_activate
159
130
  }
160
- options[:ssh_user] = @ssh_user if @ssh_user
161
- inst_specs = specs.reject!{ |s| existent.include? s.app_id }
162
- Spider::AppManager.install(inst_specs, Dir.pwd, options)
163
- unless @no_activate
164
- require 'spiderfw/spider'
165
- specs_hash = {}
166
- specs.each{ |s| specs_hash[s.app_id] = s }
167
- Spider.activate_apps(deps, specs_hash)
168
- end
131
+ options[:url] = @server_url if @server_url
132
+ Spider::AppManager.install_apps(args, options)
169
133
  end
170
134
  self.add_command(install)
171
135
 
136
+ activate = CmdParse::Command.new('activate', false )
137
+ activate.short_desc = _("Activate an app")
138
+ activate.set_execution_block do |args|
139
+ apps = args
140
+ require 'spiderfw/spider'
141
+ apps = Spider.get_app_deps(apps)
142
+ Spider.activate_apps(apps)
143
+ end
144
+ self.add_command(activate)
145
+
172
146
  update = CmdParse::Command.new( 'update', false )
173
147
  update.short_desc = _("Update an app")
174
148
  update.options = CmdParse::OptionParserWrapper.new do |opt|
@@ -188,44 +162,13 @@ class AppCommand < CmdParse::Command
188
162
  puts _("Please execute this command from the home folder")
189
163
  exit
190
164
  end
191
- require 'spiderfw/setup/app_server_client'
192
- use_git = false
193
- unless @no_git
194
- begin
195
- require 'grit'
196
- use_git = true
197
- rescue
198
- puts "Grit not available; install Grit for Git support"
199
- end
200
- end
201
- apps = args
202
- if @all
203
- require 'spiderfw/home'
204
- home = Spider::Home.new(Dir.pwd)
205
- apps = home.list_apps
206
- end
207
- if apps.empty?
208
- puts _("No app to update")
209
- exit
210
- end
211
165
  require 'spiderfw/setup/app_manager'
212
- specs = []
213
- client = Spider::AppServerClient.new(@server_url)
214
- if @no_deps
215
- specs = client.get_specs(apps)
216
- else
217
- specs = client.get_deps(apps, :no_optional => @no_optional)
218
- end
219
- deps = specs.map{ |s| s.app_id }
220
- unless (deps - apps).empty?
221
- puts _("The following apps will be updated as a dependency:")
222
- puts (deps - apps).inspect
223
- end
224
- Spider::AppManager.update(specs, Dir.pwd, {
225
- :use_git => use_git,
226
- :no_gems => @no_gems,
227
- :no_optional_gems => @no_optional_gems
228
- })
166
+ options = {
167
+ :no_git => @no_git, :all => @all, :no_deps => @no_deps, :no_optional => @no_optional,
168
+ :no_gems => @no_gems, :no_optional_gems => @no_optional_gems
169
+ }
170
+ options[:url] = @server_url if @server_url
171
+ Spider::AppManager.update_apps(args, options)
229
172
  end
230
173
  self.add_command(update)
231
174
 
@@ -33,7 +33,7 @@ module Spider
33
33
  :default => Proc.new{ RUBY_VERSION_PARTS[1] == '8' && !Object.const_defined?(:PhusionPassenger) ? true : false }
34
34
  config_option 'webserver.timeout', _("Time allowed for each request (in seconds)"), :type=> Fixnum, :default => nil
35
35
  config_option 'webserver.respawn_on_change', _("Restart the webserver when application code changes"), :type => Spider::Bool,
36
- :default => Proc.new{ Spider.config.get('runmode') == 'devel' ? true : false }
36
+ :default => Proc.new{ RUBY_PLATFORM !~ /win32|mingw32/ && Spider.config.get('runmode') == 'devel' ? true : false }
37
37
  config_option 'static_content.mode', _("Mode to use for serving static files"), :type => String,
38
38
  :choices => [nil, 'x-sendfile', 'x-accel-redirect', 'published'], :default => nil
39
39
  config_option 'static_content.auto_publish', _("Automatically publish content to the home's public folder"),
@@ -22,6 +22,9 @@ module Spider
22
22
  class ControllerError < RuntimeError
23
23
  end
24
24
 
25
+ class Maintenance < RuntimeError
26
+ end
27
+
25
28
  end
26
29
 
27
30
  end
@@ -40,6 +40,11 @@ module Spider
40
40
 
41
41
  end
42
42
 
43
+ def try_rescue(exc)
44
+ super
45
+ self.done = true
46
+ end
47
+
43
48
 
44
49
  end
45
50
 
@@ -1,7 +1,7 @@
1
1
  module Spider
2
2
 
3
3
  class HomeController < Controller
4
- include StaticContent
4
+ include StaticContent, HTTPMixin
5
5
  route 'spider/public', Spider.controller, :prepend => 'public/'
6
6
  # route 'spider', Spider.controller
7
7
 
@@ -89,9 +89,13 @@ module Spider; module ControllerMixins
89
89
  super
90
90
  end
91
91
 
92
- def base_url()
92
+ def self.base_url
93
93
  HTTPMixin.reverse_proxy_mapping("")
94
94
  end
95
+
96
+ def base_url
97
+ self.class.base_url
98
+ end
95
99
 
96
100
  def prepare_scene(scene)
97
101
  scene = super
@@ -101,7 +105,6 @@ module Spider; module ControllerMixins
101
105
  end
102
106
 
103
107
  def try_rescue(exc)
104
- self.done = true
105
108
  if (exc.is_a?(Spider::Controller::NotFound))
106
109
  @response.status = Spider::HTTP::NOT_FOUND
107
110
  elsif (exc.is_a?(Spider::Controller::BadRequest))
@@ -40,6 +40,9 @@ module Spider; module ControllerMixins
40
40
  output_format_headers(format)
41
41
  @executed_format = format
42
42
  @executed_format_params = format_params
43
+ if Spider.runmode != 'devel' && File.exists?(File.join(Spider.paths[:tmp], 'maintenance.txt'))
44
+ raise Spider::Controller::Maintenance
45
+ end
43
46
  super
44
47
  end
45
48
 
@@ -182,7 +185,7 @@ module Spider; module ControllerMixins
182
185
  def render(path=nil, options={})
183
186
  scene = options[:scene] || @scene
184
187
  scene ||= get_scene
185
- scene = prepare_scene(scene)
188
+ scene = prepare_scene(scene) unless options[:no_prepare_scene]
186
189
  request = options[:request] || @request
187
190
  response = options[:response] || @response
188
191
  if (path.is_a?(Spider::Template))
@@ -215,6 +218,11 @@ module Spider; module ControllerMixins
215
218
  return template
216
219
  end
217
220
 
221
+ def render_error(path, options)
222
+ options[:no_prepare_scene] = true
223
+ render(path, options)
224
+ end
225
+
218
226
  def find_widget(name)
219
227
  @template.find_widget(name)
220
228
  end
@@ -239,19 +247,26 @@ module Spider; module ControllerMixins
239
247
  return obj
240
248
  end
241
249
 
242
- def try_rescue(exc)
250
+ def try_rescue(exc)
243
251
  exc.uuid = UUIDTools::UUID.random_create.to_s if exc.respond_to?(:uuid=)
244
252
  format = self.class.output_format(:error) || :html
245
- return super unless @executed_format == :html
246
- return super unless action_target?
247
- return super if target_mode?
253
+ unless exc.is_a?(Spider::Controller::Maintenance) || exc.is_a?(Spider::Controller::NotFound)
254
+ return super unless @executed_format == :html
255
+ return super unless action_target?
256
+ return super if target_mode?
257
+ end
248
258
  output_format_headers(format)
249
- if (exc.is_a?(Spider::Controller::NotFound))
250
- error_page = '404'
259
+ layout = 'errors/error'
260
+ if exc.is_a?(Spider::Controller::Maintenance)
261
+ error_page = 'maintenance'
262
+ layout = 'generic'
263
+ elsif exc.is_a?(Spider::Controller::NotFound)
264
+ error_page = 'errors/404'
265
+ layout = 'errors/simple'
251
266
  @scene.error_msg = _("Page not found")
252
267
  @scene.email_subject = @scene.error_msg
253
268
  else
254
- error_page = 'error_generic'
269
+ error_page = 'errors/error_generic'
255
270
  if (exc.is_a?(HTTPMixin::HTTPStatus))
256
271
  @scene.error_msg = exc.status_message
257
272
  end
@@ -259,13 +274,13 @@ module Spider; module ControllerMixins
259
274
  @scene.email_subject = @scene.error_msg
260
275
  end
261
276
 
262
- if (exc.respond_to?(:uuid))
277
+ if exc.respond_to?(:uuid)
263
278
  exc.extend(UUIDExceptionMessage)
264
279
  @scene.exception_uuid = exc.uuid
265
- @scene.email_subject += " (#{exc.uuid})"
280
+ @scene.email_subject += " (#{exc.uuid})" if @scene.email_subject
266
281
  end
267
282
  @scene.admin_email = Spider.conf.get('site.tech_admin.email')
268
- if (Spider.runmode == 'devel')
283
+ if Spider.runmode == 'devel'
269
284
  begin
270
285
  @scene.devel = true
271
286
  @scene.backtrace = build_backtrace(exc)
@@ -294,7 +309,7 @@ module Spider; module ControllerMixins
294
309
  rescue => exc2
295
310
  end
296
311
  end
297
- render "errors/#{error_page}", :layout => "errors/error"
312
+ render_error "#{error_page}", :layout => layout
298
313
  super
299
314
  end
300
315
 
@@ -166,7 +166,6 @@ module Spider; module HTTP
166
166
  Process.kill 'KILL', @monitor_thread[:spawner_child_pid]
167
167
  }
168
168
  Spider.on_main_process_shutdown(&exit_spawner)
169
- Spider.main_process_startup
170
169
  $SPIDER_SCRIPT ||= $0
171
170
  $0 = 'spider-spawner'
172
171
  end
@@ -4,6 +4,129 @@ require 'fileutils'
4
4
  module Spider
5
5
 
6
6
  module AppManager
7
+
8
+ def self.install_or_update(apps, options={})
9
+ require 'spiderfw/home'
10
+ home = Spider::Home.new(Dir.pwd)
11
+ installed = {}
12
+ Spider.init_base
13
+ active = Spider.config.get('apps')
14
+ Spider.home.apps.each do |app, info|
15
+ installed[app] = {
16
+ :active => active.include?(app)
17
+ }
18
+ if spec = info[:spec]
19
+ installed[app].merge!({
20
+ :version => spec.version
21
+ })
22
+ end
23
+ end
24
+ to_inst = apps.select{ |a| !installed[a] }
25
+ to_upd = apps.select{ |a| installed[a] }
26
+ install_apps(to_inst, options)
27
+ update_apps(to_upd, options)
28
+ return {:installed => to_inst, :updated => to_upd}
29
+ end
30
+
31
+ def self.install_apps(apps, options={})
32
+ return if apps.empty?
33
+ require 'spiderfw/setup/app_server_client'
34
+ use_git = false
35
+ unless options[:no_git]
36
+ begin
37
+ require 'grit'
38
+ use_git = true
39
+ rescue => exc
40
+ puts exc.message
41
+ puts "Grit not available; install Grit for Git support"
42
+ end
43
+ end
44
+
45
+ existent = []
46
+ apps.each do |app|
47
+ if File.exist?("apps/#{app}")
48
+ puts _("%s already exists, skipping") % app
49
+ existent << app
50
+ end
51
+ end
52
+ require 'spiderfw/setup/app_manager'
53
+ specs = []
54
+ url = options[:url]
55
+ unless url
56
+ require 'spiderfw/spider'
57
+ Spider.init_base
58
+ url = Spider.config.get('app_server.url')
59
+ end
60
+ client = Spider::AppServerClient.new(url)
61
+ if options[:no_deps]
62
+ specs = client.get_specs(apps)
63
+ else
64
+ specs = client.get_deps(apps, :no_optional => options[:no_optional])
65
+ end
66
+ deps = specs.map{ |s| s.app_id }
67
+ unless (deps - apps).empty?
68
+ puts _("The following apps will be installed as a dependency:")
69
+ puts (deps - apps).inspect
70
+ end
71
+ i_options = {
72
+ :use_git => use_git,
73
+ :no_gems => options[:no_gems],
74
+ :no_optional_gems => options[:no_optional_gems]
75
+ }
76
+ i_options[:ssh_user] = options[:ssh_user] if options[:ssh_user]
77
+ inst_specs = specs.reject!{ |s| existent.include? s.app_id }
78
+ Spider::AppManager.install(inst_specs, Dir.pwd, i_options)
79
+ unless options[:no_activate]
80
+ require 'spiderfw/spider'
81
+ specs_hash = {}
82
+ specs.each{ |s| specs_hash[s.app_id] = s }
83
+ Spider.activate_apps(deps, specs_hash)
84
+ end
85
+
86
+ end
87
+
88
+ def self.update_apps(apps, options={})
89
+ require 'spiderfw/spider'
90
+ require 'spiderfw/setup/app_server_client'
91
+ Spider.init_base
92
+ url = options[:url] || Spider.conf.get('app_server.url')
93
+ use_git = false
94
+ unless options[:no_git]
95
+ begin
96
+ require 'grit'
97
+ use_git = true
98
+ rescue
99
+ puts "Grit not available; install Grit for Git support"
100
+ end
101
+ end
102
+ if options[:all]
103
+ require 'spiderfw/home'
104
+ home = Spider::Home.new(Dir.pwd)
105
+ apps = home.list_apps
106
+ end
107
+ if apps.empty?
108
+ puts _("No app to update")
109
+ exit
110
+ end
111
+ require 'spiderfw/setup/app_manager'
112
+ specs = []
113
+ client = Spider::AppServerClient.new(url)
114
+ if options[:no_deps]
115
+ specs = client.get_specs(apps)
116
+ else
117
+ specs = client.get_deps(apps, :no_optional => options[:no_optional])
118
+ end
119
+ deps = specs.map{ |s| s.app_id }
120
+ unless (deps - apps).empty?
121
+ puts _("The following apps will be updated as a dependency:")
122
+ puts (deps - apps).inspect
123
+ end
124
+ Spider::AppManager.update(specs, Dir.pwd, {
125
+ :use_git => use_git,
126
+ :no_gems => options[:no_gems],
127
+ :no_optional_gems => options[:no_optional_gems]
128
+ })
129
+ end
7
130
 
8
131
  def self.install(specs, home_path, options)
9
132
  options[:use_git] = true unless options[:use_git] == false
@@ -77,7 +200,7 @@ module Spider
77
200
  end
78
201
  end
79
202
 
80
- def pre_update
203
+ def self.pre_update(specs, options={})
81
204
  end
82
205
 
83
206
  def self.post_setup(specs, options={})
@@ -89,7 +212,7 @@ module Spider
89
212
  options[:use_git] = true unless options[:use_git] == false
90
213
  specs = [specs] unless specs.is_a?(Array)
91
214
  pre_setup(specs, options)
92
- pre_update(specs, option)
215
+ pre_update(specs, options)
93
216
  specs.each do |spec|
94
217
  if spec.git_repo && options[:use_git]
95
218
  git_update(spec, home_path, options)
@@ -78,6 +78,11 @@ module Spider
78
78
  @home.instance_eval(File.read(init_file), init_file)
79
79
  end
80
80
 
81
+ init_apps
82
+ @init_done=true
83
+ end
84
+
85
+ def init_apps
81
86
  @apps.each do |name, mod|
82
87
  mod.app_init if mod.respond_to?(:app_init)
83
88
  end
@@ -87,7 +92,6 @@ module Spider
87
92
  GetText.bindtextdomain(mod.short_name)
88
93
  end
89
94
  end
90
- @init_done=true
91
95
  end
92
96
 
93
97
  def init_done?
@@ -175,9 +179,9 @@ module Spider
175
179
  @fssm_thread = Thread.new do
176
180
  monitor.run
177
181
  end
178
- Spider.logger.debug("Monitoring restart.txt")
182
+ Spider.logger.debug("Monitoring restart.txt") if Spider.logger
179
183
  else
180
- Spider.logger.debug("FSSM not installed, unable to monitor restart.txt")
184
+ Spider.logger.debug("FSSM not installed, unable to monitor restart.txt") if Spider.logger
181
185
  end
182
186
  trap('TERM'){ Spider.main_process_shutdown; exit }
183
187
  trap('INT'){ Spider.main_process_shutdown; exit }
@@ -314,6 +318,7 @@ module Spider
314
318
  @paths[:tmp] = File.join(root, 'tmp')
315
319
  @paths[:data] = File.join(root, 'data')
316
320
  @paths[:log] = File.join(@paths[:var], 'log')
321
+ @paths[:restart_file] = File.join(@paths[:tmp], 'restart.txt')
317
322
  @paths.each do |k, path|
318
323
  @paths[k] = File.expand_path(File.readlink(path)) if File.symlink?(path)
319
324
  end
@@ -422,6 +427,20 @@ module Spider
422
427
  return false
423
428
  end
424
429
 
430
+ def get_app_deps(apps, options={})
431
+ new_apps = apps.clone
432
+ specs = {}
433
+ init_base
434
+ while !new_apps.empty? && curr = new_apps.pop
435
+ raise "Could not find app #{curr}" unless Spider.home.apps[curr]
436
+ spec = Spider.home.apps[curr][:spec]
437
+ specs[curr] = spec
438
+ new_apps += spec.depends.reject{ |app| specs[app] }
439
+ new_apps += spec.depends_optional.reject{ |app| specs[app] } if options[:optional]
440
+ end
441
+ specs.keys
442
+ end
443
+
425
444
  def activate_apps(apps, specs=nil)
426
445
  require 'spiderfw/config/configuration_editor'
427
446
  init_base
@@ -448,7 +467,7 @@ module Spider
448
467
  apps.each do |a|
449
468
  sort.add(specs[a] ? specs[a] : a)
450
469
  end
451
- sort.tsort
470
+ sort.tsort.reject{ |a| a.nil? }
452
471
  end
453
472
 
454
473
  def load_configuration(path)
@@ -3,4 +3,7 @@
3
3
  <div class="error_description">
4
4
  _(We are sorry, but the required page was not found).
5
5
  </div>
6
+ <div class="link_back">
7
+ <a href="{ Spider.site }/{ Spider::ControllerMixins::HTTPMixin.base_url }">_(Return to the site)</a>
8
+ </div>
6
9
  </div>
@@ -0,0 +1,16 @@
1
+ <!DOCTYPE HTML>
2
+ <html>
3
+ <tpl:asset type="css" src="css/error_page.css" />
4
+ <head>
5
+ <title>{ @error_msg }</title>
6
+ <script sp:each='@assets[:js] |script|' type="text/javascript" src="{ script }"></script>
7
+ <link sp:each='@assets[:css] |css_file|' rel='stylesheet' href='{ css_file }' />
8
+ </head>
9
+ <body>
10
+ <div id="header">
11
+ </div>
12
+ <div id="content">
13
+ <sp:yield />
14
+ </div>
15
+ </div>
16
+ </div>
@@ -0,0 +1,16 @@
1
+ <!DOCTYPE HTML>
2
+ <html>
3
+ <tpl:asset type="css" src="css/error_page.css" />
4
+ <head>
5
+ <title>{ @error_msg }</title>
6
+ <script sp:each='@assets[:js] |script|' type="text/javascript" src="{ script }"></script>
7
+ <link sp:each='@assets[:css] |css_file|' rel='stylesheet' href='{ css_file }' />
8
+ </head>
9
+ <body>
10
+ <div id="header">
11
+ </div>
12
+ <div id="content">
13
+ <sp:yield />
14
+ </div>
15
+ </div>
16
+ </div>
@@ -0,0 +1,6 @@
1
+ <div>
2
+ <h3 class="error_message">_(Under maintenance)</h3>
3
+ <div class="error_description">
4
+ _(The server is currently under maintenance. Please come back shortly).
5
+ </div>
6
+ </div>
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: spiderfw
3
3
  version: !ruby/object:Gem::Version
4
- hash: 11
4
+ hash: 9
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 6
9
- - 6
10
- version: 0.6.6
9
+ - 7
10
+ version: 0.6.7
11
11
  platform: ruby
12
12
  authors:
13
13
  - Ivan Pirlik
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-07-19 00:00:00 +02:00
18
+ date: 2011-07-26 00:00:00 +02:00
19
19
  default_executable: spider
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -850,6 +850,7 @@ files:
850
850
  - apps/master/models/admin.rb
851
851
  - apps/master/models/command.rb
852
852
  - apps/master/models/customer.rb
853
+ - apps/master/models/event.rb
853
854
  - apps/master/models/installation.rb
854
855
  - apps/master/models/remote_log.rb
855
856
  - apps/master/models/resource.rb
@@ -935,6 +936,7 @@ files:
935
936
  - apps/servant/controllers/servant_controller.rb
936
937
  - apps/servant/Gemfile
937
938
  - apps/servant/lib/client.rb
939
+ - apps/servant/lib/commands_processor.rb
938
940
  - apps/servant/servant.appspec
939
941
  - apps/servant/servant.rb
940
942
  - apps/soap/_init.rb
@@ -1211,6 +1213,9 @@ files:
1211
1213
  - views/errors/404.shtml
1212
1214
  - views/errors/error.layout.shtml
1213
1215
  - views/errors/error_generic.shtml
1216
+ - views/errors/simple.layout.shtml
1217
+ - views/generic.layout.shtml
1218
+ - views/maintenance.shtml
1214
1219
  has_rdoc: true
1215
1220
  homepage: http://github.com/me/spider
1216
1221
  licenses: []