sfpagent 0.1.6 → 0.1.9
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.
Potentially problematic release.
This version of sfpagent might be problematic. Click here for more details.
- data/README.md +9 -9
- data/VERSION +1 -1
- data/bin/sfpagent +5 -3
- data/lib/sfpagent/agent.rb +252 -153
- data/lib/sfpagent/bsig.rb +301 -12
- data/lib/sfpagent/module.rb +7 -3
- data/lib/sfpagent/runtime.rb +113 -89
- data/lib/sfpagent/sfplanner.rb +85 -0
- data/lib/sfpagent.rb +1 -0
- data/sfpagent.gemspec +1 -1
- metadata +5 -4
data/lib/sfpagent/agent.rb
CHANGED
@@ -7,45 +7,42 @@ require 'uri'
|
|
7
7
|
require 'net/http'
|
8
8
|
require 'logger'
|
9
9
|
require 'json'
|
10
|
+
require 'digest/md5'
|
10
11
|
|
11
12
|
module Sfp
|
12
13
|
module Agent
|
13
14
|
NetHelper = Object.new.extend(Nuri::Net::Helper)
|
14
15
|
|
15
|
-
|
16
|
-
CachedDir = '/var/sfpagent'
|
17
|
-
else
|
18
|
-
CachedDir = File.expand_path('~/.sfpagent')
|
19
|
-
end
|
16
|
+
CachedDir = (Process.euid == 0 ? '/var/sfpagent' : File.expand_path('~/.sfpagent'))
|
20
17
|
Dir.mkdir(CachedDir, 0700) if not File.exist?(CachedDir)
|
21
18
|
|
22
19
|
DefaultPort = 1314
|
20
|
+
|
23
21
|
PIDFile = "#{CachedDir}/sfpagent.pid"
|
24
22
|
LogFile = "#{CachedDir}/sfpagent.log"
|
25
23
|
ModelFile = "#{CachedDir}/sfpagent.model"
|
26
24
|
AgentsDataFile = "#{CachedDir}/sfpagent.agents"
|
27
25
|
|
26
|
+
BSigFile = "#{CachedDir}/bsig.model"
|
27
|
+
BSigPIDFile = "#{CachedDir}/bsig.pid"
|
28
|
+
|
28
29
|
@@logger = WEBrick::Log.new(LogFile, WEBrick::BasicLog::INFO ||
|
29
30
|
WEBrick::BasicLog::ERROR ||
|
30
31
|
WEBrick::BasicLog::FATAL ||
|
31
32
|
WEBrick::BasicLog::WARN)
|
32
33
|
|
33
|
-
@@
|
34
|
+
@@current_model_hash = nil
|
35
|
+
|
36
|
+
@@bsig = nil
|
37
|
+
@@bsig_modified_time = nil
|
38
|
+
@@bsig_engine = Sfp::BSig.new # create BSig engine instance
|
39
|
+
|
34
40
|
@@runtime_lock = Mutex.new
|
35
41
|
|
36
42
|
def self.logger
|
37
43
|
@@logger
|
38
44
|
end
|
39
45
|
|
40
|
-
def self.check_config(p={})
|
41
|
-
# check modules directory, and create it if it's not exist
|
42
|
-
p[:modules_dir] = "#{CachedDir}/modules" if p[:modules_dir].to_s.strip == ''
|
43
|
-
p[:modules_dir] = File.expand_path(p[:modules_dir].to_s)
|
44
|
-
p[:modules_dir].chop! if p[:modules_dir][-1,1] == '/'
|
45
|
-
Dir.mkdir(p[:modules_dir], 0700) if not File.exists?(p[:modules_dir])
|
46
|
-
p
|
47
|
-
end
|
48
|
-
|
49
46
|
# Start the agent.
|
50
47
|
#
|
51
48
|
# options:
|
@@ -56,14 +53,29 @@ module Sfp
|
|
56
53
|
# :keyfile
|
57
54
|
#
|
58
55
|
def self.start(p={})
|
56
|
+
Process.daemon
|
57
|
+
|
59
58
|
begin
|
60
|
-
|
61
|
-
|
59
|
+
# check modules directory, and create it if it's not exist
|
60
|
+
p[:modules_dir] = File.expand_path(p[:modules_dir].to_s.strip != '' ? p[:modules_dir].to_s : "#{CachedDir}/modules")
|
61
|
+
Dir.mkdir(p[:modules_dir], 0700) if not File.exist?(p[:modules_dir])
|
62
|
+
@@config = p
|
63
|
+
Sfp::Agent.logger.info "modules dir: " + p[:modules_dir]
|
64
|
+
|
65
|
+
# load modules from cached directory
|
66
|
+
load_modules(p)
|
67
|
+
|
68
|
+
# reload model
|
69
|
+
build_model({:complete => true})
|
70
|
+
|
71
|
+
# create web server
|
62
72
|
server_type = (p[:daemon] ? WEBrick::Daemon : WEBrick::SimpleServer)
|
63
73
|
port = (p[:port] ? p[:port] : DefaultPort)
|
64
|
-
|
65
|
-
|
66
|
-
|
74
|
+
config = { :Host => '0.0.0.0',
|
75
|
+
:Port => port,
|
76
|
+
:ServerType => server_type,
|
77
|
+
:pid => '/tmp/webrick.pid',
|
78
|
+
:Logger => Sfp::Agent.logger }
|
67
79
|
if p[:ssl]
|
68
80
|
config[:SSLEnable] = true
|
69
81
|
config[:SSLVerifyClient] = OpenSSL::SSL::VERIFY_NONE
|
@@ -71,36 +83,44 @@ module Sfp
|
|
71
83
|
config[:SSLPrivateKey] = OpenSSL::PKey::RSA.new(File.open(p[:keyfile]).read)
|
72
84
|
config[:SSLCertName] = [["CN", WEBrick::Utils::getservername]]
|
73
85
|
end
|
74
|
-
|
75
|
-
load_modules(p)
|
76
|
-
reload_model
|
77
|
-
|
78
86
|
server = WEBrick::HTTPServer.new(config)
|
79
|
-
server.mount("/", Sfp::Agent::Handler,
|
87
|
+
server.mount("/", Sfp::Agent::Handler, Sfp::Agent.logger)
|
88
|
+
|
89
|
+
# trap signal
|
90
|
+
['INT', 'KILL', 'HUP'].each { |signal|
|
91
|
+
trap(signal) {
|
92
|
+
Sfp::Agent.logger.info "Shutting down web server"
|
93
|
+
server.shutdown
|
94
|
+
}
|
95
|
+
}
|
80
96
|
|
97
|
+
# send request to local web server to save its PID
|
81
98
|
fork {
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
99
|
+
sleep 0.5
|
100
|
+
1.upto(5) do |i|
|
101
|
+
begin
|
102
|
+
NetHelper.get_data('127.0.0.1', config[:Port], '/pid')
|
103
|
+
break if File.exist?(PIDFile)
|
104
|
+
rescue
|
105
|
+
sleep (i*i)
|
90
106
|
end
|
91
|
-
req = Net::HTTP::Get.new(url.path)
|
92
|
-
http.request(req)
|
93
|
-
puts "\nSFP Agent is running with PID #{File.read(PIDFile)}" if File.exist?(PIDFile)
|
94
|
-
rescue Exception => e
|
95
|
-
Sfp::Agent.logger.warn "Cannot request /pid #{e}"
|
96
107
|
end
|
108
|
+
puts "SFP Agent is running with PID #{File.read(PIDFile)}" if File.exist?(PIDFile)
|
97
109
|
}
|
98
110
|
|
99
|
-
|
111
|
+
# start BSig's main thread in a separate process
|
112
|
+
fork {
|
113
|
+
bsig_engine.enable({:mode => :main})
|
114
|
+
}
|
115
|
+
|
116
|
+
# enable BSig's satisfier
|
117
|
+
bsig_engine.enable({:mode => :satisfier})
|
100
118
|
|
119
|
+
# start web server
|
101
120
|
server.start
|
121
|
+
|
102
122
|
rescue Exception => e
|
103
|
-
|
123
|
+
Sfp::Agent.logger.error "Starting the agent [Failed] #{e}\n#{e.backtrace.join("\n")}"
|
104
124
|
raise e
|
105
125
|
end
|
106
126
|
end
|
@@ -108,25 +128,36 @@ module Sfp
|
|
108
128
|
# Stop the agent's daemon.
|
109
129
|
#
|
110
130
|
def self.stop
|
131
|
+
# stopping web server (main thread)
|
111
132
|
pid = (File.exist?(PIDFile) ? File.read(PIDFile).to_i : nil)
|
112
133
|
if not pid.nil? and `ps h #{pid}`.strip =~ /.*sfpagent.*/
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
@@logger.info "SFP Agent daemon has been stopped."
|
134
|
+
Process.kill('HUP', pid)
|
135
|
+
puts "Stopping SFP Agent with PID #{pid}"
|
136
|
+
File.delete(PIDFile) if File.exist?(PIDFile)
|
117
137
|
else
|
118
138
|
puts "SFP Agent is not running."
|
119
139
|
end
|
120
|
-
|
140
|
+
|
141
|
+
# stopping BSig engine
|
142
|
+
pid_bsig = (File.exist?(BSigPIDFile) ? File.read(BSigPIDFile).to_i : nil)
|
143
|
+
if not pid_bsig.nil? and `ps h #{pid_bsig}`.strip =~ /.*sfpagent.*/
|
144
|
+
Process.kill('HUP', pid_bsig)
|
145
|
+
puts "Stopping BSig engine with PID #{pid_bsig}"
|
146
|
+
File.delete(BSigPIDFile) if File.exist?(BSigPIDFile)
|
147
|
+
else
|
148
|
+
puts "BSig engine is not running."
|
149
|
+
end
|
150
|
+
|
151
|
+
Sfp::Agent.logger.info "SFP Agent daemon has been stopped."
|
121
152
|
end
|
122
153
|
|
123
154
|
# Print the status of the agent.
|
124
155
|
#
|
125
156
|
def self.status
|
126
|
-
|
127
|
-
if pid.nil?
|
157
|
+
if not File.exist?(PIDFile)
|
128
158
|
puts "SFP Agent is not running."
|
129
159
|
else
|
160
|
+
pid = File.read(PIDFile).to_i
|
130
161
|
if `ps hf #{pid}`.strip =~ /.*sfpagent.*/
|
131
162
|
puts "SFP Agent is running with PID #{pid}"
|
132
163
|
else
|
@@ -134,56 +165,118 @@ module Sfp
|
|
134
165
|
puts "SFP Agent is not running."
|
135
166
|
end
|
136
167
|
end
|
168
|
+
|
169
|
+
if not File.exist?(BSigPIDFile)
|
170
|
+
puts "BSig engine is not running."
|
171
|
+
else
|
172
|
+
pid = File.read(BSigPIDFile).to_i
|
173
|
+
if `ps hf #{pid}`.strip =~ /.*sfpagent.*/
|
174
|
+
puts "BSig engine is running with PID #{pid}"
|
175
|
+
else
|
176
|
+
File.delete(BSigPIDFile)
|
177
|
+
puts "BSig engine is not running."
|
178
|
+
end
|
179
|
+
end
|
137
180
|
end
|
138
181
|
|
139
182
|
# Save given model to cached file, and then reload the model.
|
140
183
|
#
|
141
184
|
def self.set_model(model)
|
142
185
|
begin
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
186
|
+
# generate MD5 hash for the new model
|
187
|
+
data = JSON.generate(model)
|
188
|
+
new_model_hash = Digest::MD5.hexdigest(data)
|
189
|
+
|
190
|
+
# save the new model if it's not same with the existing one
|
191
|
+
if Digest::MD5.hexdigest(data) != @@current_model_hash
|
192
|
+
Sfp::Agent.logger.info "Setting new model [Wait]"
|
193
|
+
File.open(ModelFile, File::RDWR|File::CREAT, 0600) { |f|
|
194
|
+
f.flock(File::LOCK_EX)
|
195
|
+
f.rewind
|
196
|
+
f.write(data)
|
147
197
|
f.flush
|
198
|
+
f.truncate(f.pos)
|
148
199
|
}
|
149
|
-
|
150
|
-
|
151
|
-
|
200
|
+
build_model
|
201
|
+
Sfp::Agent.logger.info "Setting the model [OK]"
|
202
|
+
else
|
203
|
+
#Sfp::Agent.logger.info "The model is not changed."
|
204
|
+
end
|
152
205
|
return true
|
153
206
|
rescue Exception => e
|
154
|
-
|
207
|
+
Sfp::Agent.logger.error "Setting the model [Failed] #{e}\n#{e.backtrace.join("\n")}"
|
155
208
|
end
|
156
209
|
false
|
157
210
|
end
|
158
211
|
|
159
|
-
#
|
212
|
+
# Reload the model from cached file.
|
213
|
+
#
|
214
|
+
def self.build_model(p={})
|
215
|
+
if not File.exist?(ModelFile)
|
216
|
+
Sfp::Agent.logger.info "There is no model in cache."
|
217
|
+
else
|
218
|
+
begin
|
219
|
+
@@runtime_lock.synchronize {
|
220
|
+
data = File.read(ModelFile)
|
221
|
+
@@current_model_hash = Digest::MD5.hexdigest(data)
|
222
|
+
if !defined?(@@runtime) or @@runtime.nil? or p[:complete]
|
223
|
+
@@runtime = Sfp::Runtime.new(JSON[data])
|
224
|
+
else
|
225
|
+
@@runtime.set_model(JSON[data])
|
226
|
+
end
|
227
|
+
}
|
228
|
+
Sfp::Agent.logger.info "Reloading the model in cache [OK]"
|
229
|
+
rescue Exception => e
|
230
|
+
Sfp::Agent.logger.error "Reloading the model in cache [Failed] #{e}\n#{e.backtrace.join("\n")}"
|
231
|
+
end
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
235
|
+
# Setting a new BSig model: set @@bsig variable, and save in cached file
|
160
236
|
#
|
161
|
-
def self.
|
162
|
-
return nil if not File.exist?(ModelFile)
|
237
|
+
def self.set_bsig(bsig)
|
163
238
|
begin
|
164
|
-
|
165
|
-
|
239
|
+
File.open(BSigFile, File::RDWR|File::CREAT, 0600) { |f|
|
240
|
+
f.flock(File::LOCK_EX)
|
241
|
+
Sfp::Agent.logger.info "Setting the BSig model [Wait]"
|
242
|
+
f.rewind
|
243
|
+
data = (bsig.nil? ? '' : JSON.generate(bsig))
|
244
|
+
f.write(data)
|
245
|
+
f.flush
|
246
|
+
f.truncate(f.pos)
|
166
247
|
}
|
248
|
+
Sfp::Agent.logger.info "Setting the BSig model [OK]"
|
249
|
+
return true
|
167
250
|
rescue Exception => e
|
168
|
-
|
251
|
+
Sfp::Agent.logger.error "Setting the BSig model [Failed] #{e}\n#{e.backtrace.join("\n")}"
|
169
252
|
end
|
170
253
|
false
|
171
254
|
end
|
172
255
|
|
173
|
-
#
|
256
|
+
# Return a BSig model from cached file
|
174
257
|
#
|
175
|
-
def self.
|
176
|
-
|
177
|
-
if
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
258
|
+
def self.get_bsig
|
259
|
+
return nil if not File.exist?(BSigFile)
|
260
|
+
return @@bsig if File.mtime(BSigFile) == @@bsig_modified_time
|
261
|
+
|
262
|
+
begin
|
263
|
+
data = File.read(BSigFile)
|
264
|
+
@@bsig = (data.length > 0 ? JSON[data] : nil)
|
265
|
+
@@bsig_modified_time = File.mtime(BSigFile)
|
266
|
+
return @@bsig
|
267
|
+
rescue Exception => e
|
268
|
+
Sfp::Agent.logger.error "Get the BSig model [Failed] #{e}\n#{e.backtrace.join("\n")}"
|
186
269
|
end
|
270
|
+
false
|
271
|
+
end
|
272
|
+
|
273
|
+
def self.bsig_engine
|
274
|
+
@@bsig_engine
|
275
|
+
end
|
276
|
+
|
277
|
+
def self.whoami?
|
278
|
+
return nil if !defined?(@@runtime) or @@runtime.nil?
|
279
|
+
@@runtime.whoami?
|
187
280
|
end
|
188
281
|
|
189
282
|
# Return the current state of the model.
|
@@ -192,33 +285,31 @@ module Sfp
|
|
192
285
|
@@runtime_lock.synchronize {
|
193
286
|
return nil if !defined?(@@runtime) or @@runtime.nil?
|
194
287
|
begin
|
195
|
-
@@runtime.get_state if @@runtime.modules.nil?
|
196
288
|
return @@runtime.get_state(as_sfp)
|
197
289
|
rescue Exception => e
|
198
|
-
|
290
|
+
Sfp::Agent.logger.error "Get state [Failed] #{e}\n#{e.backtrace.join("\n")}"
|
199
291
|
end
|
200
292
|
}
|
201
293
|
false
|
202
294
|
end
|
203
295
|
|
204
296
|
def self.resolve(path, as_sfp=true)
|
297
|
+
return Sfp::Undefined.new if !defined?(@@runtime) or @@runtime.nil? or @@runtime.root.nil?
|
205
298
|
begin
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
mod
|
214
|
-
|
215
|
-
|
216
|
-
state = mod[:_self].state
|
217
|
-
return state[attribute] if state.has_key?(attribute)
|
218
|
-
end
|
219
|
-
return Sfp::Undefined.new
|
299
|
+
path = path.simplify
|
300
|
+
_, node, _ = path.split('.', 3)
|
301
|
+
if @@runtime.root.has_key?(node)
|
302
|
+
# local resolve
|
303
|
+
parent, attribute = path.pop_ref
|
304
|
+
mod = @@runtime.root.at?(parent)
|
305
|
+
if mod.is_a?(Hash)
|
306
|
+
mod[:_self].update_state
|
307
|
+
state = mod[:_self].state
|
308
|
+
return state[attribute] if state.has_key?(attribute)
|
220
309
|
end
|
221
|
-
|
310
|
+
return Sfp::Undefined.new
|
311
|
+
end
|
312
|
+
|
222
313
|
agents = get_agents
|
223
314
|
if agents[node].is_a?(Hash)
|
224
315
|
# remote resolve
|
@@ -232,7 +323,7 @@ module Sfp
|
|
232
323
|
end
|
233
324
|
end
|
234
325
|
rescue Exception => e
|
235
|
-
|
326
|
+
Sfp::Agent.logger.error "Resolve #{path} [Failed] #{e}\n#{e.backtrace.join("\n")}"
|
236
327
|
end
|
237
328
|
Sfp::Undefined.new
|
238
329
|
end
|
@@ -242,15 +333,14 @@ module Sfp
|
|
242
333
|
# @param action contains the action's schema.
|
243
334
|
#
|
244
335
|
def self.execute_action(action)
|
245
|
-
logger = (@@config[:daemon] ?
|
336
|
+
logger = (@@config[:daemon] ? Sfp::Agent.logger : Logger.new(STDOUT))
|
246
337
|
action_string = "#{action['name']} #{JSON.generate(action['parameters'])}"
|
247
338
|
begin
|
248
339
|
result = @@runtime.execute_action(action)
|
249
340
|
logger.info "Executing #{action_string} " + (result ? "[OK]" : "[Failed]")
|
250
341
|
return result
|
251
342
|
rescue Exception => e
|
252
|
-
logger.
|
253
|
-
logger.error "#{e}\n#{e.bracktrace.join("\n")}"
|
343
|
+
logger.error "Executing #{action_string} [Failed] #{e}\n#{e.backtrace.join("\n")}"
|
254
344
|
end
|
255
345
|
false
|
256
346
|
end
|
@@ -266,22 +356,22 @@ module Sfp
|
|
266
356
|
@@modules = []
|
267
357
|
counter = 0
|
268
358
|
if dir != '' and File.exist?(dir)
|
269
|
-
|
359
|
+
Sfp::Agent.logger.info "Modules directory: #{dir}"
|
270
360
|
Dir.entries(dir).each { |name|
|
271
361
|
next if name == '.' or name == '..' or File.file?("#{dir}/#{name}")
|
272
362
|
module_file = "#{dir}/#{name}/#{name}.rb"
|
273
363
|
next if not File.exist?(module_file)
|
274
364
|
begin
|
275
365
|
load module_file #require module_file
|
276
|
-
|
366
|
+
Sfp::Agent.logger.info "Loading module #{dir}/#{name} [OK]"
|
277
367
|
counter += 1
|
278
368
|
@@modules << name
|
279
369
|
rescue Exception => e
|
280
|
-
|
370
|
+
Sfp::Agent.logger.warn "Loading module #{dir}/#{name} [Failed]\n#{e}"
|
281
371
|
end
|
282
372
|
}
|
283
373
|
end
|
284
|
-
|
374
|
+
Sfp::Agent.logger.info "Successfully loading #{counter} modules."
|
285
375
|
end
|
286
376
|
|
287
377
|
def self.get_schemata(module_name)
|
@@ -312,17 +402,16 @@ module Sfp
|
|
312
402
|
data = {}
|
313
403
|
@@modules.each { |m| data[m] = get_module_hash(m) }
|
314
404
|
data
|
315
|
-
#(defined?(@@modules) and @@modules.is_a?(Array) ? @@modules : [])
|
316
405
|
end
|
317
406
|
|
318
407
|
def self.uninstall_all_modules(p={})
|
319
408
|
return true if @@config[:modules_dir] == ''
|
320
409
|
if system("rm -rf #{@@config[:modules_dir]}/*")
|
321
410
|
load_modules(@@config)
|
322
|
-
|
411
|
+
Sfp::Agent.logger.info "Deleting all modules [OK]"
|
323
412
|
return true
|
324
413
|
end
|
325
|
-
|
414
|
+
Sfp::Agent.logger.info "Deleting all modules [Failed]"
|
326
415
|
false
|
327
416
|
end
|
328
417
|
|
@@ -336,7 +425,7 @@ module Sfp
|
|
336
425
|
result = true
|
337
426
|
end
|
338
427
|
load_modules(@@config)
|
339
|
-
|
428
|
+
Sfp::Agent.logger.info "Deleting module #{name} " + (result ? "[OK]" : "[Failed]")
|
340
429
|
result
|
341
430
|
end
|
342
431
|
|
@@ -366,7 +455,11 @@ module Sfp
|
|
366
455
|
system("cd #{module_dir}; rm data.tgz")
|
367
456
|
}
|
368
457
|
load_modules(@@config)
|
369
|
-
|
458
|
+
|
459
|
+
# rebuild the model
|
460
|
+
build_model({:complete => true})
|
461
|
+
|
462
|
+
Sfp::Agent.logger.info "Installing module #{name} [OK]"
|
370
463
|
|
371
464
|
true
|
372
465
|
end
|
@@ -399,9 +492,12 @@ module Sfp
|
|
399
492
|
true
|
400
493
|
end
|
401
494
|
|
495
|
+
@@agents_data = nil
|
496
|
+
@@agents_data_modified_time = nil
|
402
497
|
def self.get_agents
|
403
498
|
return {} if not File.exist?(AgentsDataFile)
|
404
|
-
|
499
|
+
return @@agents_data if File.mtime(AgentsDataFile) == @@agents_data_modified_time
|
500
|
+
@@agents_data = JSON[File.read(AgentsDataFile)]
|
405
501
|
end
|
406
502
|
|
407
503
|
# A class that handles each request.
|
@@ -445,6 +541,9 @@ module Sfp
|
|
445
541
|
elsif path == '/model'
|
446
542
|
status, content_type, body = get_model
|
447
543
|
|
544
|
+
elsif path == '/bsig'
|
545
|
+
status, content_Type, body = get_bsig
|
546
|
+
|
448
547
|
elsif path =~ /^\/schemata\/.+/
|
449
548
|
status, content_type, body = get_schemata({:module => path[10, path.length-10]})
|
450
549
|
|
@@ -469,8 +568,6 @@ module Sfp
|
|
469
568
|
#
|
470
569
|
# uri:
|
471
570
|
# /execute => receive an action's schema and execute it
|
472
|
-
# /migrate => SFP object migration
|
473
|
-
# /duplicate => SFP object duplication
|
474
571
|
#
|
475
572
|
def do_POST(request, response)
|
476
573
|
status = 400
|
@@ -481,14 +578,6 @@ module Sfp
|
|
481
578
|
path = (request.path[-1,1] == '/' ? ryyequest.path.chop : request.path)
|
482
579
|
if path == '/execute'
|
483
580
|
status, content_type, body = self.execute({:query => request.query})
|
484
|
-
|
485
|
-
elsif path =~ /\/migrate\/.+/
|
486
|
-
status, content_type, body = self.migrate({:src => path[8, path.length-8],
|
487
|
-
:dest => request.query['destination']})
|
488
|
-
|
489
|
-
elsif path =~ /\/duplicate\/.+/
|
490
|
-
# TODO
|
491
|
-
|
492
581
|
end
|
493
582
|
end
|
494
583
|
|
@@ -524,6 +613,12 @@ module Sfp
|
|
524
613
|
elsif path == '/agents'
|
525
614
|
status, content_type, body = self.manage_agents({:query => request.query})
|
526
615
|
|
616
|
+
elsif path == '/bsig'
|
617
|
+
status, content_type, body = self.set_bsig({:query => request.query})
|
618
|
+
|
619
|
+
elsif path == '/bsig/satisfier'
|
620
|
+
status, content_type, body = self.satisfy_bsig_request({:query => request.query})
|
621
|
+
|
527
622
|
end
|
528
623
|
end
|
529
624
|
|
@@ -532,35 +627,6 @@ module Sfp
|
|
532
627
|
response.body = body
|
533
628
|
end
|
534
629
|
|
535
|
-
def migrate(p={})
|
536
|
-
# migrate: source path, destination path
|
537
|
-
#@logger.info "migrate #{p[:src]} => #{p[:dest]}"
|
538
|
-
return [400, 'plain/text', 'Destination path should begin with "/"'] if p[:dest].to_s[0,1] != '/'
|
539
|
-
begin
|
540
|
-
# reformat the source and destination paths to SFP reference
|
541
|
-
p[:src] = '$' + p[:src].gsub(/\//, '.')
|
542
|
-
p[:dest] = '$' + p[:dest].gsub(/\//, '.')
|
543
|
-
|
544
|
-
# find the target in agents' database
|
545
|
-
agents = Sfp::Agent.get_agents
|
546
|
-
data = agents.at?(p[:dest])
|
547
|
-
return [404, 'plain/text', 'Unrecognized destination!'] if !data.is_a?(Hash)
|
548
|
-
|
549
|
-
# send the sub-model to destination
|
550
|
-
model = Sfp::Agent.get_model
|
551
|
-
return [404, '', ''] if model.nil?
|
552
|
-
submodel = model.at?(p[:src])
|
553
|
-
|
554
|
-
# TODO
|
555
|
-
# 1. send the configuration to destination
|
556
|
-
|
557
|
-
return [200, 'plain/text', "#{p[:src]} #{p[:dest]}:#{data.inspect}"]
|
558
|
-
rescue Exception => e
|
559
|
-
@logger.error "Migration failed #{e}\n#{e.backtrace.join("\n")}"
|
560
|
-
end
|
561
|
-
return [500, 'plain/text', e.to_s]
|
562
|
-
end
|
563
|
-
|
564
630
|
def manage_agents(p={})
|
565
631
|
begin
|
566
632
|
if p[:query].has_key?('agents')
|
@@ -614,11 +680,11 @@ module Sfp
|
|
614
680
|
end
|
615
681
|
|
616
682
|
def set_model(p={})
|
617
|
-
if p[:query].has_key?('model')
|
618
|
-
#
|
683
|
+
if p[:query] and p[:query].has_key?('model')
|
684
|
+
# If setting the model was success, then return '200' status.
|
619
685
|
return [200, '', ''] if Sfp::Agent.set_model(JSON[p[:query]['model']])
|
620
686
|
else
|
621
|
-
#
|
687
|
+
# Removing the existing model by setting an empty model, if it's success then return '200' status.
|
622
688
|
return [200, '', ''] if Sfp::Agent.set_model({})
|
623
689
|
end
|
624
690
|
|
@@ -632,7 +698,7 @@ module Sfp
|
|
632
698
|
# The model is not exist.
|
633
699
|
return [404, '', ''] if model.nil?
|
634
700
|
|
635
|
-
# The model is exist, and then send
|
701
|
+
# The model is exist, and then send it in JSON.
|
636
702
|
return [200, 'application/json', JSON.generate(model)] if !!model
|
637
703
|
|
638
704
|
# There is an error when retrieving the model!
|
@@ -657,15 +723,48 @@ module Sfp
|
|
657
723
|
[500, '', '']
|
658
724
|
end
|
659
725
|
|
726
|
+
def set_bsig(p={})
|
727
|
+
if p[:query] and p[:query].has_key?('bsig')
|
728
|
+
# If setting the BSig model was success, then return '200' status
|
729
|
+
return [200, '', ''] if Sfp::Agent.set_bsig(JSON[p[:query]['bsig']])
|
730
|
+
else
|
731
|
+
# Deleting the existing BSig model by setting with Nil, if it's success then return '200' status.
|
732
|
+
return [200, '', ''] if Sfp::Agent.set_bsig(nil)
|
733
|
+
end
|
734
|
+
|
735
|
+
# There is an error on setting/deleting the BSig model
|
736
|
+
[500, '', '']
|
737
|
+
end
|
738
|
+
|
739
|
+
def get_bsig(p={})
|
740
|
+
bsig = Sfp::Agent.get_bsig
|
741
|
+
|
742
|
+
# The BSig model is not exist
|
743
|
+
return [404, '', ''] if bsig.nil?
|
744
|
+
|
745
|
+
# The BSig model is exist, and then send it in JSON
|
746
|
+
return [200, 'application/json', JSON.generate(bsig)] if !!bsig
|
747
|
+
|
748
|
+
[500, '', '']
|
749
|
+
end
|
750
|
+
|
751
|
+
def satisfy_bsig_request(p={})
|
752
|
+
return [400, '', ''] if not p[:query]
|
753
|
+
|
754
|
+
Sfp::Agent.logger.info Sfp::Agent.bsig_engine.to_s
|
755
|
+
|
756
|
+
return [500, '', ''] if Sfp::Agent.bsig_engine.nil?
|
757
|
+
|
758
|
+
req = p[:query]
|
759
|
+
return [200, '', ''] if Sfp::Agent.bsig_engine.receive_goal_from_agent(req['id'].to_i, JSON[req['goal']], req['pi'].to_i)
|
760
|
+
|
761
|
+
[500, '', '']
|
762
|
+
end
|
763
|
+
|
660
764
|
def trusted(address)
|
661
765
|
true
|
662
766
|
end
|
663
|
-
end
|
664
|
-
end
|
665
767
|
|
666
|
-
|
667
|
-
::Kernel.require gem
|
668
|
-
rescue LoadError => e
|
669
|
-
::Kernel.require gem if system("gem install #{pack||gem} --no-ri --no-rdoc")
|
768
|
+
end
|
670
769
|
end
|
671
770
|
end
|