sfpagent 0.1.14 → 0.2.3

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of sfpagent might be problematic. Click here for more details.

data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.14
1
+ 0.2.3
@@ -11,7 +11,7 @@ require 'digest/md5'
11
11
 
12
12
  module Sfp
13
13
  module Agent
14
- NetHelper = Object.new.extend(Sfp::Net::Helper)
14
+ NetHelper = Object.new.extend(Sfp::Helper::Net)
15
15
 
16
16
  CacheDir = (Process.euid == 0 ? '/var/sfpagent' : File.expand_path('~/.sfpagent'))
17
17
  Dir.mkdir(CacheDir, 0700) if not File.exist?(CacheDir)
@@ -42,7 +42,7 @@ module Sfp
42
42
 
43
43
  @@runtime_lock = Mutex.new
44
44
 
45
- @@agents_database = nil
45
+ @@agents_database = {}
46
46
  @@agents_database_modified_time = nil
47
47
 
48
48
  def self.logger
@@ -53,6 +53,10 @@ module Sfp
53
53
  @@config
54
54
  end
55
55
 
56
+ def self.runtime
57
+ @@runtime
58
+ end
59
+
56
60
  # Start the agent.
57
61
  #
58
62
  # options:
@@ -511,6 +515,16 @@ module Sfp
511
515
  end
512
516
  end
513
517
 
518
+ def self.delete_agents
519
+ File.open(AgentsDataFile, File::RDWR|File::CREAT, 0644) { |f|
520
+ f.flock(File::LOCK_EX)
521
+ f.rewind
522
+ f.write('{}')
523
+ f.flush
524
+ f.truncate(f.pos)
525
+ }
526
+ end
527
+
514
528
  # parameter:
515
529
  # :data => To delete an agent: { "agent_name" => nil }
516
530
  # To add/modify an agent: { "agent_name" => { "sfpAddress" => "10.0.0.1", "sfpPort" => 1314 } }
@@ -528,6 +542,7 @@ module Sfp
528
542
  json = f.read
529
543
  agents = (json == '' ? {} : JSON[json])
530
544
  current_hash = agents.hash
545
+
531
546
  data.each { |k,v|
532
547
  if !agents.has_key?(k) or v.nil? or agents[k].hash != v.hash
533
548
  agents[k] = v
@@ -544,16 +559,18 @@ module Sfp
544
559
  end
545
560
  }
546
561
 
