sfp 0.2.1 → 0.3.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/lib/sfp/Sfplib.rb CHANGED
@@ -82,6 +82,13 @@ module Sfp
82
82
  c.inherits( sclass )
83
83
  c['_super'] = (sclass.has_key?('_super') ? sclass['_super'].clone : Array.new)
84
84
  c['_super'] << c['_extends']
85
+ if sclass['_finals'].is_a?(Array)
86
+ if c['_finals'].is_a?(Array)
87
+ c['_finals'].concat(sclass['_finals'])
88
+ else
89
+ c['_finals'] = sclass['_finals']
90
+ end
91
+ end
85
92
  }
86
93
  end
87
94
 
@@ -91,22 +98,7 @@ module Sfp
91
98
  end
92
99
 
93
100
  def deep_clone(value)
94
- if value.is_a?(Hash)
95
- result = value.clone
96
- value.each { |k,v|
97
- if k != '_parent'
98
- result[k] = deep_clone(v)
99
- result[k]['_parent'] = result if result[k].is_a?(Hash) and result[k].has_key?('_parent')
100
- end
101
- }
102
- result
103
- elsif value.is_a?(Array)
104
- result = Array.new
105
- value.each { |v| result << deep_clone(v) }
106
- result
107
- else
108
- value
109
- end
101
+ Sfp::Helper.deep_clone(value)
110
102
  end
111
103
  end
112
104
 
@@ -147,11 +139,20 @@ module Sfp
147
139
  not obj.has_key?('_isa') or obj['_isa'] == nil
148
140
  objclass = root.at?(obj['_isa'])
149
141
  if objclass.nil? or objclass.is_a?(Sfp::Unknown) or objclass.is_a?(Sfp::Undefined)
150
- raise Exception, 'Super class is not found: ' + obj['_self'] + ' < ' + obj['_isa']
142
+ raise Exception, "Schema #{obj['_isa']} of object #{obj['_self']} is not found!"
151
143
  end
152
144
  obj.inherits( objclass )
153
145
  obj['_classes'] = (objclass.has_key?('_super') ? objclass['_super'].clone : Array.new)
154
146
  obj['_classes'] << obj['_isa']
147
+
148
+ if objclass['_finals'].is_a?(Array)
149
+ if obj['_finals'].is_a?(Array)
150
+ obj['_finals'].concat(objclass['_finals'])
151
+ else
152
+ obj['_finals'] = objclass['_finals']
153
+ end
154
+ end
155
+
155
156
  return true
156
157
  end
157
158
  end
@@ -163,9 +164,14 @@ module Sfp
163
164
 
164
165
  # Instance of this class will be returned as the value of a non-exist variable
165
166
  class Undefined
166
- attr_accessor :path
167
- def initialize(path=nil); @path = path; end
168
- def to_s; (@path.nil? ? "<sfp::undefined>" : "<sfp::undefined[#{@path}]>"); end
167
+ attr_accessor :path, :type
168
+ def initialize(path=nil, type=nil)
169
+ @path = path
170
+ @type = type
171
+ end
172
+ def to_s
173
+ (@path.nil? ? "<sfp::undefined>" : "<sfp::undefined[#{@path}]>")
174
+ end
169
175
  end
170
176
 
171
177
  # Instance of this class will be return as the value of an unknown variable
@@ -175,6 +181,10 @@ module Sfp
175
181
  def initialize(path=nil); @path = path; end
176
182
  def to_s; (@path.nil? ? "<sfp::unknown>" : "<sfp::unknown[#{@path}]>"); end
177
183
  end
184
+
185
+ class Any
186
+ def to_s; '<sfp::any>'; end
187
+ end
178
188
  end
179
189
 
180
190
  # return a fullpath of reference of this context
data/lib/sfp/parser.rb CHANGED
@@ -6,6 +6,7 @@ module Sfp
6
6
  include Sfp::SasTranslator
7
7
 
8
8
  attr_accessor :root_dir, :home_dir, :conformant
9
+ attr_reader :root
9
10
 
10
11
  def initialize(params={})
11
12
  @root_dir = (params[:root_dir].is_a?(String) ?
@@ -31,6 +32,19 @@ module Sfp
31
32
  @parser_arrays = parser.arrays
32
33
  end
33
34
 
35
+ def to_json(params={})
36
+ return 'null' if @root.nil?
37
+ return Sfp::Helper.to_pretty_json(@root) if params[:pretty]
38
+ return Sfp::Helper.to_json(@root)
39
+ end
40
+
41
+ def self.parse_file(filepath)
42
+ homedir = File.expand_path(File.dirname(filepath))
43
+ parser = Sfp::Parser.new({:home_dir => homedir})
44
+ parser.parse(File.read(filepath))
45
+ parser.root
46
+ end
47
+
34
48
  =begin
35
49
  # Parse SFP file and return its JSON representation
36
50
  def self.parse_file(file)
@@ -103,12 +117,6 @@ module Sfp
103
117
  return Nuri::Sfp.to_json(root)
104
118
  end
105
119
  =end
106
-
107
- def to_json(params={})
108
- return '' if @root.nil?
109
- return Sfp::Helper.to_pretty_json(@root) if params[:pretty]
110
- return Sfp::Helper.to_json(@root)
111
- end
112
120
  end
113
121
 
114
122
  =begin
@@ -1346,7 +1346,7 @@ module Sfp
1346
1346
  value = @init.at?(value) if isref
1347
1347
  type = (isfinal ? self.isa?(value) : self.get_type(name, value, parent))
1348
1348
  if type == nil
1349
- raise Exception, "Unrecognized type of variable: #{var_name}"
1349
+ raise Exception, "Unrecognized type of variable: #{var_name}:#{value.class}"
1350
1350
  else
1351
1351
  value = null_value(type) if value == nil
1352
1352
  isset = true if type[0,1] == '('
@@ -1375,6 +1375,8 @@ module Sfp
1375
1375
  return type if type != nil
1376
1376
  end
1377
1377
  =end
1378
+ return value.type if value.is_a?(Sfp::Undefined)
1379
+
1378
1380
  type = nil
1379
1381
  if parent.has_key?('_isa')
1380
1382
  isa = @main.root.at?(parent['_isa'])
data/lib/sfp.rb CHANGED
@@ -14,8 +14,3 @@ require libdir + '/sfp/SfpLangLexer'
14
14
  require libdir + '/sfp/visitors'
15
15
  require libdir + '/sfp/sas_translator'
16
16
  require libdir + '/sfp/parser'
17
-
18
- require libdir + '/sfp/sas'
19
- require libdir + '/sfp/planner'
20
-
21
- require libdir + '/sfp/executor.rb'
data/sfp.gemspec CHANGED
@@ -1,23 +1,17 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'sfp'
3
- s.version = '0.2.1'
4
- s.date = '2013-05-15'
5
- s.summary = 'SFP Parser and Planner'
6
- s.description = 'A Ruby gem that provides a Ruby API to SFP language parser and ' +
7
- 'SFP planner. It also provides a planner sript to solve a planning problem ' +
8
- 'written in SFP language.'
3
+ s.version = '0.3.4'
4
+ s.date = '2013-07-14'
5
+ s.summary = 'SFP Parser'
6
+ s.description = 'A Ruby API and script for SFP language parser'
9
7
  s.authors = ['Herry']
10
8
  s.email = 'herry13@gmail.com'
11
9
 
12
10
  s.executables << 'sfp'
13
- s.files = `git ls-files`.split("\n")
14
- s.test_files = `git ls-files -- test/*`.split("\n")
15
-
16
- s.files.delete_if { |f| f =~ /linux\-arm/ }
17
-
18
- `git ls-files --exclude=bin/solver/linux-arm/* -- bin/*`.split("\n") { |f| s.executables << f }
11
+ s.files = `git ls-files`.split("\n").select { |n| !(n =~ /^test\/.*/) }
19
12
 
20
13
  s.require_paths = ['lib']
14
+ s.license = 'BSD'
21
15
 
22
16
  s.homepage = 'https://github.com/herry13/sfp-ruby'
23
17
  s.rubyforge_project = 'sfp'
data/src/SfpLang.g CHANGED
@@ -40,11 +40,11 @@ sfp
40
40
  : { self.init }
41
41
  NL* include* header*
42
42
  { self.expand_classes }
43
- (mmutation | object_def NL* | state | constraint | goal_constraint | composite)*
43
+ (object_def NL* | state | constraint | goal_constraint | composite)*
44
44
  ;
45
45
 
46
46
 
47
- mmutation
47
+ /*mmutation
48
48
  : reference equals_op value NL+
49
49
  {
50
50
  path, var = $reference.val.extract
@@ -60,6 +60,7 @@ mmutation
60
60
  parent[var] = self.null_value
61
61
  }
62
62
  ;
63
+ */
63
64
 
64
65
  include
65
66
  : 'include' include_file NL+
@@ -136,6 +137,17 @@ extends_class returns [val]
136
137
  ;
137
138
 
138
139
  attribute
140
+ : {
141
+ @is_final = false
142
+ @now['_finals'] = [] if !@now.has_key? '_finals'
143
+ }
144
+ ('final' { @is_final = true })? attribute_stmt
145
+ {
146
+ @now['_finals'] << $attribute_stmt.id if @is_final and !$attribute_stmt.id.nil?
147
+ }
148
+ ;
149
+
150
+ attribute_stmt returns [id]
139
151
  : ID equals_op value NL+
140
152
  {
141
153
  if @now.has_key?($ID.text) and @now[$ID.text].is_a?(Hash) and
@@ -144,11 +156,18 @@ attribute
144
156
  else
145
157
  @now[$ID.text] = $value.val
146
158
  end
159
+ $id = $ID.text
147
160
  }
148
161
  | ID reference_type NL+
149
- { @now[$ID.text] = $reference_type.val }
162
+ {
163
+ @now[$ID.text] = $reference_type.val
164
+ $id = $ID.text
165
+ }
150
166
  | ID set_type NL+
151
- { @now[$ID.text] = $set_type.val }
167
+ {
168
+ @now[$ID.text] = $set_type.val
169
+ $id = $ID.text
170
+ }
152
171
  | ID probability_op set_value NL+
153
172
  {
154
173
  @conformant = true
@@ -157,27 +176,72 @@ attribute
157
176
  '_parent' => @now,
158
177
  '_values' => $set_value.val
159
178
  }
179
+ $id = $ID.text
180
+ }
181
+ | ID ':' path NL+
182
+ {
183
+ case $path.text
184
+ when 'String'
185
+ @now[$ID.text] = { '_context' => 'any_value',
186
+ '_isa' => '$.String'
187
+ }
188
+ when 'Bool'
189
+ @now[$ID.text] = { '_context' => 'any_value',
190
+ '_isa' => '$.Boolean'
191
+ }
192
+ when 'Int'
193
+ @now[$ID.text] = { '_context' => 'any_value',
194
+ '_isa' => '$.Number'
195
+ }
196
+ else
197
+ raise Exception, "Use isa/isref for any non-primitive type (#{$path.text})."
198
+ end
199
+ $id = $ID.text
160
200
  }