547
- if updated # if updated then broadcast to other agents
548
- http_data = {'agents' => JSON.generate(data)}
549
-
550
- agents.each { |name,agent|
551
- begin
552
- code, _ = NetHelper.put_data(agent['sfpAddress'], agent['sfpPort'], '/agents', http_data, 5, 20)
553
- raise Exception if code != '200'
554
- rescue Exception => e
555
- Sfp::Agent.logger.warn "Push agents list to #{agent['sfpAddress']}:#{agent['sfpPort']} [Failed]"
556
- end
562
+ if updated
563
+ Thread.new {
564
+ # if updated then broadcast to other agents
565
+ http_data = {'agents' => JSON.generate(data)}
566
+ agents.each { |name,agent|
567
+ begin
568
+ code, _ = NetHelper.put_data(agent['sfpAddress'], agent['sfpPort'], '/agents', http_data, 5, 20)
569
+ raise Exception if code != '200'
570
+ rescue Exception => e
571
+ Sfp::Agent.logger.warn "Push agents list to #{agent['sfpAddress']}:#{agent['sfpPort']} [Failed]"
572
+ end
573
+ }
557
574
  }
558
575
  end
559
576
 
@@ -563,6 +580,7 @@ module Sfp
563
580
  def self.get_agents
564
581
  return {} if not File.exist?(AgentsDataFile)
565
582
  return @@agents_database if File.mtime(AgentsDataFile) == @@agents_database_modified_time
583
+ @@agents_database_modified_time = File.mtime(AgentsDataFile)
566
584
  @@agents_database = JSON[File.read(AgentsDataFile)]
567
585
  end
568
586
 
@@ -677,21 +695,25 @@ module Sfp
677
695
  path = (request.path[-1,1] == '/' ? ryyequest.path.chop : request.path)
678
696
 
679
697
  if path == '/model' and request.query.has_key?('model')
680
- status, content_type, body = self.set_model({:query => request.query})
698
+ status, content_type, body = self.set_model({:model => request.query['model']})
681
699
 
682
700
  elsif path =~ /\/model\/cache\/.+/ and request.query.length > 0
683
- status, content_type, body = self.set_cache_model({:name => path[13, path.length-13],
684
- :query => request.query})
701
+ status, content_type, body = self.manage_cache_model({:set => true,
702
+ :name => path[13, path.length-13],
703
+ :model => request.query['model']})
685
704
 
686
705
  elsif path =~ /\/modules\/.+/ and request.query.length > 0
687
- status, content_type, body = self.manage_modules({:name => path[9, path.length-9],
688
- :query => request.query})
706
+ status, content_type, body = self.manage_modules({:install => true,
707
+ :name => path[9, path.length-9],
708
+ :module => request.query['module']})
689
709
 
690
710
  elsif path == '/modules' and request.query.length > 0
691
- status, content_type, body = self.manage_modules({:query => request.query})
711
+ status, content_type, body = self.manage_modules({:install => true,
712
+ :modules => request.query})
692
713
 
693
714
  elsif path == '/agents' and request.query.has_key?('agents')
694
- status, content_type, body = self.set_agents({:query => request.query})
715
+ status, content_type, body = self.manage_agents({:set => true,
716
+ :agents => request.query['agents']})
695
717
 
696
718
  elsif path == '/bsig' and request.query.has_key?('bsig')
697
719
  status, content_type, body = self.set_bsig({:query => request.query})
@@ -707,14 +729,17 @@ module Sfp
707
729
  response.body = body
708
730
  end
709
731
 
710
- # Handle HTTP Put request
732
+ # Handle HTTP Delete request
711
733
  #
712
734
  # uri:
713
- # /model => delete existing model
714
- # /modules => delete a module with name specified in parameter "module", or
715
- # delete all modules if parameter "module" is not provided
716
- # /agents => delete agents database
717
- # /bsig => delete existing BSig model
735
+ # /model => delete existing model
736
+ # /model/cache => delete all cache models
737
+ # /model/cache/name => delete cache model of agent "name"
738
+ # /modules => delete all modules from module database
739
+ # /modules/name => delete module "name" from module database
740
+ # /agents => delete all agents from agent database
741
+ # /agents/name => delete "name" from agent database
742
+ # /bsig => delete existing BSig model
718
743
  #
719
744
  def do_DELETE(request, response)
720
745
  status = 400
@@ -728,19 +753,19 @@ module Sfp
728
753
  status, content_type, body = self.set_model
729
754
 
730
755
  elsif path == '/model/cache'
731
- status, content_type, body = self.set_cache_model
756
+ status, content_type, body = self.manage_cache_model({:delete => true, :name => :all})
732
757
 
733
758
  elsif path =~ /\/model\/cache\/.+/
734
- status, content_type, body = self.set_cache_model({:name => path[13, path.length-13]})
759
+ status, content_type, body = self.manage_cache_model({:delete => true, :name => path[13, path.length-13]})
735
760
 
736
761
  elsif path == '/modules'
737
- status, content_type, body = self.manage_modules({:deleteall => true})
762
+ status, content_type, body = self.manage_modules({:uninstall => true, :name => :all})
738
763
 
739
764
  elsif path =~ /\/modules\/.+/
740
- status, content_type, body = self.manage_modules({:name => path[9, path.length-9]})
765
+ status, content_type, body = self.manage_modules({:uninstall => true, :name => path[9, path.length-9]})
741
766
 
742
767
  elsif path == '/agents'
743
- status, content_type, body = self.set_agents
768
+ status, content_type, body = self.manage_agents({:delete => true, :name => :all})
744
769
 
745
770
  elsif path == '/bsig'
746
771
  status, content_type, body = self.set_bsig
@@ -750,12 +775,18 @@ module Sfp
750
775
  end
751
776
  end
752
777
 
753
- def set_agents(p={})
778
+ def manage_agents(p={})
754
779
  begin
755
- if p[:query] and p[:query].has_key?('agents')
756
- return [200, '', ''] if Sfp::Agent.set_agents(JSON[p[:query]['agents']])
757
- else
758
- return [200, '', ''] if Sfp::Agent.set_agents({})
780
+ if p[:delete]
781
+ if p[:name] == :all
782
+ return [200, '', ''] if Sfp::Agent.delete_agents
783
+ elsif p[:name] != ''
784
+ return [200, '', ''] if Sfp::Agent.set_agents({p[:name] => nil})
785
+ else
786
+ return [400, '', '']
787
+ end
788
+ elsif p[:set]
789
+ return [200, '', ''] if Sfp::Agent.set_agents(JSON[p[:agents]])
759
790
  end
760
791
  rescue Exception => e
761
792
  @logger.error "Saving agents list [Failed]\n#{e}\n#{e.backtrace.join("\n")}"
@@ -764,18 +795,23 @@ module Sfp
764
795
  end
765
796
 
766
797
  def manage_modules(p={})
767
- if p[:name]
768
- if p[:query]
769
- return [200, '', ''] if Sfp::Agent.install_module(p[:name], p[:query]['module'])
798
+ if p[:install]
799
+ if p[:name] and p[:module]
800
+ return [200, '', ''] if Sfp::Agent.install_module(p[:name], p[:module])
801
+ elsif p[:modules]
802
+ return [200, '', ''] if Sfp::Agent.install_modules(p[:modules])
770
803
  else
804
+ return [400, '', '']
805
+ end
806
+ elsif p[:uninstall]
807
+ if p[:name] == :all
808
+ return [200, '', ''] if Sfp::Agent.uninstall_all_modules
809
+ elsif p[:name] != ''
771
810
  return [200, '', ''] if Sfp::Agent.uninstall_module(p[:name])
811
+ else
812
+ return [400, '', '']
772
813
  end
773
- elsif p[:query].length > 0
774
- return [200, '', ''] if Sfp::Agent.install_modules(p[:query])
775
- else
776
- return [200, '', ''] if Sfp::Agent.uninstall_all_modules
777
814
  end
778
-
779
815
  [500, '', '']
780
816
  end
781
817
 
@@ -788,19 +824,22 @@ module Sfp
788
824
  end
789
825
  end
790
826
 
791
- def set_cache_model(p={})
792
- p[:model] = JSON[p[:query]['model']] if p[:query].is_a?(Hash) and p[:query]['model']
793
-
794
- if p[:name]
827
+ def manage_cache_model(p={})
828
+ if p[:set] and p[:name] and p[:model]
829
+ p[:model] = JSON[p[:model]]
795
830
  return [200, '', ''] if Sfp::Agent.set_cache_model(p)
831
+ elsif p[:delete] and p[:name]
832
+ if p[:name] == :all
833
+ return [200, '', ''] if Sfp::Agent.set_cache_model
834
+ else
835
+ return [200, '', ''] if Sfp::Agent.set_cache_model({:name => p[:name]})
836
+ end
796
837
  else
797
- return [200, '', ''] if Sfp::Agent.set_cache_model
838
+ return [400, '', '']
798
839
  end
799
-
800
840
  [500, '', '']
801
841
  end
802
842
 
803
-
804
843
  def get_sfp(p={})
805
844
  begin
806
845
  module_name, _ = p[:module].split('/', 2)
@@ -827,9 +866,9 @@ module Sfp
827
866
  end
828
867
 
829
868
  def set_model(p={})
830
- if p[:query] and p[:query].has_key?('model')
869
+ if p[:model]
831
870
  # If setting the model was success, then return '200' status.
832
- return [200, '', ''] if Sfp::Agent.set_model(JSON[p[:query]['model']])
871
+ return [200, '', ''] if Sfp::Agent.set_model(JSON[p[:model]])
833
872
  else
834
873
  # Removing the existing model by setting an empty model, if it's success then return '200' status.
835
874
  return [200, '', ''] if Sfp::Agent.set_model({})
data/lib/sfpagent/bsig.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  require 'thread'
2
2
 
3
3
  class Sfp::BSig
4
- include Sfp::Net::Helper
4
+ include Sfp::Helper::Net
5
5
 
6
6
  SleepTime = 5
7
7
  MaxTries = 5
@@ -108,8 +108,8 @@ class Sfp::BSig
108
108
  operator = select_operator(flaws, operators, pi)
109
109
  return :failure if operator.nil?
110
110
 
111
- # debugging
112
- #Sfp::Agent.logger.info "[#{mode}] Flaws: #{JSON.generate(flaws)}"
111
+ # debugging
112
+ #Sfp::Agent.logger.info "[#{mode}] Flaws: #{JSON.generate(flaws)}"
113
113
 
114
114
  return :ongoing if not lock_operator(operator)
115
115
 
@@ -118,8 +118,8 @@ class Sfp::BSig
118
118
  next_pi = operator['pi'] + 1
119
119
  pre_local, pre_remote = split_preconditions(operator)
120
120
 
121
- # debugging
122
- #Sfp::Agent.logger.info "[#{mode}] local-flaws: #{JSON.generate(pre_local)}, remote-flaws: #{JSON.generate(pre_remote)}"
121
+ # debugging
122
+ #Sfp::Agent.logger.info "[#{mode}] local-flaws: #{JSON.generate(pre_local)}, remote-flaws: #{JSON.generate(pre_remote)}"
123
123
 
124
124
  status = nil
125
125
  tries = MaxTries
@@ -149,7 +149,6 @@ class Sfp::BSig
149
149
  end
150
150
 
151
151
  def achieve_remote_goal(id, goal, pi, mode)
152
-
153
152
  if goal.length > 0
154
153
  agents = Sfp::Agent.get_agents
155
154
  split_goal_by_agent(goal).each do |agent_name,agent_goal|
@@ -161,6 +160,7 @@ class Sfp::BSig
161
160
  end
162
161
  end
163
162
  end
163
+
164
164
  true
165
165
  end
166
166
 
@@ -178,7 +178,6 @@ class Sfp::BSig
178
178
  return false if not @enabled
179
179
 
180
180
  bsig = Sfp::Agent.get_bsig
181
-
182
181
  return false if bsig.nil? or id < bsig['id']
183
182
 
184
183
  status = nil
@@ -242,38 +241,67 @@ class Sfp::BSig
242
241
  end
243
242
 
244
243
  def split_goal_by_agent(goal)
245
- #agents = Sfp::Agent.get_agents
246
244
  agent_goal = {}
247
245
  goal.each { |var,val|
248
246
  _, agent_name, _ = var.split('.', 3)
249
- #fail "Agent #{agent_name} is not in database!" if not agents.has_key?(agent_name)
250
247
  agent_goal[agent_name] = {} if not agent_goal.has_key?(agent_name)
251
248
  agent_goal[agent_name][var] = val
252
249
  }
253
250
  agent_goal
254
251
  end
255
252
 
256
- def send_goal_to_agent(agent, id, g, pi, agent_name='', mode)
253
+ def send_goal_to_agent(agent, id, goal, pi, agent_name='', mode)
257
254
  begin
258
255
  data = {'id' => id,
259
- 'goal' => JSON.generate(g),
256
+ 'goal' => JSON.generate(goal),
260
257
  'pi' => pi}
261
-
262
258
  Sfp::Agent.logger.info "[#{mode}] Request goal to: #{agent_name} [WAIT]"
263
-
264
259
  code, _ = put_data(agent['sfpAddress'], agent['sfpPort'], SatisfierPath, data)
265
-
266
260
  Sfp::Agent.logger.info "[#{mode}] Request goal to: #{agent_name} - status: #{code}"
267
-
268
261
  (code == '200')
269
262
  rescue
263
+ return true if check_not_created_agent(agent_name, goal)
270
264
  false
271
265
  end
272
266
  end
273
267
 
268
+ def check_not_created_agent(agent_name, goal)
269
+ state = Sfp::Agent.get_state
270
+ vms = {}
271
+ Sfp::Agent.runtime.cloudfinder.clouds.each { |cloud|
272
+ cloud.sub!(/^\$\./, '')
273
+ cloud_ref = "$.#{Sfp::Agent.whoami?}.#{cloud}"
274
+ ref = "#{cloud_ref}.vms"
275
+ vms = state.at?(ref)
276
+ vms.each { |name,status| vms[name] = {'created' => true} } if vms.is_a?(Hash)
277
+ }
278
+ if not vms.has_key?(agent_name)
279
+ state = {agent_name => {'created' => false, 'in_cloud' => nil}}
280
+ goal.each { |var,val| return false if state.at?(var) != val }
281
+ return true
282
+ end
283
+ false
284
+ end
285
+
274
286
  def get_current_state
275
287
  state = Sfp::Agent.get_state
276
288
  fail "BSig engine cannot get current state" if state == false
289
+
290
+ Sfp::Agent.runtime.cloudfinder.clouds.each { |cloud|
291
+ cloud.sub!(/^\$\./, '')
292
+ cloud_ref = "$.#{Sfp::Agent.whoami?}.#{cloud}"
293
+ ref = "#{cloud_ref}.vms"
294
+ vms = state.at?(ref)
295
+ if vms.is_a?(Hash)
296
+ vms.each { |name,status|
297
+ state[name] = { 'created' => true,
298
+ 'in_cloud' => cloud_ref,
299
+ 'sfpAddress' => status['ip'],
300
+ 'sfpPort' => Sfp::Agent::DefaultPort }
301
+ }
302
+ end
303
+ }
304
+
277
305
  state
278
306
  end
279
307
 
@@ -281,13 +309,14 @@ class Sfp::BSig
281
309
  return goal.clone if current.nil?
282
310
  flaws = {}
283
311
  goal.each { |var,val|
284
- _, agent_name, _ = var.split('.', 3)
285
- if agent_name != Sfp::Agent.whoami?
286
- current_value = Sfp::Resource.resolve(var)
287
- else
288
- current_value = current.at?(var)
312
+ current_value = current.at?(var)
313
+ if current_value.is_a?(Sfp::Unknown)
314
+ _, agent_name, _ = var.split('.', 3)
315
+ if agent_name != Sfp::Agent.whoami?
316
+ s = {agent_name => {'created' => false, 'in_cloud' => nil}}
317
+ current_value = s.at?(var)
318
+ end
289
319
  end
290
-
291
320
  if current_value.is_a?(Sfp::Undefined)
292
321
  flaws[var] = val if not val.is_a?(Sfp::Undefined)
293
322
  else
@@ -359,7 +388,7 @@ class Sfp::BSig
359
388
  @lock_postprocess.synchronize {
360
389
  _, agent_name, _ = operator['name'].split('.', 3)
361
390
 
362
- Sfp::Agent.logger.info "Postprocess delete VM #{agent_name}"
391
+ Sfp::Agent.logger.info "Postprocess delete VM #{agent_name}"
363
392
 
364
393
  # update agents database (automatically broadcast to other agents)
365
394
  Sfp::Agent.set_agents({agent_name => nil})
@@ -373,7 +402,7 @@ Sfp::Agent.logger.info "Postprocess delete VM #{agent_name}"
373
402
 
374
403
  _, agent_name, _ = operator['parameters']['$.vm'].split('.', 3)
375
404
 
376
- Sfp::Agent.logger.info "Postprocess create VM #{agent_name}"
405
+ Sfp::Agent.logger.info "Postprocess create VM #{agent_name}"
377
406
 
378
407
  # update proxy component's state
379
408
  state = Sfp::Agent.get_state
@@ -390,6 +419,8 @@ Sfp::Agent.logger.info "Postprocess create VM #{agent_name}"
390
419
  # get new agent's model and BSig model from cache database
391
420
  model = Sfp::Agent.get_cache_model(agent_name)
392
421
  model['model']['in_cloud'] = refs[0..-2].join('.')
422
+ model['model']['sfpAddress'] = vms[agent_name]['ip']
423
+ model['model']['sfpPort'] = Sfp::Agent::DefaultPort
393
424
 
394
425
  if not model.nil?
395
426
  address = data[agent_name]['sfpAddress']
@@ -467,20 +498,4 @@ Sfp::Agent.logger.info "Postprocess create VM #{agent_name}"
467
498
 
468
499
  end
469
500
 
470
- module Sfp::Helper
471
- end
472
-
473
- class Sfp::Helper::SchemaCollector
474
- attr_reader :schemata
475
- def initialize
476
- @schemata = []
477
- end
478
-
479
- def visit(name, value, parent)
480
- if value.is_a?(Hash) and value.has_key?('_classes')
481
- value['_classes'].each { |s| @schemata << s }
482
- end
483
- true
484
- end
485
- end
486
501
 
@@ -0,0 +1,96 @@
1
+ module Sfp::Helper
2
+ end
3
+
4
+ module Sfp::Helper::Net
5
+ def post_data(address, port, path, data, open_timeout=5, read_timeout=1800)
6
+ uri = create_uri(address, port, path)
7
+ req = Net::HTTP::Post.new(uri.path)
8
+ req.set_form_data(data)
9
+ http_request(uri, req, open_timeout, read_timeout)
10
+ end
11
+
12
+ def put_data(address, port, path, data, open_timeout=5, read_timeout=1800)
13
+ uri = create_uri(address, port, path)
14
+ req = Net::HTTP::Put.new(uri.path)
15
+ req.set_form_data(data)
16
+ http_request(uri, req, open_timeout, read_timeout)
17
+ end
18
+
19
+ def get_data(address, port, path, open_timeout=5, read_timeout=1800)
20
+ uri = create_uri(address, port, path)
21
+ req = Net::HTTP::Get.new(uri.path)
22
+ http_request(uri, req, open_timeout, read_timeout)
23
+ end
24
+
25
+ def delete_data(address, port, path, open_timeout=5, read_timeout=1800)
26
+ uri = create_uri(address, port, path)
27
+ req = Net::HTTP::Delete.new(uri.path)
28
+ http_request(uri, req, open_timeout, read_timeout)
29
+ end
30
+
31
+ private
32
+ def create_uri(address, port, path)
33
+ address = address.to_s.strip
34
+ port = port.to_s.strip
35
+ path = path.to_s.strip
36
+ raise Exception, "Invalid parameters [address:#{address},port:#{port},path:#{path}]" if
37
+ address.length <= 0 or port.length <= 0 or path.length <= 0
38
+ path.sub!(/^\/+/, '')
39
+ URI.parse("http://#{address}:#{port}/#{path}")
40
+ end
41
+
42
+ def use_http_proxy?(uri)
43
+ ENV['no_proxy'].to_s.split(',').each { |pattern|
44
+ pattern.chop! if pattern[-1] == '*'
45
+ return false if uri.host[0,pattern.length] == pattern
46
+ }
47
+ true
48
+ end
49
+
50
+ def http_request(uri, request, open_timeout=5, read_timeout=1800)
51
+ if ENV['http_proxy'].to_s.strip != '' and use_http_proxy?(uri)
52
+ proxy = URI.parse(ENV['http_proxy'])
53
+ http = Net::HTTP::Proxy(proxy.host, proxy.port).new(uri.host, uri.port)
54
+ else
55
+ http = Net::HTTP.new(uri.host, uri.port)
56
+ end
57
+ http.open_timeout = open_timeout
58
+ http.read_timeout = read_timeout
59
+ http.start
60
+ http.request(request) { |res| return [res.code, res.body] }
61
+ end
62
+ end
63
+
64
+ class Sfp::Helper::SchemaCollector
65
+ attr_reader :schemata
66
+ def initialize
67
+ @schemata = []
68
+ end
69
+
70
+ def visit(name, value, parent)
71
+ if value.is_a?(Hash) and value.has_key?('_classes')
72
+ value['_classes'].each { |s| @schemata << s }
73
+ end
74
+ true
75
+ end
76
+ end
77
+
78
+ class Sfp::Helper::CloudFinder
79
+ CloudSchema = '$.Cloud'
80
+ attr_accessor :clouds
81
+
82
+ def reset
83
+ @clouds = []
84
+ self
85
+ end
86
+
87
+ def visit(name, value, parent)
88
+ if value.is_a?(Hash)
89
+ if value['_context'] == 'object'
90
+ @clouds << parent.ref.push(name) if value.has_key?('_classes') and value['_classes'].index(CloudSchema)
91
+ return true
92
+ end
93
+ end
94
+ false
95
+ end
96
+ end
@@ -1,12 +1,13 @@
1
1
  require 'thread'
2
2
 
3
3
  class Sfp::Runtime
4
- attr_reader :root
4
+ attr_reader :root, :cloudfinder
5
5
 
6
6
  def initialize(model)
7
7
  @mutex_procedure = Mutex.new
8
8
  @mutex_get_state = Mutex.new
9
9
  @root = nil
10
+ @cloudfinder = Sfp::Helper::CloudFinder.new
10
11
  set_model(model)
11
12
  end
12
13
 
@@ -48,6 +49,9 @@ class Sfp::Runtime
48
49
  root_model.accept(ParentEliminator)
49
50
  @root = update_model(root_model, root_model, '$')
50
51
  @root.accept(ParentGenerator)
52
+
53
+ @cloudfinder.clouds = []
54
+ @model.accept(@cloudfinder.reset)
51
55
  end
52
56
  }
53
57
  end
@@ -57,6 +57,34 @@ class Planner
57
57
  end
58
58
 
59
59
  def to_image(p={})
60
+ def self.dot2image(dot, image_file)
61
+ dot_file = "/tmp/#{Time.now.getutc.to_i}.dot"
62
+ File.open(dot_file, 'w') { |f|
63
+ f.write(dot)
64
+ f.flush
65
+ }
66
+ !!system("dot -Tpng -o #{image_file} #{dot_file}")
67
+ ensure
68
+ File.delete(dot_file) if File.exist?(dot_file)
69
+ end
70
+
71
+ dot = "digraph {\n"
72
+ @variables.each do |sym,var|
73
+ name = var.name.gsub(/[\s\.\$]/, '_')
74
+ dot += "#{name} [label=\"#{var.name}\", shape=rect];\n"
75
+ end
76
+ @variables.each do |sym,var|
77
+ name = var.name.gsub(/[\s\.\$]/, '_')
78
+ var.dependencies.each { |sym,operators|
79
+ var2 = @variables[sym]
80
+ name2 = var2.name.gsub(/[\s\.\$]/, '_')
81
+ dot += "#{name} -> #{name2} ;\n"
82
+ }
83
+ end
84
+ dot += "}"
85
+ puts dot
86
+
87
+ dot2image(dot, p[:file])
60
88
  end
61
89
 
62
90
  class Variable < Array
@@ -214,4 +242,7 @@ class Planner
214
242
  end
215
243
  end
216
244
 
217
- Planner.new(:sas => File.read(ARGV[0]))
245
+ if $0 == __FILE__ and ARGV.length > 0
246
+ planner = Planner.new(:sas => File.read(ARGV[0]))
247
+ planner.to_image(:file => 'domain.png')
248
+ end
data/lib/sfpagent.rb CHANGED
@@ -12,7 +12,7 @@ end
12
12
  # internal dependencies
13
13
  libdir = File.expand_path(File.dirname(__FILE__))
14
14
 
15
- require libdir + '/sfpagent/net_helper.rb'
15
+ require libdir + '/sfpagent/helper.rb'
16
16
  require libdir + '/sfpagent/runtime.rb'
17
17
  require libdir + '/sfpagent/module.rb'
18
18
  require libdir + '/sfpagent/bsig.rb'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sfpagent
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.14
4
+ version: 0.2.3
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -13,7 +13,7 @@ date: 2013-08-13 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: sfp
16
- requirement: &13903480 !ruby/object:Gem::Requirement
16
+ requirement: &14891600 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ~>
@@ -21,7 +21,7 @@ dependencies:
21
21
  version: 0.3.12
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *13903480
24
+ version_requirements: *14891600
25
25
  description: A Ruby implementation of SFP agent.
26
26
  email: herry13@gmail.com
27
27
  executables:
@@ -39,8 +39,8 @@ files:
39
39
  - lib/sfpagent.rb
40
40
  - lib/sfpagent/agent.rb
41
41
  - lib/sfpagent/bsig.rb
42
+ - lib/sfpagent/helper.rb
42
43
  - lib/sfpagent/module.rb
43
- - lib/sfpagent/net_helper.rb
44
44
  - lib/sfpagent/runtime.rb
45
45
  - lib/sfpagent/sfplanner.rb
46
46
  - sfpagent.gemspec
@@ -1,56 +0,0 @@
1
- require 'uri'
2
- require 'net/http'
3
-
4
- module Sfp::Net
5
- end
6
-
7
- module Sfp::Net::Helper
8
- def http_request(uri, request, open_timeout=5, read_timeout=1800)
9
- http = Net::HTTP.new(uri.host, uri.port)
10
- http.open_timeout = open_timeout
11
- http.read_timeout = read_timeout
12
- http.start
13
- http.request(request) { |res| return [res.code, res.body] }
14
- end
15
-
16
- def post_data(address, port, path, data, open_timeout=5, read_timeout=1800)
17
- address = address.to_s.strip
18
- port = port.to_s.strip
19
- path = path.to_s.strip
20
- raise Exception, "Invalid parameters [address:#{address},port:#{port},path:#{path}]" if
21
- address.length <= 0 or port.length <= 0 or path.length <= 0
22
-
23
- path.sub!(/^\/+/, '')
24
- url = URI.parse("http://#{address}:#{port}/#{path}")
25
- req = Net::HTTP::Post.new(url.path)
26
- req.set_form_data(data)
27
- http_request(url, req, open_timeout, read_timeout)
28
- end
29
-
30
- def put_data(address, port, path, data, open_timeout=5, read_timeout=1800)
31
- address = address.to_s.strip
32
- port = port.to_s.strip
33
- path = path.to_s.strip
34
- raise Exception, "Invalid parameters [address:#{address},port:#{port},path:#{path}]" if
35
- address.length <= 0 or port.length <= 0 or path.length <= 0
36
-
37
- path.sub!(/^\/+/, '')
38
- url = URI.parse("http://#{address}:#{port}/#{path}")
39
- req = Net::HTTP::Put.new(url.path)
40
- req.set_form_data(data)
41
- http_request(url, req, open_timeout, read_timeout)
42
- end
43
-
44
- def get_data(address, port, path, open_timeout=5, read_timeout=1800)
45
- address = address.to_s.strip
46
- port = port.to_s.strip
47
- path = path.to_s.strip
48
- raise Exception, "Invalid parameters [address:#{address},port:#{port},path:#{path}]" if
49
- address.length <= 0 or port.length <= 0 or path.length <= 0
50
-
51
- path.sub!(/^\/+/, '')
52
- url = URI.parse("http://#{address}:#{port}/#{path}")
53
- req = Net::HTTP::Get.new(url.path)
54
- http_request(url, req, open_timeout, read_timeout)
55
- end
56
- end