161
201
  | object_def NL+
202
+ { $id = nil }
203
+ ;
204
+
205
+ object_schema
206
+ : path('[' NUMBER { @now['_is_array'] = true } ']')?
207
+ {
208
+ @now['_isa'] = self.to_ref($path.text)
209
+ self.expand_object(@now)
210
+ }
211
+ ;
212
+
213
+ object_schemata
214
+ : ',' object_schema
162
215
  ;
163
216
 
164
217
  object_def
165
- : ID
218
+ : { @use_template = false }
219
+ ID
220
+ ('extends' path
221
+ {
222
+ template = @root.at?($path.text)
223
+ raise Exception, "Object template #{$path.text} is not found!" if
224
+ template.is_a?(Sfp::Unknown) or template.is_a?(Sfp::Undefined)
225
+ raise Exception, "#{$path.text} is not an object!" if
226
+ !template.is_a?(Hash) or template['_context'] != 'object'
227
+ @now[$ID.text] = Sfp::Helper.deep_clone(template)
228
+ @now[$ID.text].accept(Sfp::Visitor::ParentEliminator.new)
229
+ @now[$ID.text]['_parent'] = @now
230
+ @now[$ID.text]['_self'] = $ID.text
231
+ @now[$ID.text].accept(Sfp::Visitor::SfpGenerator.new(@root))
232
+ @use_template = true
233
+ }
234
+ )?
166
235
  {
167
236
  @now[$ID.text] = { '_self' => $ID.text,
168
237
  '_context' => 'object',
169
238
  '_parent' => @now,
170
239
  '_isa' => '$.Object'
171
- }
240
+ } if not @use_template
172
241
  @now = @now[$ID.text]
173
242
  @now['_is_array'] = false
174
243
  }
175
- ('isa' path('[' NUMBER { @now['_is_array'] = true } ']')?
176
- {
177
- @now['_isa'] = self.to_ref($path.text)
178
- self.expand_object(@now)
179
- }
180
- )?
244
+ ('isa' object_schema (object_schemata)* )?
181
245
  object_body?
182
246
  {
183
247
  if @now['_is_array']
@@ -280,7 +344,7 @@ op_statement
280
344
  ;
281
345
 
282
346
  procedure
283
- : 'procedure' ID
347
+ : ('procedure'|'sub') ID
284
348
  {
285
349
  @now[$ID.text] = { '_self' => $ID.text,
286
350
  '_context' => 'procedure',
@@ -862,6 +926,11 @@ value returns [val, type]
862
926
  $val = $set_value.val
863
927
  $type = 'Set'
864
928
  }
929
+ | 'any'
930
+ {
931
+ $val = Sfp::Any.new
932
+ $type = 'Any'
933
+ }
865
934
  ;
866
935
 
867
936
  primitive_value returns [val, type]
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sfp
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.3.4
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-05-15 00:00:00.000000000 Z
12
+ date: 2013-07-14 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: json
16
- requirement: &7789060 !ruby/object:Gem::Requirement
16
+ requirement: !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ~>
@@ -21,10 +21,15 @@ dependencies:
21
21
  version: 1.7.5
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *7789060
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: 1.7.5
25
30
  - !ruby/object:Gem::Dependency
26
31
  name: antlr3
27
- requirement: &7788020 !ruby/object:Gem::Requirement
32
+ requirement: !ruby/object:Gem::Requirement
28
33
  none: false
29
34
  requirements:
30
35
  - - ~>
@@ -32,9 +37,13 @@ dependencies:
32
37
  version: 1.8.12
33
38
  type: :runtime
34
39
  prerelease: false
35
- version_requirements: *7788020
36
- description: A Ruby gem that provides a Ruby API to SFP language parser and SFP planner.
37
- It also provides a planner sript to solve a planning problem written in SFP language.
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: 1.8.12
46
+ description: A Ruby API and script for SFP language parser
38
47
  email: herry13@gmail.com
39
48
  executables:
40
49
  - sfp
@@ -45,18 +54,11 @@ files:
45
54
  - LICENSE
46
55
  - README.md
47
56
  - bin/sfp
48
- - bin/solver/linux-x86/downward
49
- - bin/solver/linux-x86/preprocess
50
- - bin/solver/macos/downward
51
- - bin/solver/macos/preprocess
52
57
  - lib/sfp.rb
53
58
  - lib/sfp/SfpLangLexer.rb
54
59
  - lib/sfp/SfpLangParser.rb
55
60
  - lib/sfp/Sfplib.rb
56
- - lib/sfp/executor.rb
57
61
  - lib/sfp/parser.rb
58
- - lib/sfp/planner.rb
59
- - lib/sfp/sas.rb
60
62
  - lib/sfp/sas_translator.rb
61
63
  - lib/sfp/sfw2graph.rb
62
64
  - lib/sfp/trollop.rb
@@ -65,27 +67,9 @@ files:
65
67
  - sfp.gemspec
66
68
  - src/SfpLang.g
67
69
  - src/build.sh
68
- - test/cloud-schemas.sfp
69
- - test/future/test1.sfp
70
- - test/nd-cloud1.sfp
71
- - test/nd-cloud2.sfp
72
- - test/nd-cloud3.sfp
73
- - test/nd-service1.sfp
74
- - test/nd-service2.sfp
75
- - test/run.sh
76
- - test/s.sfp
77
- - test/service-schemas.sfp
78
- - test/test-module1-scripts.tgz
79
- - test/test-module1.sfp
80
- - test/test1.inc
81
- - test/test1.sfp
82
- - test/test2.sfp
83
- - test/test3.inc
84
- - test/test3.sfp
85
- - test/test4.inc
86
- - test/test4.sfp
87
70
  homepage: https://github.com/herry13/sfp-ruby
88
- licenses: []
71
+ licenses:
72
+ - BSD
89
73
  post_install_message:
90
74
  rdoc_options: []
91
75
  require_paths:
@@ -104,27 +88,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
104
88
  version: '0'
105
89
  requirements: []
106
90
  rubyforge_project: sfp
107
- rubygems_version: 1.8.11
91
+ rubygems_version: 1.8.23
108
92
  signing_key:
109
93
  specification_version: 3
110
- summary: SFP Parser and Planner
111
- test_files:
112
- - test/cloud-schemas.sfp
113
- - test/future/test1.sfp
114
- - test/nd-cloud1.sfp
115
- - test/nd-cloud2.sfp
116
- - test/nd-cloud3.sfp
117
- - test/nd-service1.sfp
118
- - test/nd-service2.sfp
119
- - test/run.sh
120
- - test/s.sfp
121
- - test/service-schemas.sfp
122
- - test/test-module1-scripts.tgz
123
- - test/test-module1.sfp
124
- - test/test1.inc
125
- - test/test1.sfp
126
- - test/test2.sfp
127
- - test/test3.inc
128
- - test/test3.sfp
129
- - test/test4.inc
130
- - test/test4.sfp
94
+ summary: SFP Parser
95
+ test_files: []
Binary file
Binary file
Binary file
Binary file
data/lib/sfp/executor.rb DELETED
@@ -1,207 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- require 'json'
4
- require 'thread'
5
-
6
- module Sfp
7
- module Executor
8
- class ExecutionException < Exception; end
9
- class ParallelExecutionException < Exception; end
10
- class SequentialExecutionException < Exception; end
11
-
12
- # @param :plan the plan to be executed
13
- # @param :owner an object that implement the action
14
- # @param :retry number of retries (default: 2) when execution is failed
15
- #
16
- def execute_plan(params={})
17
- if params[:plan].nil? or not params[:plan].is_a?(Hash)
18
- raise ExecutionException, 'Plan is not available.'
19
- elsif params[:plan]['type'].to_s == 'parallel' or
20
- params[:plan][:type].to_s == 'parallel'
21
- return self.execute_parallel_plan(params)
22
- elsif params[:plan]['type'].to_s == 'sequential' or
23
- params[:plan][:type].to_s == 'sequential'
24
- return self.execute_sequential_plan(params)
25
- else
26
- raise ExecutionException, 'Unknown type of plan!'
27
- end
28
- false
29
- end
30
-
31
- # @param :plan the plan to be executed
32
- # @param :owner an object that implement the action
33
- # @param :retry number of retries (default: 2) when execution is failed
34
- #
35
- def execute_parallel_plan(params={})
36
- def assign_action_with_id(id)
37
- thread_id = next_thread_id
38
- action = @actions[id]
39
- action[:executor] = thread_id
40
- self.thread_execute_action(thread_id, action)
41
- end
42
-
43
- def next_thread_id
44
- id = 0
45
- @mutex.synchronize { @thread_id = id = @thread_id + 1 }
46
- id
47
- end
48
-
49
- def action_to_string(action)
50
- "#{action['id']}:#{action['name']}#{JSON.generate(action['parameters'])}"
51
- end
52
-
53
- def thread_execute_action(tid, action)
54
- t = Thread.new {
55
- @mutex.synchronize { @threads << tid }
56
-
57
- while not @failed and not action[:executed]
58
- # execute the action
59
- op_str = action_to_string(action)
60
- #Nuri::Util.puts "[ExecutorThread: #{tid}] #{op_str}"
61
- success = false
62
- num = @retry
63
- begin
64
- success = @owner.execute_action { action }
65
- num -= 1
66
- end while not success and num > 0
67
-
68
- # check if execution failed
69
- if success
70
- next_actions = []
71
- @mutex.synchronize {
72
- # set executed
73
- action[:executed] = true
74
- # select next action to be executed from all predecessor actions
75
- # if each action has not been assigned to any thread yet
76
- if action['successors'].length > 0
77
- action['successors'].each { |id|
78
- if @actions[id][:executor].nil?
79
- predecessors_ok = true
80
- @actions[id]['predecessors'].each { |pid|
81
- predecessors_ok = (predecessors_ok and @actions[pid][:executed])
82
- }
83
- next_actions << id if predecessors_ok
84
- end
85
- }
86
- end
87
- next_actions.each { |id| @actions[id][:executor] = tid }
88
- }
89
- if next_actions.length > 0
90
- # execute next actions
91
- action = @actions[next_actions[0]]
92
- if next_actions.length > 1
93
- for i in 1..(next_actions.length-1)
94
- assign_action_with_id(next_actions[i])
95
- end
96
- end
97
- end
98
-
99
- else
100
- Nuri::Util.error "Failed executing #{op_str}!"
101
- @mutex.synchronize {
102
- @failed = true # set global flag
103
- @actions_failed << action
104
- }
105
- end
106
- end
107
-
108
- @mutex.synchronize { @threads.delete(tid) }
109
- }
110
- end
111
-
112
- if params[:plan].nil? or not params[:plan].is_a?(Hash)
113
- raise ParallelExecutionException, 'Plan is not available.'
114
- elsif params[:plan]['type'].to_s == 'parallel' or
115
- params[:plan][:type].to_s == 'parallel'
116
- else
117
- raise ParallelExecutionException, 'Not a parallel plan.'
118
- end
119
-
120
- @owner = params[:owner]
121
- @retry = (params[:retry].nil? ? 2 : params[:retry].to_i)
122
-
123
- @actions = params[:plan]['workflow']
124
- @actions.sort! { |x,y| x['id'] <=> y['id'] }
125
- @actions.each { |op| op[:executed] = false; op[:executor] = nil; }
126
-
127
- @threads = []
128
- @actions_failed = []
129
- @mutex = Mutex.new
130
- @failed = false
131
- @thread_id = 0
132
-
133
- params[:plan]['init'].each { |op_id| assign_action_with_id(op_id) }
134
-
135
- begin
136
- sleep 1
137
- end while @threads.length > 0
138
-
139
- Nuri::Util.log "Using #{@thread_id} threads in execution."
140
-
141
- return (not @failed)
142
- end
143
-
144
- # @param :plan the plan to be executed
145
- # @param :owner an object that implement the action
146
- # @param :retry number of retries (default: 2) when execution is failed
147
- #
148
- def execute_sequential_plan(params={})
149
- if params[:plan].nil? or not params[:plan].is_a?(Hash)
150
- raise ParallelExecutionException, 'Plan is not available.'
151
- elsif params[:plan]['type'].to_s == 'sequential' or
152
- params[:plan][:type].to_s == 'sequential'
153
- else
154
- raise ParallelExecutionException, 'Not a parallel plan.'
155
- end
156
-
157
- @owner = params[:owner]
158
- @retry = (params[:retry].nil? ? 2 : params[:retry].to_i)
159
- params[:plan]['workflow'].each { |action|
160
- success = false
161
- num = @retry
162
- begin
163
- success, data = @owner.execute_action { action }
164
- puts data.to_s if params[:print_output]
165
- num -= 1
166
- end while not success and num > 0
167
- return false if not success
168
- }
169
- true
170
- end
171
- end
172
-
173
- class RubyExecutor
174
- def execute_plan(params={})
175
- exec = Object.new
176
- exec.extend(Sfp::Executor)
177
- params[:owner] = self
178
- exec.execute_plan(params)
179
- end
180
-
181
- def execute_action
182
- # TODO
183
- action = yield
184
- puts "Exec: #{action.inspect}"
185
- [true, nil]
186
- end
187
- end
188
-
189
- class BashExecutor < RubyExecutor
190
- def execute_action
191
- # TODO
192
- action = yield
193
- module_dir = (ENV.has_key?("SFP_HOME") ? ENV['SFP_HOME'] : ".")
194
- script_path = "#{action['name'].sub!(/^\$\./, '')}"
195
- script_path = "#{module_dir}/#{script_path.gsub!(/\./, '/')}"
196
- cmd = "/bin/bash #{script_path}"
197
- action['parameters'].each { |p| cmd += " '#{p}'" }
198
- begin
199
- data = `#{cmd}`
200
- rescue Exception => exp
201
- $stderr.puts "#{exp}\n#{exp.backtrace}"
202
- [false, nil]
203
- end
204
- [true, data]
205
- end
206
- end
207
- end